diff --git a/BUILD.gn b/BUILD.gn
index 3216b4c..c952580 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -453,13 +453,13 @@
     }
 
     if (enable_nacl) {
-      deps += [ "//components/nacl:nacl_loader_unittests" ]
+      deps += [ "//components/nacl/loader:nacl_loader_unittests" ]
 
       if (is_linux) {
         # TODO(dpranke): Figure out what platforms should actually have this.
         deps += [
-          "//components/nacl:helper_nonsfi",
-          "//components/nacl:nacl_helper",
+          "//components/nacl/loader:helper_nonsfi",
+          "//components/nacl/loader:nacl_helper",
         ]
       }
     }
diff --git a/DEPS b/DEPS
index 1a45f40..a3c3e58 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,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': 'aab16e54cb6ab712b477ed9eed8b9aa52098572c',
+  'skia_revision': '4e4155df100b77d11bd14591c7716743369fde9b',
   # 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': '85106b6fe0060a4d28dfaa9898c0e736476da14c',
+  'v8_revision': '8311bed8649e1195de0ddeba71f876143c9a7f95',
   # 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.
@@ -51,7 +51,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'd561057f243629474299ee182e0bd86464d41e03',
+  'angle_revision': '457f1d929e5fd911e0ad9ea53db43010dfae0662',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -145,7 +145,7 @@
     Var('chromium_git') + '/external/snappy.git' + '@' + '762bb32f0c9d2f31ba4958c7c0933d22e80c20bf',
 
   'src/tools/gyp':
-    Var('chromium_git') + '/external/gyp.git' + '@' + '70ee80e82bacf2d7816a56f792bb33587b04c338',
+    Var('chromium_git') + '/external/gyp.git' + '@' + 'b85ad3e578da830377dbc1843aa4fbc5af17a192',
 
   'src/tools/swarming_client':
    Var('chromium_git') + '/external/swarming.client.git' + '@' +  Var('swarming_revision'),
@@ -444,7 +444,7 @@
      Var('chromium_git') + '/chromium/deps/findbugs.git' + '@' + '57f05238d3ac77ea0a194813d3065dd780c6e566',
 
     'src/third_party/freetype-android/src':
-     Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + '66cf29b1bc869b44863b0de2115bd017dfcce849',
+     Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + 'a512b0fe7a8d9db0e5aa9c0a4db1e92cb861722d',
 
    'src/third_party/elfutils/src':
      Var('chromium_git') + '/external/elfutils.git' + '@' + '249673729a7e5dbd5de4f3760bdcaa3d23d154d7',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 6eaddd2..675846f1 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1353,6 +1353,7 @@
     "memory/linked_ptr_unittest.cc",
     "memory/memory_pressure_monitor_chromeos_unittest.cc",
     "memory/memory_pressure_monitor_win_unittest.cc",
+    "memory/ptr_util_unittest.cc",
     "memory/ref_counted_memory_unittest.cc",
     "memory/ref_counted_unittest.cc",
     "memory/scoped_ptr_unittest.cc",
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java
index 485bc82..5d8fa0c 100644
--- a/base/android/java/src/org/chromium/base/PowerMonitor.java
+++ b/base/android/java/src/org/chromium/base/PowerMonitor.java
@@ -59,7 +59,7 @@
             ApplicationStatus.registerApplicationStateListener(sInstance);
             IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
             Intent batteryStatusIntent = context.registerReceiver(null, ifilter);
-            onBatteryChargingChanged(batteryStatusIntent);
+            if (batteryStatusIntent != null) onBatteryChargingChanged(batteryStatusIntent);
         }
     }
 
diff --git a/base/base.gyp b/base/base.gyp
index d8bff8a..7e42ac8 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -527,6 +527,7 @@
         'memory/memory_pressure_monitor_chromeos_unittest.cc',
         'memory/memory_pressure_monitor_mac_unittest.cc',
         'memory/memory_pressure_monitor_win_unittest.cc',
+        'memory/ptr_util_unittest.cc',
         'memory/ref_counted_memory_unittest.cc',
         'memory/ref_counted_unittest.cc',
         'memory/scoped_ptr_unittest.cc',
diff --git a/base/base.gypi b/base/base.gypi
index 8bc9673..80771c3 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -350,6 +350,7 @@
           'memory/memory_pressure_monitor_mac.h',
           'memory/memory_pressure_monitor_win.cc',
           'memory/memory_pressure_monitor_win.h',
+          'memory/ptr_util.h',
           'memory/raw_scoped_refptr_mismatch_checker.h',
           'memory/ref_counted.cc',
           'memory/ref_counted.h',
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index f885403..afa523c9 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "base/bind.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
@@ -150,7 +153,7 @@
 
 template <typename T>
 T PassThru(T scoper) {
-  return scoper.Pass();
+  return scoper;
 }
 
 // Some test functions that we can Bind to.
@@ -752,6 +755,49 @@
   cb_unbound.Run(ptr.Pass());
 }
 
+TEST_F(BindTest, UniquePtr) {
+  int deletes = 0;
+
+  // Tests the Passed() function's support for pointers.
+  std::unique_ptr<DeleteCounter> ptr(new DeleteCounter(&deletes));
+  Callback<std::unique_ptr<DeleteCounter>(void)> unused_callback =
+      Bind(&PassThru<std::unique_ptr<DeleteCounter>>, Passed(&ptr));
+  EXPECT_FALSE(ptr.get());
+  EXPECT_EQ(0, deletes);
+
+  // If we never invoke the Callback, it retains ownership and deletes.
+  unused_callback.Reset();
+  EXPECT_EQ(1, deletes);
+
+  // Tests the Passed() function's support for rvalues.
+  deletes = 0;
+  DeleteCounter* counter = new DeleteCounter(&deletes);
+  Callback<std::unique_ptr<DeleteCounter>(void)> callback =
+      Bind(&PassThru<std::unique_ptr<DeleteCounter>>,
+           Passed(std::unique_ptr<DeleteCounter>(counter)));
+  EXPECT_FALSE(ptr.get());
+  EXPECT_EQ(0, deletes);
+
+  // Check that ownership can be transferred back out.
+  std::unique_ptr<DeleteCounter> result = callback.Run();
+  ASSERT_EQ(counter, result.get());
+  EXPECT_EQ(0, deletes);
+
+  // Resetting does not delete since ownership was transferred.
+  callback.Reset();
+  EXPECT_EQ(0, deletes);
+
+  // Ensure that we actually did get ownership.
+  result.reset();
+  EXPECT_EQ(1, deletes);
+
+  // Test unbound argument forwarding.
+  Callback<std::unique_ptr<DeleteCounter>(std::unique_ptr<DeleteCounter>)>
+      cb_unbound = Bind(&PassThru<std::unique_ptr<DeleteCounter>>);
+  ptr.reset(new DeleteCounter(&deletes));
+  cb_unbound.Run(std::move(ptr));
+}
+
 // Argument Copy-constructor usage for non-reference parameters.
 //   - Bound arguments are only copied once.
 //   - Forwarded arguments are only copied once.
diff --git a/base/callback_internal.h b/base/callback_internal.h
index aa8542c..a2adbf9 100644
--- a/base/callback_internal.h
+++ b/base/callback_internal.h
@@ -9,6 +9,7 @@
 #define BASE_CALLBACK_INTERNAL_H_
 
 #include <stddef.h>
+#include <memory>
 #include <type_traits>
 
 #include "base/atomic_ref_count.h"
@@ -94,7 +95,13 @@
 
 // A helper template to determine if given type is non-const move-only-type,
 // i.e. if a value of the given type should be passed via std::move() in a
-// destructive way.
+// destructive way. Types are considered to be move-only if they have a
+// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using
+// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro.
+// It would be easy to generalize this trait to all move-only types... but this
+// confuses template deduction in VS2013 with certain types such as
+// std::unique_ptr.
+// TODO(dcheng): Revisit this when Windows switches to VS2015 by default.
 template <typename T> struct IsMoveOnlyType {
   template <typename U>
   static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
@@ -106,6 +113,11 @@
                             !is_const<T>::value;
 };
 
+// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered
+// move-only, even without the sentinel member.
+template <typename T>
+struct IsMoveOnlyType<std::unique_ptr<T>> : std::true_type {};
+
 template <typename>
 struct CallbackParamTraitsForMoveOnlyType;
 
diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn
index 2070447..672330e 100644
--- a/base/memory/BUILD.gn
+++ b/base/memory/BUILD.gn
@@ -24,6 +24,7 @@
     "memory_pressure_monitor_mac.h",
     "memory_pressure_monitor_win.cc",
     "memory_pressure_monitor_win.h",
+    "ptr_util.h",
     "raw_scoped_refptr_mismatch_checker.h",
     "ref_counted.cc",
     "ref_counted.h",
diff --git a/base/memory/ptr_util.h b/base/memory/ptr_util.h
new file mode 100644
index 0000000..04f2c02
--- /dev/null
+++ b/base/memory/ptr_util.h
@@ -0,0 +1,22 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MEMORY_PTR_UTIL_H_
+#define BASE_MEMORY_PTR_UTIL_H_
+
+#include <memory>
+
+namespace base {
+
+// Helper to transfer ownership of a raw pointer to a std::unique_ptr<T>.
+// Note that std::unique_ptr<T> has very different semantics from
+// std::unique_ptr<T[]>: do not use this helper for array allocations.
+template <typename T>
+std::unique_ptr<T> WrapUnique(T* ptr) {
+  return std::unique_ptr<T>(ptr);
+}
+
+}  // namespace base
+
+#endif  // BASE_MEMORY_PTR_UTIL_H_
diff --git a/base/memory/ptr_util_unittest.cc b/base/memory/ptr_util_unittest.cc
new file mode 100644
index 0000000..ecf99bff9
--- /dev/null
+++ b/base/memory/ptr_util_unittest.cc
@@ -0,0 +1,38 @@
+// Copyright 2015 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/memory/ptr_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+class DeleteCounter {
+ public:
+  DeleteCounter() { ++count_; }
+  ~DeleteCounter() { --count_; }
+
+  static size_t count() { return count_; }
+
+ private:
+  static size_t count_;
+};
+
+size_t DeleteCounter::count_ = 0;
+
+}  // namespace
+
+TEST(PtrUtilTest, WrapUnique) {
+  EXPECT_EQ(0u, DeleteCounter::count());
+  DeleteCounter* counter = new DeleteCounter;
+  EXPECT_EQ(1u, DeleteCounter::count());
+  std::unique_ptr<DeleteCounter> owned_counter = WrapUnique(counter);
+  EXPECT_EQ(1u, DeleteCounter::count());
+  owned_counter.reset();
+  EXPECT_EQ(0u, DeleteCounter::count());
+}
+
+}  // namespace base
diff --git a/base/metrics/histogram_samples.cc b/base/metrics/histogram_samples.cc
index b6303a53..4cd8e556b 100644
--- a/base/metrics/histogram_samples.cc
+++ b/base/metrics/histogram_samples.cc
@@ -59,8 +59,16 @@
 
 }  // namespace
 
+// Don't try to delegate behavior to the constructor below that accepts a
+// Matadata pointer by passing &local_meta_. Such cannot be reliably passed
+// because it has not yet been constructed -- no member variables have; the
+// class itself is in the middle of being constructed. Using it to
+// initialize meta_ is okay because the object now exists and local_meta_
+// is before meta_ in the construction order.
 HistogramSamples::HistogramSamples(uint64_t id)
-    : HistogramSamples(id, &local_meta_) {}
+    : meta_(&local_meta_) {
+  meta_->id = id;
+}
 
 HistogramSamples::HistogramSamples(uint64_t id, Metadata* meta)
     : meta_(meta) {
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index 5e5ed77..db2ff84 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -48,10 +48,30 @@
   return static_cast<Dst>(value);
 }
 
+// HandleNaN will cause this class to CHECK(false).
+struct SaturatedCastNaNBehaviorCheck {
+  template <typename T>
+  static T HandleNaN() {
+    CHECK(false);
+    return T();
+  }
+};
+
+// HandleNaN will return 0 in this case.
+struct SaturatedCastNaNBehaviorReturnZero {
+  template <typename T>
+  static T HandleNaN() {
+    return T();
+  }
+};
+
 // saturated_cast<> is analogous to static_cast<> for numeric types, except
 // that the specified numeric conversion will saturate rather than overflow or
-// underflow. NaN assignment to an integral will trigger a CHECK condition.
-template <typename Dst, typename Src>
+// underflow. NaN assignment to an integral will defer the behavior to a
+// specified class. By default, it will return 0.
+template <typename Dst,
+          class NaNHandler = SaturatedCastNaNBehaviorReturnZero,
+          typename Src>
 inline Dst saturated_cast(Src value) {
   // Optimization for floating point values, which already saturate.
   if (std::numeric_limits<Dst>::is_iec559)
@@ -69,8 +89,7 @@
 
     // Should fail only on attempting to assign NaN to a saturated integer.
     case internal::RANGE_INVALID:
-      CHECK(false);
-      return std::numeric_limits<Dst>::max();
+      return NaNHandler::template HandleNaN<Dst>();
   }
 
   NOTREACHED();
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index aaf2779..6de2980 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -664,8 +664,25 @@
   EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
   EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
   EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
+
+  float not_a_number = std::numeric_limits<float>::infinity() -
+                       std::numeric_limits<float>::infinity();
+  EXPECT_TRUE(std::isnan(not_a_number));
+  EXPECT_EQ(0, saturated_cast<int>(not_a_number));
 }
 
+#if GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, SaturatedCastChecks) {
+  float not_a_number = std::numeric_limits<float>::infinity() -
+                       std::numeric_limits<float>::infinity();
+  EXPECT_TRUE(std::isnan(not_a_number));
+  EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(
+      not_a_number)), "");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
 TEST(SafeNumerics, IsValueInRangeForNumericType) {
   EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
   EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
diff --git a/blimp/client/android/toolbar.h b/blimp/client/android/toolbar.h
index b72ce1b..df4203b 100644
--- a/blimp/client/android/toolbar.h
+++ b/blimp/client/android/toolbar.h
@@ -41,6 +41,9 @@
  private:
   virtual ~Toolbar();
 
+  // A bridge to the network layer which does the work of (de)serializing the
+  // outgoing and incoming navigation messages from the engine. Toolbar does not
+  // own this and it is expected to outlive this Toolbar instance.
   NavigationFeature* navigation_feature_;
 
   // Reference to the Java object which owns this class.
diff --git a/blimp/client/compositor/blimp_compositor.h b/blimp/client/compositor/blimp_compositor.h
index 18280e04..05401c1 100644
--- a/blimp/client/compositor/blimp_compositor.h
+++ b/blimp/client/compositor/blimp_compositor.h
@@ -81,8 +81,7 @@
   // |dp_to_px| is the scale factor required to move from dp (device pixels) to
   // px.  See https://developer.android.com/guide/practices/screens_support.html
   // for more details.
-  explicit BlimpCompositor(float dp_to_px,
-                           RenderWidgetFeature* render_widget_feature);
+  BlimpCompositor(float dp_to_px, RenderWidgetFeature* render_widget_feature);
 
   // Populates the cc::LayerTreeSettings used by the cc::LayerTreeHost.  Can be
   // overridden to provide custom settings parameters.
@@ -162,6 +161,8 @@
   cc::RemoteProtoChannel::ProtoReceiver* remote_proto_channel_receiver_;
 
   // The bridge to the network layer that does the proto/RenderWidget id work.
+  // BlimpCompositor does not own this and it is expected to outlive this
+  // BlimpCompositor instance.
   // TODO(dtrainor): Move this to a higher level once we start dealing with
   // multiple tabs.
   RenderWidgetFeature* render_widget_feature_;
diff --git a/blimp/client/session/render_widget_feature_unittest.cc b/blimp/client/session/render_widget_feature_unittest.cc
index 3e7752d..aeb4eb07 100644
--- a/blimp/client/session/render_widget_feature_unittest.cc
+++ b/blimp/client/session/render_widget_feature_unittest.cc
@@ -17,6 +17,8 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
+using testing::InSequence;
+using testing::Sequence;
 
 namespace blimp {
 
@@ -96,37 +98,31 @@
 
 TEST_F(RenderWidgetFeatureTest, DelegateCallsOK) {
   EXPECT_CALL(delegate1_, MockableOnRenderWidgetInitialized()).Times(1);
-  SendRenderWidgetMessage(&feature_, 1, 1U);
-
-  EXPECT_CALL(delegate1_, MockableOnCompositorMessageReceived(_)).Times(1);
-  SendCompositorMessage(&feature_, 1, 1U);
-
+  EXPECT_CALL(delegate1_, MockableOnCompositorMessageReceived(_)).Times(2);
   EXPECT_CALL(delegate2_, MockableOnRenderWidgetInitialized()).Times(1);
-  SendRenderWidgetMessage(&feature_, 2, 2U);
+  EXPECT_CALL(delegate2_, MockableOnCompositorMessageReceived(_)).Times(0);
 
-  EXPECT_CALL(delegate2_, MockableOnCompositorMessageReceived(_)).Times(1);
-  SendCompositorMessage(&feature_, 2, 2U);
+  SendRenderWidgetMessage(&feature_, 1, 1U);
+  SendCompositorMessage(&feature_, 1, 1U);
+  SendCompositorMessage(&feature_, 1, 1U);
+  SendRenderWidgetMessage(&feature_, 2, 2U);
 }
 
 TEST_F(RenderWidgetFeatureTest, RepliesHaveCorrectRenderWidgetId) {
+  InSequence sequence;
+
+  EXPECT_CALL(*out_compositor_processor_,
+              MockableProcessMessage(CompMsgEquals(1, 2U), _));
+  EXPECT_CALL(*out_compositor_processor_,
+              MockableProcessMessage(CompMsgEquals(1, 3U), _));
+  EXPECT_CALL(*out_compositor_processor_,
+              MockableProcessMessage(CompMsgEquals(2, 1U), _));
+
   SendRenderWidgetMessage(&feature_, 1, 2U);
-  SendRenderWidgetMessage(&feature_, 2, 1U);
-
-  EXPECT_CALL(*out_compositor_processor_,
-              MockableProcessMessage(CompMsgEquals(1, 2U), _))
-      .Times(1);
   feature_.SendCompositorMessage(1, cc::proto::CompositorMessage());
-
   SendRenderWidgetMessage(&feature_, 1, 3U);
-
-  EXPECT_CALL(*out_compositor_processor_,
-              MockableProcessMessage(CompMsgEquals(1, 3U), _))
-      .Times(1);
   feature_.SendCompositorMessage(1, cc::proto::CompositorMessage());
-
-  EXPECT_CALL(*out_compositor_processor_,
-              MockableProcessMessage(CompMsgEquals(2, 1U), _))
-      .Times(1);
+  SendRenderWidgetMessage(&feature_, 2, 1U);
   feature_.SendCompositorMessage(2, cc::proto::CompositorMessage());
 }
 
diff --git a/blimp/engine/browser/engine_render_widget_message_processor_unittest.cc b/blimp/engine/browser/engine_render_widget_message_processor_unittest.cc
index 70d78fdc..82a06df 100644
--- a/blimp/engine/browser/engine_render_widget_message_processor_unittest.cc
+++ b/blimp/engine/browser/engine_render_widget_message_processor_unittest.cc
@@ -19,10 +19,8 @@
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 
 using testing::_;
-using testing::InvokeArgument;
-using testing::Ref;
-using testing::Return;
-using testing::SaveArg;
+using testing::InSequence;
+using testing::Sequence;
 
 namespace blimp {
 
@@ -110,9 +108,6 @@
   void SetUp() override {
     processor_.SetDelegate(1, &delegate1_);
     processor_.SetDelegate(2, &delegate2_);
-
-    processor_.OnRenderWidgetInitialized(1);
-    processor_.OnRenderWidgetInitialized(2);
   }
 
  protected:
@@ -125,63 +120,77 @@
 TEST_F(EngineRenderWidgetMessageProcessorTest, DelegateCallsOK) {
   std::vector<uint8_t> payload = { 'd', 'a', 'v', 'i', 'd' };
 
-  EXPECT_CALL(delegate1_, MockableOnCompositorMessageReceived(
-      CompMsgEquals(payload))).Times(1);
-  SendCompositorMessage(&processor_, 1, 1U, payload);
-
+  EXPECT_CALL(out_processor_, MockableProcessMessage(_, _)).Times(2);
+  EXPECT_CALL(delegate1_,
+              MockableOnCompositorMessageReceived(CompMsgEquals(payload)))
+      .Times(1);
   EXPECT_CALL(delegate1_, MockableOnWebInputEvent()).Times(1);
+  EXPECT_CALL(delegate2_,
+              MockableOnCompositorMessageReceived(CompMsgEquals(payload)))
+      .Times(1);
+  EXPECT_CALL(delegate2_, MockableOnWebInputEvent()).Times(0);
+
+  processor_.OnRenderWidgetInitialized(1);
+  processor_.OnRenderWidgetInitialized(2);
+  SendCompositorMessage(&processor_, 1, 1U, payload);
   SendInputMessage(&processor_, 1, 1U);
-
-  EXPECT_CALL(delegate2_, MockableOnCompositorMessageReceived(
-      CompMsgEquals(payload))).Times(1);
   SendCompositorMessage(&processor_, 2, 1U, payload);
-
-  EXPECT_CALL(delegate2_, MockableOnWebInputEvent()).Times(1);
-  SendInputMessage(&processor_, 2, 1U);
 }
 
 TEST_F(EngineRenderWidgetMessageProcessorTest, DropsStaleMessages) {
+  InSequence sequence;
   std::vector<uint8_t> payload = { 'f', 'u', 'n' };
-
-  EXPECT_CALL(delegate1_, MockableOnCompositorMessageReceived(
-      CompMsgEquals(payload))).Times(1);
-  SendCompositorMessage(&processor_, 1, 1U, payload);
+  std::vector<uint8_t> new_payload = {'n', 'o', ' ', 'f', 'u', 'n'};
 
   EXPECT_CALL(out_processor_,
-              MockableProcessMessage(BlimpRWMsgEquals(1, 2U), _)).Times(1);
+              MockableProcessMessage(BlimpRWMsgEquals(1, 1U), _));
+  EXPECT_CALL(delegate1_,
+              MockableOnCompositorMessageReceived(CompMsgEquals(payload)));
+  EXPECT_CALL(out_processor_,
+              MockableProcessMessage(BlimpRWMsgEquals(1, 2U), _));
+  EXPECT_CALL(delegate1_,
+              MockableOnCompositorMessageReceived(CompMsgEquals(new_payload)));
+  EXPECT_CALL(delegate1_, MockableOnWebInputEvent());
+
+  processor_.OnRenderWidgetInitialized(1);
+  SendCompositorMessage(&processor_, 1, 1U, payload);
   processor_.OnRenderWidgetInitialized(1);
 
-  EXPECT_CALL(delegate1_, MockableOnCompositorMessageReceived(
-      CompMsgEquals(payload))).Times(0);
-  payload[0] = 'a';
+  // These next three calls should be dropped.
   SendCompositorMessage(&processor_, 1, 1U, payload);
-
-  EXPECT_CALL(delegate1_, MockableOnWebInputEvent()).Times(0);
+  SendCompositorMessage(&processor_, 1, 1U, payload);
   SendInputMessage(&processor_, 1, 1U);
 
-  EXPECT_CALL(delegate1_, MockableOnCompositorMessageReceived(
-      CompMsgEquals(payload))).Times(1);
-  SendCompositorMessage(&processor_, 1, 2U, payload);
-
-  EXPECT_CALL(delegate1_, MockableOnWebInputEvent()).Times(1);
+  SendCompositorMessage(&processor_, 1, 2U, new_payload);
   SendInputMessage(&processor_, 1, 2U);
 }
 
 TEST_F(EngineRenderWidgetMessageProcessorTest,
        RepliesHaveCorrectRenderWidgetId) {
+  Sequence delegate1_sequence;
+  Sequence delegate2_sequence;
   std::vector<uint8_t> payload = { 'a', 'b', 'c', 'd' };
 
   EXPECT_CALL(out_processor_,
-              MockableProcessMessage(BlimpRWMsgEquals(1, 2U), _)).Times(1);
-  processor_.OnRenderWidgetInitialized(1);
-
+              MockableProcessMessage(BlimpRWMsgEquals(1, 1U), _))
+      .InSequence(delegate1_sequence);
   EXPECT_CALL(out_processor_,
-              MockableProcessMessage(BlimpRWMsgEquals(2, 2U), _)).Times(1);
+              MockableProcessMessage(BlimpRWMsgEquals(1, 2U), _))
+      .InSequence(delegate1_sequence);
+  EXPECT_CALL(out_processor_,
+              MockableProcessMessage(BlimpCompMsgEquals(1, 2U, payload), _))
+      .InSequence(delegate1_sequence);
+  EXPECT_CALL(out_processor_,
+              MockableProcessMessage(BlimpRWMsgEquals(2, 1U), _))
+      .InSequence(delegate2_sequence);
+  EXPECT_CALL(out_processor_,
+              MockableProcessMessage(BlimpRWMsgEquals(2, 2U), _))
+      .InSequence(delegate2_sequence);
+
+  processor_.OnRenderWidgetInitialized(1);
   processor_.OnRenderWidgetInitialized(2);
-
-  EXPECT_CALL(out_processor_, MockableProcessMessage(
-      BlimpCompMsgEquals(1, 2U, payload), _)).Times(1);
-
+  processor_.OnRenderWidgetInitialized(1);
+  processor_.OnRenderWidgetInitialized(2);
   processor_.SendCompositorMessage(1, payload);
 }
 
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index ad8ca1f8..8cfe59c 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -27,8 +27,8 @@
       input_api,
       output_api,
       pylintrc='pylintrc',
-      # symbols has its own PRESUBMIT.py
-      black_list=build_pys + [r'pylib/symbols/.*\.py$'],
+      # devil and symbols have their own PRESUBMIT.py
+      black_list=build_pys + [r'devil/.*\.py$', r'pylib/symbols/.*\.py$'],
       extra_paths_list=[J(), J('buildbot')]))
   output.extend(input_api.canned_checks.RunPylint(
       input_api,
@@ -60,26 +60,6 @@
       ],
       env=pylib_test_env))
 
-
-  devil_test_env = dict(pylib_test_env)
-  devil_test_env.update({
-      'DEVIL_ENV_CONFIG':
-          input_api.os_path.join(build_android_dir, 'devil_chromium.json')
-  })
-  output.extend(input_api.canned_checks.RunUnitTests(
-      input_api,
-      output_api,
-      unit_tests=[
-          J('devil', 'devil_env_test.py'),
-          J('devil', 'android', 'battery_utils_test.py'),
-          J('devil', 'android', 'device_utils_test.py'),
-          J('devil', 'android', 'fastboot_utils_test.py'),
-          J('devil', 'android', 'md5sum_test.py'),
-          J('devil', 'android', 'logcat_monitor_test.py'),
-          J('devil', 'utils', 'cmd_helper_test.py'),
-          J('devil', 'utils', 'timeout_retry_unittest.py'),
-      ],
-      env=devil_test_env))
   return output
 
 
diff --git a/build/android/devil/PRESUBMIT.py b/build/android/devil/PRESUBMIT.py
new file mode 100644
index 0000000..e2c3dfe
--- /dev/null
+++ b/build/android/devil/PRESUBMIT.py
@@ -0,0 +1,87 @@
+# Copyright 2015 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.
+
+"""Presubmit script for devil.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into depot_tools.
+"""
+
+
+def _RunPylint(input_api, output_api):
+  return input_api.canned_checks.RunPylint(
+      input_api,
+      output_api,
+      pylintrc='pylintrc',
+      extra_paths_list=[
+          input_api.os_path.join(input_api.PresubmitLocalPath(), '..'),
+      ])
+
+
+def _RunUnitTests(input_api, output_api):
+  def J(*dirs):
+    """Returns a path relative to presubmit directory."""
+    return input_api.os_path.join(input_api.PresubmitLocalPath(), *dirs)
+
+  test_env = dict(input_api.environ)
+  test_env.update({
+    'PYTHONDONTWRITEBYTECODE': '1',
+    'PYTHONPATH': ':'.join([J(), J('..')]),
+  })
+
+  return input_api.canned_checks.RunUnitTests(
+      input_api,
+      output_api,
+      unit_tests=[
+          J('devil_env_test.py'),
+          J('android', 'battery_utils_test.py'),
+          J('android', 'device_utils_test.py'),
+          J('android', 'fastboot_utils_test.py'),
+          J('android', 'md5sum_test.py'),
+          J('android', 'logcat_monitor_test.py'),
+          J('utils', 'cmd_helper_test.py'),
+          J('utils', 'timeout_retry_unittest.py'),
+      ],
+      env=test_env)
+
+
+def _EnsureNoPylibUse(input_api, output_api):
+  def other_python_files(f):
+    this_presubmit_file = input_api.os_path.join(
+        input_api.PresubmitLocalPath(), 'PRESUBMIT.py')
+    return (f.LocalPath().endswith('.py')
+            and not f.AbsoluteLocalPath() == this_presubmit_file)
+
+  changed_files = input_api.AffectedSourceFiles(other_python_files)
+  import_error_re = input_api.re.compile(
+      r'(from pylib.* import)|(import pylib)')
+
+  errors = []
+  for f in changed_files:
+    errors.extend(
+        '%s:%d' % (f.LocalPath(), line_number)
+        for line_number, line_text in f.ChangedContents()
+        if import_error_re.search(line_text))
+
+  if errors:
+    return [output_api.PresubmitError(
+        'pylib modules should not be imported from devil modules.',
+        items=errors)]
+  return []
+
+
+def CommonChecks(input_api, output_api):
+  output = []
+  output += _RunPylint(input_api, output_api)
+  output += _RunUnitTests(input_api, output_api)
+  output += _EnsureNoPylibUse(input_api, output_api)
+  return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return CommonChecks(input_api, output_api)
diff --git a/build/android/devil/android/device_errors.py b/build/android/devil/android/device_errors.py
index 2fe5a80..ea14bf9 100644
--- a/build/android/devil/android/device_errors.py
+++ b/build/android/devil/android/device_errors.py
@@ -112,6 +112,6 @@
 class NoAdbError(base_error.BaseError):
   """Exception for being unable to find ADB."""
 
-  def __init__(self):
+  def __init__(self, msg=None):
     super(NoAdbError, self).__init__(
-        'Unable to find adb.', is_infra_error=True)
+        msg or 'Unable to find adb.', is_infra_error=True)
diff --git a/build/android/devil/android/sdk/adb_wrapper.py b/build/android/devil/android/sdk/adb_wrapper.py
index 38db0e1..17288c20 100644
--- a/build/android/devil/android/sdk/adb_wrapper.py
+++ b/build/android/devil/android/sdk/adb_wrapper.py
@@ -115,7 +115,7 @@
           timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime())
     except OSError as e:
       if e.errno in (errno.ENOENT, errno.ENOEXEC):
-        raise device_errors.NoAdbError()
+        raise device_errors.NoAdbError(msg=str(e))
       else:
         raise
 
diff --git a/build/android/devil/pylintrc b/build/android/devil/pylintrc
new file mode 100644
index 0000000..8005a5d
--- /dev/null
+++ b/build/android/devil/pylintrc
@@ -0,0 +1,15 @@
+[FORMAT]
+
+max-line-length=80
+
+[MESSAGES CONTROL]
+
+disable=abstract-class-not-used,bad-continuation,bad-indentation,duplicate-code,fixme,invalid-name,locally-disabled,locally-enabled,missing-docstring,star-args,too-few-public-methods,too-many-arguments,too-many-branches,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-statements,
+
+[REPORTS]
+
+reports=no
+
+[VARIABLES]
+
+dummy-variables-rgx=^_.*$|dummy
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index a474837..b973351 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -298,6 +298,9 @@
     else:
       logging.warning('Cannot remove system webview from a non-rooted device')
 
+  # Some device types can momentarily disappear after setting properties.
+  device.adb.WaitForDevice()
+
 
 def _ConfigureLocalProperties(device, java_debug=True):
   """Set standard readonly testing device properties prior to reboot."""
@@ -388,10 +391,14 @@
 
 def _UninstallIfMatch(device, pattern, app_to_keep):
   installed_packages = device.RunShellCommand(['pm', 'list', 'packages'])
+  installed_system_packages = [
+      pkg.split(':')[1] for pkg in device.RunShellCommand(['pm', 'list',
+                                                           'packages', '-s'])]
   for package_output in installed_packages:
     package = package_output.split(":")[1]
     if pattern.match(package) and not package == app_to_keep:
-      device.Uninstall(package)
+      if not device.IsUserBuild() or package not in installed_system_packages:
+        device.Uninstall(package)
 
 
 def _WipeUnderDirIfMatch(device, path, pattern):
diff --git a/build/config/gcc/BUILD.gn b/build/config/gcc/BUILD.gn
index b0fc981..3380eb266 100644
--- a/build/config/gcc/BUILD.gn
+++ b/build/config/gcc/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/sanitizers/sanitizers.gni")
 import("//build/toolchain/toolchain.gni")
 
 # This config causes functions not to be automatically exported from shared
@@ -67,7 +68,9 @@
       "-Wl,-z,nocopyreloc",
     ]
   } else {
-    if (is_component_build) {
+    # See the rpath_for... config above for why this is necessary for component
+    # builds. Sanitizers use a custom libc++ where this is also necessary.
+    if (is_component_build || using_sanitizer) {
       configs = [ ":rpath_for_built_shared_libraries" ]
     }
 
diff --git a/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn
index 904fa543..152b05d 100644
--- a/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn
@@ -6,7 +6,10 @@
   if (is_win) {
     include_dirs = [ "win" ]
   } else if (is_mac) {
-    include_dirs = [ "mac" ]
+    include_dirs = [
+      "mac",
+      "non_cxx11_lib",
+    ]
   }
 }
 
@@ -21,6 +24,8 @@
       "mac/mach-o/loader.h",
       "mac/mach/mach.h",
       "mac/sys/resource.h",
+      "non_cxx11_lib/type_traits",
+      "non_cxx11_lib/utility",
     ]
   } else {
     sources += [ "non_mac/mach/mach.h" ]
diff --git a/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn
index aa8443a..376fb6b9 100644
--- a/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -91,10 +91,14 @@
     "win/pe_image_annotations_reader.h",
     "win/pe_image_reader.cc",
     "win/pe_image_reader.h",
+    "win/pe_image_resource_reader.cc",
+    "win/pe_image_resource_reader.h",
     "win/process_reader_win.cc",
     "win/process_reader_win.h",
     "win/process_snapshot_win.cc",
     "win/process_snapshot_win.h",
+    "win/process_subrange_reader.cc",
+    "win/process_subrange_reader.h",
     "win/system_snapshot_win.cc",
     "win/system_snapshot_win.h",
     "win/thread_snapshot_win.cc",
diff --git a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
index 9429597..cae4b64 100644
--- a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
@@ -102,6 +102,8 @@
     "posix/process_info_mac.cc",
     "posix/symbolic_constants_posix.cc",
     "posix/symbolic_constants_posix.h",
+    "stdlib/aligned_allocator.cc",
+    "stdlib/aligned_allocator.h",
     "stdlib/cxx.h",
     "stdlib/map_insert.h",
     "stdlib/objc.h",
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 6c4008b..fb77e981 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -104,6 +104,8 @@
     "input/scroll_elasticity_helper.h",
     "input/scroll_state.cc",
     "input/scroll_state.h",
+    "input/scroll_state_data.cc",
+    "input/scroll_state_data.h",
     "input/selection.h",
     "input/selection_bound_type.h",
     "input/top_controls_manager.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index b64eb7c8..9374fcf 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -166,6 +166,8 @@
         'input/scroll_elasticity_helper.h',
         'input/scroll_state.cc',
         'input/scroll_state.h',
+        'input/scroll_state_data.cc',
+        'input/scroll_state_data.h',
         'input/selection_bound_type.h',
         'input/selection.h',
         'input/top_controls_manager.cc',
@@ -433,6 +435,7 @@
         'raster/single_thread_task_graph_runner.h',
         'raster/synchronous_task_graph_runner.cc',
         'raster/synchronous_task_graph_runner.h',
+        'raster/task_category.h',
         'raster/task_graph_runner.cc',
         'raster/task_graph_runner.h',
         'raster/task_graph_work_queue.cc',
diff --git a/cc/input/scroll_state.cc b/cc/input/scroll_state.cc
index 52a0cca6..513c08f 100644
--- a/cc/input/scroll_state.cc
+++ b/cc/input/scroll_state.cc
@@ -15,24 +15,26 @@
                          bool should_propagate,
                          bool delta_consumed_for_scroll_sequence,
                          bool is_direct_manipulation)
-    : delta_x_(delta_x),
-      delta_y_(delta_y),
-      start_position_x_(start_position_x),
-      start_position_y_(start_position_y),
-      should_propagate_(should_propagate),
-      delta_consumed_for_scroll_sequence_(delta_consumed_for_scroll_sequence),
-      is_direct_manipulation_(is_direct_manipulation),
-      caused_scroll_x_(false),
-      caused_scroll_y_(false) {}
+    : data_(new ScrollStateData(delta_x,
+                                delta_y,
+                                start_position_x,
+                                start_position_y,
+                                should_propagate,
+                                delta_consumed_for_scroll_sequence,
+                                is_direct_manipulation)) {}
+
+ScrollState::ScrollState(scoped_ptr<ScrollStateData> data) {
+  data_ = data.Pass();
+}
 
 ScrollState::~ScrollState() {}
 
 void ScrollState::ConsumeDelta(double x, double y) {
-  delta_x_ -= x;
-  delta_y_ -= y;
+  data_->delta_x -= x;
+  data_->delta_y -= y;
 
   if (x || y)
-    delta_consumed_for_scroll_sequence_ = true;
+    data_->delta_consumed_for_scroll_sequence = true;
 }
 
 void ScrollState::DistributeToScrollChainDescendant() {
diff --git a/cc/input/scroll_state.h b/cc/input/scroll_state.h
index 2cd437d..ce0c701 100644
--- a/cc/input/scroll_state.h
+++ b/cc/input/scroll_state.h
@@ -7,7 +7,9 @@
 
 #include <list>
 
+#include "base/memory/scoped_ptr.h"
 #include "cc/base/cc_export.h"
+#include "cc/input/scroll_state_data.h"
 
 namespace cc {
 
@@ -24,6 +26,7 @@
               bool should_propagate,
               bool delta_consumed_for_scroll_sequence,
               bool is_direct_manipulation);
+  explicit ScrollState(scoped_ptr<ScrollStateData> data);
   ~ScrollState();
 
   // Reduce deltas by x, y.
@@ -32,74 +35,49 @@
   // |DistributeScroll| on it.
   void DistributeToScrollChainDescendant();
   // Positive when scrolling left.
-  double delta_x() const { return delta_x_; }
+  double delta_x() const { return data_->delta_x; }
   // Positive when scrolling up.
-  double delta_y() const { return delta_y_; }
+  double delta_y() const { return data_->delta_y; }
   // The location the scroll started at. For touch, the starting
   // position of the finger. For mouse, the location of the cursor.
-  int start_position_x() const { return start_position_x_; }
-  int start_position_y() const { return start_position_y_; }
+  int start_position_x() const { return data_->start_position_x; }
+  int start_position_y() const { return data_->start_position_y; }
 
   // True if this scroll is allowed to bubble upwards.
-  bool should_propagate() const { return should_propagate_; }
+  bool should_propagate() const { return data_->should_propagate; }
   // True if the user interacts directly with the screen, e.g., via touch.
-  bool is_direct_manipulation() const { return is_direct_manipulation_; }
+  bool is_direct_manipulation() const { return data_->is_direct_manipulation; }
 
   void set_scroll_chain(const std::list<LayerImpl*>& scroll_chain) {
     scroll_chain_ = scroll_chain;
   }
 
   void set_current_native_scrolling_layer(LayerImpl* layer) {
-    current_native_scrolling_layer_ = layer;
+    data_->current_native_scrolling_layer = layer;
   }
 
   LayerImpl* current_native_scrolling_layer() const {
-    return current_native_scrolling_layer_;
+    return data_->current_native_scrolling_layer;
   }
 
   bool delta_consumed_for_scroll_sequence() const {
-    return delta_consumed_for_scroll_sequence_;
+    return data_->delta_consumed_for_scroll_sequence;
   }
 
-  bool FullyConsumed() const { return !delta_x_ && !delta_y_; }
+  bool FullyConsumed() const { return !data_->delta_x && !data_->delta_y; }
 
   void set_caused_scroll(bool x, bool y) {
-    caused_scroll_x_ |= x;
-    caused_scroll_y_ |= y;
+    data_->caused_scroll_x |= x;
+    data_->caused_scroll_y |= y;
   }
 
-  bool caused_scroll_x() const { return caused_scroll_x_; }
-  bool caused_scroll_y() const { return caused_scroll_y_; }
+  bool caused_scroll_x() const { return data_->caused_scroll_x; }
+  bool caused_scroll_y() const { return data_->caused_scroll_y; }
+
+  ScrollStateData* data() { return data_.get(); }
 
  private:
-  ScrollState();
-  double delta_x_;
-  double delta_y_;
-  double start_position_x_;
-  double start_position_y_;
-
-  bool should_propagate_;
-
-  // The last layer to respond to a scroll, or null if none exists.
-  LayerImpl* current_native_scrolling_layer_;
-  // Whether the scroll sequence has had any delta consumed, in the
-  // current frame, or any child frames.
-  bool delta_consumed_for_scroll_sequence_;
-  // True if the user interacts directly with the display, e.g., via
-  // touch.
-  bool is_direct_manipulation_;
-  // TODO(tdresser): ScrollState shouldn't need to keep track of whether or not
-  // this ScrollState object has caused a scroll. Ideally, any native scroller
-  // consuming delta has caused a scroll. Currently, there are some cases where
-  // we consume delta without scrolling, such as in
-  // |Viewport::AdjustOverscroll|. Once these cases are fixed, we should get rid
-  // of |caused_scroll_*_|. See crbug.com/510045 for details.
-  bool caused_scroll_x_;
-  bool caused_scroll_y_;
-
-  // TODO(tdresser): Change LayerImpl* to an abstract scrollable type. See
-  // crbug.com/476553 for detail on the effort to unify impl and main thread
-  // scrolling, which will require an abstract scrollable type.
+  scoped_ptr<ScrollStateData> data_;
   std::list<LayerImpl*> scroll_chain_;
 };
 
diff --git a/cc/input/scroll_state_data.cc b/cc/input/scroll_state_data.cc
new file mode 100644
index 0000000..1e012d3
--- /dev/null
+++ b/cc/input/scroll_state_data.cc
@@ -0,0 +1,30 @@
+// Copyright 2015 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 "cc/input/scroll_state_data.h"
+
+namespace cc {
+
+ScrollStateData::ScrollStateData(double delta_x,
+                                 double delta_y,
+                                 int start_position_x,
+                                 int start_position_y,
+                                 bool should_propagate,
+                                 bool delta_consumed_for_scroll_sequence,
+                                 bool is_direct_manipulation)
+    : delta_x(delta_x),
+      delta_y(delta_y),
+      start_position_x(start_position_x),
+      start_position_y(start_position_y),
+      should_propagate(should_propagate),
+      current_native_scrolling_layer(nullptr),
+      delta_consumed_for_scroll_sequence(delta_consumed_for_scroll_sequence),
+      is_direct_manipulation(is_direct_manipulation),
+      caused_scroll_x(false),
+      caused_scroll_y(false) {}
+
+ScrollStateData::ScrollStateData()
+    : ScrollStateData(0, 0, 0, 0, true, false, false) {}
+
+}  // namespace cc
diff --git a/cc/input/scroll_state_data.h b/cc/input/scroll_state_data.h
new file mode 100644
index 0000000..139db43
--- /dev/null
+++ b/cc/input/scroll_state_data.h
@@ -0,0 +1,53 @@
+// Copyright 2015 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 CC_INPUT_SCROLL_STATE_DATA_H_
+#define CC_INPUT_SCROLL_STATE_DATA_H_
+
+#include <list>
+
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+class LayerImpl;
+
+struct CC_EXPORT ScrollStateData {
+ public:
+  ScrollStateData();
+  ScrollStateData(double delta_x,
+                  double delta_y,
+                  int start_position_x,
+                  int start_position_y,
+                  bool should_propagate,
+                  bool delta_consumed_for_scroll_sequence,
+                  bool is_direct_manipulation);
+  double delta_x;
+  double delta_y;
+  double start_position_x;
+  double start_position_y;
+
+  bool should_propagate;
+
+  // The last layer to respond to a scroll, or null if none exists.
+  LayerImpl* current_native_scrolling_layer;
+  // Whether the scroll sequence has had any delta consumed, in the
+  // current frame, or any child frames.
+  bool delta_consumed_for_scroll_sequence;
+  // True if the user interacts directly with the display, e.g., via
+  // touch.
+  bool is_direct_manipulation;
+  // TODO(tdresser): ScrollState shouldn't need to keep track of whether or not
+  // this ScrollState object has caused a scroll. Ideally, any native scroller
+  // consuming delta has caused a scroll. Currently, there are some cases where
+  // we consume delta without scrolling, such as in
+  // |Viewport::AdjustOverscroll|. Once these cases are fixed, we should get rid
+  // of |caused_scroll_*_|. See crbug.com/510045 for details.
+  bool caused_scroll_x;
+  bool caused_scroll_y;
+};
+
+}  // namespace cc
+
+#endif  // CC_INPUT_SCROLL_STATE_DATA_H_
diff --git a/cc/raster/single_thread_task_graph_runner.cc b/cc/raster/single_thread_task_graph_runner.cc
index 24994c9..80c85db 100644
--- a/cc/raster/single_thread_task_graph_runner.cc
+++ b/cc/raster/single_thread_task_graph_runner.cc
@@ -112,7 +112,7 @@
   base::AutoLock lock(lock_);
 
   while (true) {
-    if (!work_queue_.HasReadyToRunTasks()) {
+    if (!RunTaskWithLockAcquired()) {
       // Exit when shutdown is set and no more tasks are pending.
       if (shutdown_)
         break;
@@ -121,18 +121,29 @@
       has_ready_to_run_tasks_cv_.Wait();
       continue;
     }
-
-    RunTaskWithLockAcquired();
   }
 }
 
-void SingleThreadTaskGraphRunner::RunTaskWithLockAcquired() {
+bool SingleThreadTaskGraphRunner::RunTaskWithLockAcquired() {
   TRACE_EVENT0("toplevel",
                "SingleThreadTaskGraphRunner::RunTaskWithLockAcquired");
 
   lock_.AssertAcquired();
 
-  auto prioritized_task = work_queue_.GetNextTaskToRun();
+  // Find the first category with any tasks to run. This task graph runner
+  // treats categories as an additional priority.
+  const auto& ready_to_run_namespaces = work_queue_.ready_to_run_namespaces();
+  auto found = std::find_if(
+      ready_to_run_namespaces.cbegin(), ready_to_run_namespaces.cend(),
+      [](const std::pair<uint16_t, TaskGraphWorkQueue::TaskNamespace::Vector>&
+             pair) { return !pair.second.empty(); });
+
+  if (found == ready_to_run_namespaces.cend()) {
+    return false;
+  }
+
+  const uint16_t category = found->first;
+  auto prioritized_task = work_queue_.GetNextTaskToRun(category);
   Task* task = prioritized_task.task;
 
   // Call WillRun() before releasing |lock_| and running task.
@@ -152,6 +163,8 @@
   if (work_queue_.HasFinishedRunningTasksInNamespace(
           prioritized_task.task_namespace))
     has_namespaces_with_finished_running_tasks_cv_.Signal();
+
+  return true;
 }
 
 }  // namespace cc
diff --git a/cc/raster/single_thread_task_graph_runner.h b/cc/raster/single_thread_task_graph_runner.h
index 120cd7b..3e8dec07 100644
--- a/cc/raster/single_thread_task_graph_runner.h
+++ b/cc/raster/single_thread_task_graph_runner.h
@@ -40,7 +40,8 @@
   void Shutdown();
 
  private:
-  void RunTaskWithLockAcquired();
+  // Returns true if there was a task to run.
+  bool RunTaskWithLockAcquired();
 
   scoped_ptr<base::SimpleThread> thread_;
 
diff --git a/cc/raster/synchronous_task_graph_runner.cc b/cc/raster/synchronous_task_graph_runner.cc
index ed05cfb..ea7b15b 100644
--- a/cc/raster/synchronous_task_graph_runner.cc
+++ b/cc/raster/synchronous_task_graph_runner.cc
@@ -4,6 +4,9 @@
 
 #include "cc/raster/synchronous_task_graph_runner.h"
 
+#include <algorithm>
+#include <utility>
+
 #include "base/threading/simple_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/trace_event/trace_event.h"
@@ -43,7 +46,7 @@
 
   while (
       !TaskGraphWorkQueue::HasFinishedRunningTasksInNamespace(task_namespace)) {
-    RunTask();
+    DCHECK(RunTask());
   }
 }
 
@@ -57,14 +60,27 @@
 }
 
 void SynchronousTaskGraphRunner::RunUntilIdle() {
-  while (work_queue_.HasReadyToRunTasks())
-    RunTask();
+  while (RunTask()) {
+  }
 }
 
-void SynchronousTaskGraphRunner::RunTask() {
+bool SynchronousTaskGraphRunner::RunTask() {
   TRACE_EVENT0("toplevel", "SynchronousTaskGraphRunner::RunTask");
 
-  auto prioritized_task = work_queue_.GetNextTaskToRun();
+  // Find the first category with any tasks to run. This task graph runner
+  // treats categories as an additional priority.
+  const auto& ready_to_run_namespaces = work_queue_.ready_to_run_namespaces();
+  auto found = std::find_if(
+      ready_to_run_namespaces.cbegin(), ready_to_run_namespaces.cend(),
+      [](const std::pair<uint16_t, TaskGraphWorkQueue::TaskNamespace::Vector>&
+             pair) { return !pair.second.empty(); });
+
+  if (found == ready_to_run_namespaces.cend()) {
+    return false;
+  }
+
+  const uint16_t category = found->first;
+  auto prioritized_task = work_queue_.GetNextTaskToRun(category);
 
   Task* task = prioritized_task.task;
   task->WillRun();
@@ -72,6 +88,8 @@
   task->DidRun();
 
   work_queue_.CompleteTask(prioritized_task);
+
+  return true;
 }
 
 }  // namespace cc
diff --git a/cc/raster/synchronous_task_graph_runner.h b/cc/raster/synchronous_task_graph_runner.h
index 89ecca2..65a7716 100644
--- a/cc/raster/synchronous_task_graph_runner.h
+++ b/cc/raster/synchronous_task_graph_runner.h
@@ -28,7 +28,8 @@
   void RunUntilIdle();
 
  private:
-  void RunTask();
+  // Returns true if there was a task to run.
+  bool RunTask();
 
   // Stores the actual tasks to be run, sorted by priority.
   TaskGraphWorkQueue work_queue_;
diff --git a/cc/raster/task_graph_runner.h b/cc/raster/task_graph_runner.h
index b5ffade..181a455 100644
--- a/cc/raster/task_graph_runner.h
+++ b/cc/raster/task_graph_runner.h
@@ -46,19 +46,29 @@
 
 // A task dependency graph describes the order in which to execute a set
 // of tasks. Dependencies are represented as edges. Each node is assigned
-// a priority and a run count that matches the number of dependencies.
-// Priority range from 0 (most favorable scheduling) to UINT_MAX
-// (least favorable).
+// a category, a priority and a run count that matches the number of
+// dependencies. Priority range from 0 (most favorable scheduling) to UINT16_MAX
+// (least favorable). Categories range from 0 to UINT16_MAX. It is up to the
+// implementation and its consumer to determine the meaning (if any) of a
+// category. A TaskGraphRunner implementation may chose to prioritize certain
+// categories over others, regardless of the individual priorities of tasks.
 struct CC_EXPORT TaskGraph {
   struct Node {
     typedef std::vector<Node> Vector;
 
-    Node(Task* task, size_t priority, size_t dependencies)
-        : task(task), priority(priority), dependencies(dependencies) {}
+    Node(Task* task,
+         uint16_t category,
+         uint16_t priority,
+         uint32_t dependencies)
+        : task(task),
+          category(category),
+          priority(priority),
+          dependencies(dependencies) {}
 
     Task* task;
-    size_t priority;
-    size_t dependencies;
+    uint16_t category;
+    uint16_t priority;
+    uint32_t dependencies;
   };
 
   struct Edge {
diff --git a/cc/raster/task_graph_runner_perftest.cc b/cc/raster/task_graph_runner_perftest.cc
index f571d33d..0df0757 100644
--- a/cc/raster/task_graph_runner_perftest.cc
+++ b/cc/raster/task_graph_runner_perftest.cc
@@ -230,13 +230,13 @@
     for (PerfTaskImpl::Vector::const_iterator it = leaf_tasks.begin();
          it != leaf_tasks.end();
          ++it) {
-      graph->nodes.push_back(TaskGraph::Node(it->get(), 0u, 0u));
+      graph->nodes.push_back(TaskGraph::Node(it->get(), 0u, 0u, 0u));
     }
 
     for (PerfTaskImpl::Vector::const_iterator it = tasks.begin();
-         it != tasks.end();
-         ++it) {
-      graph->nodes.push_back(TaskGraph::Node(it->get(), 0u, leaf_tasks.size()));
+         it != tasks.end(); ++it) {
+      graph->nodes.push_back(
+          TaskGraph::Node(it->get(), 0u, 0u, leaf_tasks.size()));
 
       for (PerfTaskImpl::Vector::const_iterator leaf_it = leaf_tasks.begin();
            leaf_it != leaf_tasks.end();
@@ -255,7 +255,7 @@
     for (PerfTaskImpl::Vector::const_iterator it = top_level_tasks.begin();
          it != top_level_tasks.end();
          ++it) {
-      graph->nodes.push_back(TaskGraph::Node(it->get(), 0u, tasks.size()));
+      graph->nodes.push_back(TaskGraph::Node(it->get(), 0u, 0u, tasks.size()));
     }
   }
 
diff --git a/cc/raster/task_graph_work_queue.cc b/cc/raster/task_graph_work_queue.cc
index 655a005..95faedca 100644
--- a/cc/raster/task_graph_work_queue.cc
+++ b/cc/raster/task_graph_work_queue.cc
@@ -5,11 +5,41 @@
 #include "cc/raster/task_graph_work_queue.h"
 
 #include <algorithm>
+#include <map>
 #include <utility>
 
 #include "base/trace_event/trace_event.h"
 
 namespace cc {
+namespace {
+
+bool CompareTaskPriority(const TaskGraphWorkQueue::PrioritizedTask& a,
+                         const TaskGraphWorkQueue::PrioritizedTask& b) {
+  // In this system, numerically lower priority is run first.
+  return a.priority > b.priority;
+}
+
+class CompareTaskNamespacePriority {
+ public:
+  explicit CompareTaskNamespacePriority(uint16_t category)
+      : category_(category) {}
+
+  bool operator()(const TaskGraphWorkQueue::TaskNamespace* a,
+                  const TaskGraphWorkQueue::TaskNamespace* b) {
+    DCHECK(!a->ready_to_run_tasks.at(category_).empty());
+    DCHECK(!b->ready_to_run_tasks.at(category_).empty());
+
+    // Compare based on task priority of the ready_to_run_tasks heap .front()
+    // will hold the max element of the heap, except after pop_heap, when max
+    // element is moved to .back().
+    return CompareTaskPriority(a->ready_to_run_tasks.at(category_).front(),
+                               b->ready_to_run_tasks.at(category_).front());
+  }
+
+ private:
+  uint16_t category_;
+};
+}  // namespace
 
 TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {}
 
@@ -37,7 +67,9 @@
   }
 
   // Build new "ready to run" queue and remove nodes from old graph.
-  task_namespace.ready_to_run_tasks.clear();
+  for (auto& ready_to_run_tasks_it : task_namespace.ready_to_run_tasks) {
+    ready_to_run_tasks_it.second.clear();
+  }
   for (const TaskGraph::Node& node : graph->nodes) {
     // Remove any old nodes that are associated with this task. The result is
     // that the old graph is left with all nodes not present in this graph,
@@ -66,14 +98,17 @@
                   node.task) != task_namespace.running_tasks.end())
       continue;
 
-    task_namespace.ready_to_run_tasks.push_back(
-        PrioritizedTask(node.task, &task_namespace, node.priority));
+    task_namespace.ready_to_run_tasks[node.category].push_back(PrioritizedTask(
+        node.task, &task_namespace, node.category, node.priority));
   }
 
-  // Rearrange the elements in |ready_to_run_tasks| in such a way that they
-  // form a heap.
-  std::make_heap(task_namespace.ready_to_run_tasks.begin(),
-                 task_namespace.ready_to_run_tasks.end(), CompareTaskPriority);
+  // Rearrange the elements in each vector within |ready_to_run_tasks| in such a
+  // way that they form a heap.
+  for (auto& it : task_namespace.ready_to_run_tasks) {
+    auto& ready_to_run_tasks = it.second;
+    std::make_heap(ready_to_run_tasks.begin(), ready_to_run_tasks.end(),
+                   CompareTaskPriority);
+  }
 
   // Swap task graph.
   task_namespace.graph.Swap(graph);
@@ -100,41 +135,59 @@
   }
 
   // Build new "ready to run" task namespaces queue.
-  ready_to_run_namespaces_.clear();
-  for (auto& it : namespaces_) {
-    if (!it.second.ready_to_run_tasks.empty())
-      ready_to_run_namespaces_.push_back(&it.second);
+  for (auto& ready_to_run_namespaces_it : ready_to_run_namespaces_) {
+    ready_to_run_namespaces_it.second.clear();
+  }
+  for (auto& namespace_it : namespaces_) {
+    auto& task_namespace = namespace_it.second;
+    for (auto& ready_to_run_tasks_it : task_namespace.ready_to_run_tasks) {
+      auto& ready_to_run_tasks = ready_to_run_tasks_it.second;
+      uint16_t category = ready_to_run_tasks_it.first;
+      if (!ready_to_run_tasks.empty()) {
+        ready_to_run_namespaces_[category].push_back(&task_namespace);
+      }
+    }
   }
 
   // Rearrange the task namespaces in |ready_to_run_namespaces| in such a
   // way that they form a heap.
-  std::make_heap(ready_to_run_namespaces_.begin(),
-                 ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
+  for (auto& it : ready_to_run_namespaces_) {
+    uint16_t category = it.first;
+    auto& task_namespace = it.second;
+    std::make_heap(task_namespace.begin(), task_namespace.end(),
+                   CompareTaskNamespacePriority(category));
+  }
 }
 
-TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() {
-  DCHECK(!ready_to_run_namespaces_.empty());
+TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun(
+    uint16_t category) {
+  TaskNamespace::Vector& ready_to_run_namespaces =
+      ready_to_run_namespaces_[category];
+  DCHECK(!ready_to_run_namespaces.empty());
 
-  // Take top priority TaskNamespace from |ready_to_run_namespaces_|.
-  std::pop_heap(ready_to_run_namespaces_.begin(),
-                ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
-  TaskNamespace* task_namespace = ready_to_run_namespaces_.back();
-  ready_to_run_namespaces_.pop_back();
-  DCHECK(!task_namespace->ready_to_run_tasks.empty());
+  // Take top priority TaskNamespace from |ready_to_run_namespaces|.
+  std::pop_heap(ready_to_run_namespaces.begin(), ready_to_run_namespaces.end(),
+                CompareTaskNamespacePriority(category));
+  TaskNamespace* task_namespace = ready_to_run_namespaces.back();
+  ready_to_run_namespaces.pop_back();
+
+  PrioritizedTask::Vector& ready_to_run_tasks =
+      task_namespace->ready_to_run_tasks[category];
+  DCHECK(!ready_to_run_tasks.empty());
 
   // Take top priority task from |ready_to_run_tasks|.
-  std::pop_heap(task_namespace->ready_to_run_tasks.begin(),
-                task_namespace->ready_to_run_tasks.end(), CompareTaskPriority);
-  PrioritizedTask task = task_namespace->ready_to_run_tasks.back();
-  task_namespace->ready_to_run_tasks.pop_back();
+  std::pop_heap(ready_to_run_tasks.begin(), ready_to_run_tasks.end(),
+                CompareTaskPriority);
+  PrioritizedTask task = ready_to_run_tasks.back();
+  ready_to_run_tasks.pop_back();
 
-  // Add task namespace back to |ready_to_run_namespaces_| if not empty after
+  // Add task namespace back to |ready_to_run_namespaces| if not empty after
   // taking top priority task.
-  if (!task_namespace->ready_to_run_tasks.empty()) {
-    ready_to_run_namespaces_.push_back(task_namespace);
-    std::push_heap(ready_to_run_namespaces_.begin(),
-                   ready_to_run_namespaces_.end(),
-                   CompareTaskNamespacePriority);
+  if (!ready_to_run_tasks.empty()) {
+    ready_to_run_namespaces.push_back(task_namespace);
+    std::push_heap(ready_to_run_namespaces.begin(),
+                   ready_to_run_namespaces.end(),
+                   CompareTaskNamespacePriority(category));
   }
 
   // Add task to |running_tasks|.
@@ -164,19 +217,26 @@
     dependent_node.dependencies--;
     // Task is ready if it has no dependencies. Add it to |ready_to_run_tasks_|.
     if (!dependent_node.dependencies) {
-      bool was_empty = task_namespace->ready_to_run_tasks.empty();
-      task_namespace->ready_to_run_tasks.push_back(PrioritizedTask(
-          dependent_node.task, task_namespace, dependent_node.priority));
-      std::push_heap(task_namespace->ready_to_run_tasks.begin(),
-                     task_namespace->ready_to_run_tasks.end(),
+      PrioritizedTask::Vector& ready_to_run_tasks =
+          task_namespace->ready_to_run_tasks[dependent_node.category];
+
+      bool was_empty = ready_to_run_tasks.empty();
+      ready_to_run_tasks.push_back(
+          PrioritizedTask(dependent_node.task, task_namespace,
+                          dependent_node.category, dependent_node.priority));
+      std::push_heap(ready_to_run_tasks.begin(), ready_to_run_tasks.end(),
                      CompareTaskPriority);
+
       // Task namespace is ready if it has at least one ready to run task. Add
       // it to |ready_to_run_namespaces_| if it just become ready.
       if (was_empty) {
-        DCHECK(std::find(ready_to_run_namespaces_.begin(),
-                         ready_to_run_namespaces_.end(),
-                         task_namespace) == ready_to_run_namespaces_.end());
-        ready_to_run_namespaces_.push_back(task_namespace);
+        TaskNamespace::Vector& ready_to_run_namespaces =
+            ready_to_run_namespaces_[dependent_node.category];
+
+        DCHECK(std::find(ready_to_run_namespaces.begin(),
+                         ready_to_run_namespaces.end(),
+                         task_namespace) == ready_to_run_namespaces.end());
+        ready_to_run_namespaces.push_back(task_namespace);
       }
       ready_to_run_namespaces_has_heap_properties = false;
     }
@@ -185,9 +245,13 @@
   // Rearrange the task namespaces in |ready_to_run_namespaces_| in such a way
   // that they yet again form a heap.
   if (!ready_to_run_namespaces_has_heap_properties) {
-    std::make_heap(ready_to_run_namespaces_.begin(),
-                   ready_to_run_namespaces_.end(),
-                   CompareTaskNamespacePriority);
+    for (auto& it : ready_to_run_namespaces_) {
+      uint16_t category = it.first;
+      auto& ready_to_run_namespaces = it.second;
+      std::make_heap(ready_to_run_namespaces.begin(),
+                     ready_to_run_namespaces.end(),
+                     CompareTaskNamespacePriority(category));
+    }
   }
 
   // Finally add task to |completed_tasks_|.
@@ -209,7 +273,7 @@
 
   // Remove namespace if finished running tasks.
   DCHECK_EQ(0u, task_namespace.completed_tasks.size());
-  DCHECK_EQ(0u, task_namespace.ready_to_run_tasks.size());
+  DCHECK(!HasReadyToRunTasksInNamespace(&task_namespace));
   DCHECK_EQ(0u, task_namespace.running_tasks.size());
   namespaces_.erase(it);
 }
diff --git a/cc/raster/task_graph_work_queue.h b/cc/raster/task_graph_work_queue.h
index 8a46123..7b6840c 100644
--- a/cc/raster/task_graph_work_queue.h
+++ b/cc/raster/task_graph_work_queue.h
@@ -5,6 +5,7 @@
 #ifndef CC_RASTER_TASK_GRAPH_WORK_QUEUE_H_
 #define CC_RASTER_TASK_GRAPH_WORK_QUEUE_H_
 
+#include <algorithm>
 #include <map>
 #include <vector>
 
@@ -16,6 +17,11 @@
 // Implements a queue of incoming TaskGraph work. Designed for use by
 // implementations of TaskGraphRunner. Not thread safe, so the caller is
 // responsible for all necessary locking.
+//
+// Tasks in the queue are divided into categories. Tasks from a single graph may
+// be put into different categories, each of which is prioritized independently
+// from the others. It is up to the implementation of TaskGraphRunner to
+// define the meaning of the categories and handle them appropriately.
 class CC_EXPORT TaskGraphWorkQueue {
  public:
   struct TaskNamespace;
@@ -23,12 +29,19 @@
   struct PrioritizedTask {
     typedef std::vector<PrioritizedTask> Vector;
 
-    PrioritizedTask(Task* task, TaskNamespace* task_namespace, size_t priority)
-        : task(task), task_namespace(task_namespace), priority(priority) {}
+    PrioritizedTask(Task* task,
+                    TaskNamespace* task_namespace,
+                    uint16_t category,
+                    uint16_t priority)
+        : task(task),
+          task_namespace(task_namespace),
+          category(category),
+          priority(priority) {}
 
     Task* task;
     TaskNamespace* task_namespace;
-    size_t priority;
+    uint16_t category;
+    uint16_t priority;
   };
 
   // Helper classes and static methods used by dependent classes.
@@ -41,8 +54,9 @@
     // Current task graph.
     TaskGraph graph;
 
-    // Ordered set of tasks that are ready to run.
-    PrioritizedTask::Vector ready_to_run_tasks;
+    // Map from category to a vector of tasks that are ready to run for that
+    // category.
+    std::map<uint16_t, PrioritizedTask::Vector> ready_to_run_tasks;
 
     // Completed tasks not yet collected by origin thread.
     Task::Vector completed_tasks;
@@ -62,8 +76,8 @@
   // previous tasks in the graph being replaced.
   void ScheduleTasks(NamespaceToken token, TaskGraph* graph);
 
-  // Returns the next task to run paired with its namespace.
-  PrioritizedTask GetNextTaskToRun();
+  // Returns the next task to run for the given category.
+  PrioritizedTask GetNextTaskToRun(uint16_t category);
 
   // Marks a task as completed, adding it to its namespace's list of completed
   // tasks and updating the list of |ready_to_run_namespaces|.
@@ -84,13 +98,35 @@
     return &it->second;
   }
 
+  static bool HasReadyToRunTasksInNamespace(
+      const TaskNamespace* task_namespace) {
+    return std::find_if(task_namespace->ready_to_run_tasks.begin(),
+                        task_namespace->ready_to_run_tasks.end(),
+                        [](const std::pair<uint16_t, PrioritizedTask::Vector>&
+                               ready_to_run_tasks) {
+                          return !ready_to_run_tasks.second.empty();
+                        }) != task_namespace->ready_to_run_tasks.end();
+  }
+
   static bool HasFinishedRunningTasksInNamespace(
       const TaskNamespace* task_namespace) {
     return task_namespace->running_tasks.empty() &&
-           task_namespace->ready_to_run_tasks.empty();
+           !HasReadyToRunTasksInNamespace(task_namespace);
   }
 
-  bool HasReadyToRunTasks() const { return !ready_to_run_namespaces_.empty(); }
+  bool HasReadyToRunTasks() const {
+    return std::find_if(ready_to_run_namespaces_.begin(),
+                        ready_to_run_namespaces_.end(),
+                        [](const std::pair<uint16_t, TaskNamespace::Vector>&
+                               ready_to_run_namespaces) {
+                          return !ready_to_run_namespaces.second.empty();
+                        }) != ready_to_run_namespaces_.end();
+  }
+
+  bool HasReadyToRunTasksForCategory(uint16_t category) const {
+    auto found = ready_to_run_namespaces_.find(category);
+    return found != ready_to_run_namespaces_.end() && !found->second.empty();
+  }
 
   bool HasAnyNamespaces() const { return !namespaces_.empty(); }
 
@@ -102,6 +138,11 @@
                }) == namespaces_.end();
   }
 
+  const std::map<uint16_t, TaskNamespace::Vector>& ready_to_run_namespaces()
+      const {
+    return ready_to_run_namespaces_;
+  }
+
   // Helper function which ensures that graph dependencies were correctly
   // configured.
   static bool DependencyMismatch(const TaskGraph* graph);
@@ -116,29 +157,13 @@
     }
   };
 
-  static bool CompareTaskPriority(const PrioritizedTask& a,
-                                  const PrioritizedTask& b) {
-    // In this system, numerically lower priority is run first.
-    return a.priority > b.priority;
-  }
-
-  static bool CompareTaskNamespacePriority(const TaskNamespace* a,
-                                           const TaskNamespace* b) {
-    DCHECK(!a->ready_to_run_tasks.empty());
-    DCHECK(!b->ready_to_run_tasks.empty());
-
-    // Compare based on task priority of the ready_to_run_tasks heap .front()
-    // will hold the max element of the heap, except after pop_heap, when max
-    // element is moved to .back().
-    return CompareTaskPriority(a->ready_to_run_tasks.front(),
-                               b->ready_to_run_tasks.front());
-  }
-
   using TaskNamespaceMap =
       std::map<NamespaceToken, TaskNamespace, CompareToken>;
 
   TaskNamespaceMap namespaces_;
-  TaskNamespace::Vector ready_to_run_namespaces_;
+
+  // Map from category to a vector of ready to run namespaces for that category.
+  std::map<uint16_t, TaskNamespace::Vector> ready_to_run_namespaces_;
 
   // Provides a unique id to each NamespaceToken.
   int next_namespace_id_;
diff --git a/cc/raster/tile_task_worker_pool_perftest.cc b/cc/raster/tile_task_worker_pool_perftest.cc
index 1e1ff1c..70354413 100644
--- a/cc/raster/tile_task_worker_pool_perftest.cc
+++ b/cc/raster/tile_task_worker_pool_perftest.cc
@@ -223,13 +223,14 @@
 
       for (auto& decode_task : raster_task->dependencies()) {
         graph->nodes.push_back(
-            TaskGraph::Node(decode_task.get(), priority, 0u));
+            TaskGraph::Node(decode_task.get(), 0u /* group */, priority, 0u));
         graph->edges.push_back(
             TaskGraph::Edge(raster_task.get(), decode_task.get()));
       }
 
-      graph->nodes.push_back(TaskGraph::Node(
-          raster_task.get(), priority, raster_task->dependencies().size()));
+      graph->nodes.push_back(
+          TaskGraph::Node(raster_task.get(), 0u /* group */, priority,
+                          raster_task->dependencies().size()));
     }
   }
 
diff --git a/cc/raster/tile_task_worker_pool_unittest.cc b/cc/raster/tile_task_worker_pool_unittest.cc
index c5d3a416..941cd473 100644
--- a/cc/raster/tile_task_worker_pool_unittest.cc
+++ b/cc/raster/tile_task_worker_pool_unittest.cc
@@ -195,7 +195,8 @@
 
     for (RasterTaskVector::const_iterator it = tasks_.begin();
          it != tasks_.end(); ++it) {
-      graph_.nodes.emplace_back(it->get(), priority++, 0 /* dependencies */);
+      graph_.nodes.emplace_back(it->get(), 0 /* group */, priority++,
+                                0 /* dependencies */);
     }
 
     tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&graph_);
diff --git a/cc/test/data/background_filter_blur_outsets.png b/cc/test/data/background_filter_blur_outsets.png
index 3293ab86..e82c7d1 100644
--- a/cc/test/data/background_filter_blur_outsets.png
+++ b/cc/test/data/background_filter_blur_outsets.png
Binary files differ
diff --git a/cc/test/data/background_filter_rotated_gl.png b/cc/test/data/background_filter_rotated_gl.png
index b9b16ad..ccedeb8 100644
--- a/cc/test/data/background_filter_rotated_gl.png
+++ b/cc/test/data/background_filter_rotated_gl.png
Binary files differ
diff --git a/cc/test/task_graph_runner_test_template.cc b/cc/test/task_graph_runner_test_template.cc
index ba9d4ccf..6797de2e 100644
--- a/cc/test/task_graph_runner_test_template.cc
+++ b/cc/test/task_graph_runner_test_template.cc
@@ -65,13 +65,13 @@
     scoped_refptr<FakeTaskImpl> new_task(
         new FakeTaskImpl(this, it->namespace_index, it->id));
     new_graph.nodes.push_back(
-        TaskGraph::Node(new_task.get(), it->priority, 0u));
+        TaskGraph::Node(new_task.get(), it->category, it->priority, 0u));
     for (unsigned i = 0; i < it->dependent_count; ++i) {
       scoped_refptr<FakeDependentTaskImpl> new_dependent_task(
           new FakeDependentTaskImpl(this, it->namespace_index,
                                     it->dependent_id));
-      new_graph.nodes.push_back(
-          TaskGraph::Node(new_dependent_task.get(), it->priority, 1u));
+      new_graph.nodes.push_back(TaskGraph::Node(
+          new_dependent_task.get(), it->category, it->priority, 1u));
       new_graph.edges.push_back(
           TaskGraph::Edge(new_task.get(), new_dependent_task.get()));
 
diff --git a/cc/test/task_graph_runner_test_template.h b/cc/test/task_graph_runner_test_template.h
index d3989b9..d417543 100644
--- a/cc/test/task_graph_runner_test_template.h
+++ b/cc/test/task_graph_runner_test_template.h
@@ -24,17 +24,20 @@
              unsigned id,
              unsigned dependent_id,
              unsigned dependent_count,
+             unsigned category,
              unsigned priority)
         : namespace_index(namespace_index),
           id(id),
           dependent_id(dependent_id),
           dependent_count(dependent_count),
+          category(category),
           priority(priority) {}
 
     int namespace_index;
     unsigned id;
     unsigned dependent_id;
     unsigned dependent_count;
+    unsigned category;
     unsigned priority;
   };
 
@@ -126,8 +129,8 @@
     EXPECT_EQ(0u, this->run_task_ids(i).size());
     EXPECT_EQ(0u, this->on_task_completed_ids(i).size());
 
-    this->ScheduleTasks(i,
-                        std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 0u, 0u)));
+    this->ScheduleTasks(
+        i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 0u, 0u, 0u)));
   }
 
   for (int i = 0; i < kNamespaceCount; ++i) {
@@ -138,8 +141,8 @@
   }
 
   for (int i = 0; i < kNamespaceCount; ++i)
-    this->ScheduleTasks(i,
-                        std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 1u, 0u)));
+    this->ScheduleTasks(
+        i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 1u, 0u, 0u)));
 
   for (int i = 0; i < kNamespaceCount; ++i) {
     this->RunAllTasks(i);
@@ -149,8 +152,8 @@
   }
 
   for (int i = 0; i < kNamespaceCount; ++i)
-    this->ScheduleTasks(i,
-                        std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 2u, 0u)));
+    this->ScheduleTasks(
+        i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 2u, 0u, 0u)));
 
   for (int i = 0; i < kNamespaceCount; ++i) {
     this->RunAllTasks(i);
@@ -167,7 +170,7 @@
   for (int i = 0; i < kNamespaceCount; ++i) {
     this->ScheduleTasks(i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 1u,
                                                              1u,  // 1 dependent
-                                                             0u)));
+                                                             0u, 0u)));
   }
 
   for (int i = 0; i < kNamespaceCount; ++i) {
@@ -185,7 +188,7 @@
     this->ScheduleTasks(i,
                         std::vector<TaskInfo>(1, TaskInfo(i, 2u, 3u,
                                                           2u,  // 2 dependents
-                                                          0u)));
+                                                          0u, 0u)));
   }
 
   for (int i = 0; i < kNamespaceCount; ++i) {
@@ -201,7 +204,60 @@
   }
 }
 
-REGISTER_TYPED_TEST_CASE_P(TaskGraphRunnerTest, Basic, Dependencies);
+TYPED_TEST_P(TaskGraphRunnerTest, Categorys) {
+  const int kNamespaceCount = TaskGraphRunnerTestBase::kNamespaceCount;
+  const unsigned kCategoryCount = 3;
+  using TaskInfo = TaskGraphRunnerTestBase::TaskInfo;
+
+  for (int i = 0; i < kNamespaceCount; ++i) {
+    EXPECT_EQ(0u, this->run_task_ids(i).size());
+    EXPECT_EQ(0u, this->on_task_completed_ids(i).size());
+    std::vector<TaskInfo> tasks;
+    for (unsigned j = 0; j < kCategoryCount; ++j) {
+      tasks.emplace_back(i, 0u, 0u, 0u, j, 0u);
+    }
+    this->ScheduleTasks(i, tasks);
+  }
+
+  for (int i = 0; i < kNamespaceCount; ++i) {
+    this->RunAllTasks(i);
+
+    EXPECT_EQ(kCategoryCount, this->run_task_ids(i).size());
+    EXPECT_EQ(kCategoryCount, this->on_task_completed_ids(i).size());
+  }
+
+  for (int i = 0; i < kNamespaceCount; ++i) {
+    std::vector<TaskInfo> tasks;
+    for (unsigned j = 0; j < kCategoryCount; ++j) {
+      tasks.emplace_back(i, 0u, 0u, 1u, j, 0u);
+    }
+    this->ScheduleTasks(i, tasks);
+  }
+
+  for (int i = 0; i < kNamespaceCount; ++i) {
+    this->RunAllTasks(i);
+
+    EXPECT_EQ(kCategoryCount * 3u, this->run_task_ids(i).size());
+    EXPECT_EQ(kCategoryCount * 2u, this->on_task_completed_ids(i).size());
+  }
+
+  for (int i = 0; i < kNamespaceCount; ++i) {
+    std::vector<TaskInfo> tasks;
+    for (unsigned j = 0; j < kCategoryCount; ++j) {
+      tasks.emplace_back(i, 0u, 0u, 2u, j, 0u);
+    }
+    this->ScheduleTasks(i, tasks);
+  }
+
+  for (int i = 0; i < kNamespaceCount; ++i) {
+    this->RunAllTasks(i);
+
+    EXPECT_EQ(kCategoryCount * 6u, this->run_task_ids(i).size());
+    EXPECT_EQ(kCategoryCount * 3u, this->on_task_completed_ids(i).size());
+  }
+}
+
+REGISTER_TYPED_TEST_CASE_P(TaskGraphRunnerTest, Basic, Dependencies, Categorys);
 
 template <typename TaskRunnerTestDelegate>
 using SingleThreadTaskGraphRunnerTest =
@@ -215,8 +271,8 @@
 
   for (int i = 0; i < kNamespaceCount; ++i) {
     TaskInfo tasks[] = {
-        TaskInfo(i, 0u, 2u, 1u, 1u),  // Priority 1
-        TaskInfo(i, 1u, 3u, 1u, 0u)   // Priority 0
+        TaskInfo(i, 0u, 2u, 1u, 0u, 1u),  // Priority 1
+        TaskInfo(i, 1u, 3u, 1u, 0u, 0u)   // Priority 0
     };
     this->ScheduleTasks(i,
                         std::vector<TaskInfo>(tasks, tasks + arraysize(tasks)));
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 6ae1235..c3a8482 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -171,7 +171,10 @@
                       [task](const TaskGraph::Node& node) {
                         return node.task == task;
                       }) == graph->nodes.end());
-  graph->nodes.push_back(TaskGraph::Node(task, priority, dependencies));
+
+  // TODO(ericrk): Add in more logic around category selection.
+  graph->nodes.push_back(
+      TaskGraph::Node(task, 0 /* category */, priority, dependencies));
 }
 
 void InsertNodesForRasterTask(TaskGraph* graph,
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index bd38dd0..33a7683 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -75,8 +75,8 @@
   blur->SetBackgroundFilters(filters);
 
 #if defined(OS_WIN)
-  // Windows has 2596 pixels off by at most 2: crbug.com/259922
-  float percentage_pixels_large_error = 6.5f;  // 2596px / (200*200), rounded up
+  // Windows has 7.6975% pixels by at most 2: crbug.com/259922
+  float percentage_pixels_large_error = 7.7f;
   float percentage_pixels_small_error = 0.0f;
   float average_error_allowed_in_bad_pixels = 1.f;
   int large_error_allowed = 2;
@@ -385,8 +385,8 @@
     filter->SetBackgroundFilters(filters);
 
 #if defined(OS_WIN)
-    // Windows has 994 pixels off by at most 2: crbug.com/225027
-    float percentage_pixels_large_error = 2.5f;  // 994px / (200*200)
+    // Windows has 2.5875% pixels off by at most 2: crbug.com/225027
+    float percentage_pixels_large_error = 2.6f;  // 994px / (200*200)
     float percentage_pixels_small_error = 0.0f;
     float average_error_allowed_in_bad_pixels = 1.f;
     int large_error_allowed = 2;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index b90cce012..43828a7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1268,6 +1268,7 @@
     public void onOverviewModeStartedShowing(boolean showToolbar) {
         if (mFindToolbarManager != null) mFindToolbarManager.hideToolbar();
         if (getAssistStatusHandler() != null) getAssistStatusHandler().updateAssistState();
+        if (getAppMenuHandler() != null) getAppMenuHandler().hideAppMenu();
         ApiCompatibilityUtils.setStatusBarColor(getWindow(), Color.BLACK);
         StartupMetrics.getInstance().recordOpenedTabSwitcher();
     }
@@ -1277,6 +1278,7 @@
 
     @Override
     public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
+        if (getAppMenuHandler() != null) getAppMenuHandler().hideAppMenu();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
index d2552e5..d8a3cc1c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
@@ -111,6 +111,7 @@
         } else if (!event.isCtrlPressed() && !event.isAltPressed()
                 && keyCode != KeyEvent.KEYCODE_F3
                 && keyCode != KeyEvent.KEYCODE_F5
+                && keyCode != KeyEvent.KEYCODE_F10
                 && keyCode != KeyEvent.KEYCODE_FORWARD) {
             return false;
         }
@@ -133,7 +134,9 @@
             case CTRL | SHIFT | KeyEvent.KEYCODE_N:
                 activity.onMenuOrKeyboardAction(R.id.new_incognito_tab_menu_id, false);
                 return true;
+            case ALT | KeyEvent.KEYCODE_E:
             case ALT | KeyEvent.KEYCODE_F:
+            case KeyEvent.KEYCODE_F10:
             case KeyEvent.KEYCODE_BUTTON_Y:
                 activity.onMenuOrKeyboardAction(R.id.show_menu, false);
                 return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
index e880603..99e3218 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
@@ -4,8 +4,12 @@
 
 package org.chromium.chrome.browser.compositor.bottombar;
 
+import android.app.Activity;
 import android.content.Context;
 
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.PanelPriority;
@@ -22,7 +26,7 @@
  * Controls the Overlay Panel.
  */
 public class OverlayPanel extends ContextualSearchPanelAnimation
-        implements OverlayPanelContentFactory {
+        implements ActivityStateListener, OverlayPanelContentFactory {
 
     /**
      * The extra dp added around the close button touch target.
@@ -129,13 +133,22 @@
      * Destroy the native components associated with this panel's content.
      */
     public void destroy() {
+        closePanel(StateChangeReason.UNKNOWN, false);
+        ApplicationStatus.unregisterActivityStateListener(this);
+    }
+
+    /**
+     * Destroy the components associated with this panel. This should be overridden by panel
+     * implementations to destroy text views and other elements.
+     */
+    protected void destroyComponents() {
         destroyOverlayPanelContent();
     }
 
     @Override
     protected void onClosed(StateChangeReason reason) {
+        destroyComponents();
         mPanelManager.notifyPanelClosed(this, reason);
-        destroy();
     }
 
     // ============================================================================================
@@ -217,6 +230,9 @@
      */
     public void setChromeActivity(ChromeActivity activity) {
         mActivity = activity;
+        if (mActivity != null) {
+            ApplicationStatus.registerStateListenerForActivity(this, mActivity);
+        }
     }
 
     /**
@@ -251,6 +267,18 @@
     }
 
     // ============================================================================================
+    // ActivityStateListener
+    // ============================================================================================
+
+    @Override
+    public void onActivityStateChange(Activity activity, int newState) {
+        if (newState == ActivityState.RESUMED || newState == ActivityState.STOPPED
+                || newState == ActivityState.DESTROYED) {
+            closePanel(StateChangeReason.UNKNOWN, false);
+        }
+    }
+
+    // ============================================================================================
     // Content
     // ============================================================================================
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index bc8550d..3be5c5f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -4,10 +4,12 @@
 
 package org.chromium.chrome.browser.compositor.bottombar.contextualsearch;
 
+import android.app.Activity;
 import android.content.Context;
 import android.os.Handler;
 import android.view.View.MeasureSpec;
 
+import org.chromium.base.ActivityState;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayContentProgressObserver;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
@@ -73,17 +75,6 @@
         mPanelMetrics = new ContextualSearchPanelMetrics();
     }
 
-    /**
-     * Destroy the panel's components.
-     */
-    @Override
-    public void destroy() {
-        super.destroy();
-        destroyPromoView();
-        destroyPeekPromoControl();
-        destroySearchBarControl();
-    }
-
     @Override
     public OverlayPanelContent createNewOverlayPanelContent() {
         OverlayPanelContent overlayPanelContent = new OverlayPanelContent(
@@ -313,6 +304,22 @@
     // ============================================================================================
 
     @Override
+    protected void destroyComponents() {
+        super.destroyComponents();
+        destroyPromoView();
+        destroyPeekPromoControl();
+        destroySearchBarControl();
+    }
+
+    @Override
+    public void onActivityStateChange(Activity activity, int newState) {
+        super.onActivityStateChange(activity, newState);
+        if (newState == ActivityState.PAUSED) {
+            mManagementDelegate.logCurrentState();
+        }
+    }
+
+    @Override
     public PanelPriority getPriority() {
         return PanelPriority.HIGH;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java
index 015f302..6acf810 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java
@@ -146,14 +146,22 @@
 
     @Override
     protected void closePanel(StateChangeReason reason, boolean animate) {
-        if (!mIsAnimatingPanelClosing) {
-            if (animate) {
-                mIsAnimatingPanelClosing = true;
-                animatePanelToState(PanelState.CLOSED, reason);
+        // If close without animation is called while the panel is already animating closed, cancel
+        // the animation and finish closing immediately.
+        if (mIsAnimatingPanelClosing) {
+            if (!animate) {
+                cancelAnimation(this, Property.PANEL_HEIGHT);
             } else {
-                resizePanelToState(PanelState.CLOSED, reason);
+                return;
             }
         }
+
+        if (animate) {
+            mIsAnimatingPanelClosing = true;
+            animatePanelToState(PanelState.CLOSED, reason);
+        } else {
+            resizePanelToState(PanelState.CLOSED, reason);
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java
index a0f7c56..6fb41dfe 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/readermode/ReaderModePanel.java
@@ -67,14 +67,6 @@
         mContentViewDelegate = contentViewDelegate;
     }
 
-    /**
-     * Destroy the panel's components.
-     */
-    public void destroy() {
-        super.destroy();
-        destroyReaderModeBarControl();
-    }
-
     @Override
     public OverlayPanelContent createNewOverlayPanelContent() {
         OverlayContentDelegate delegate = new OverlayContentDelegate() {
@@ -200,6 +192,12 @@
     // ============================================================================================
 
     @Override
+    public void destroyComponents() {
+        super.destroyComponents();
+        destroyReaderModeBarControl();
+    }
+
+    @Override
     public PanelPriority getPriority() {
         return PanelPriority.MEDIUM;
     }
@@ -212,6 +210,10 @@
     @Override
     protected void updatePanelForCloseOrPeek(float percent) {
         super.updatePanelForCloseOrPeek(percent);
+
+        // Do not update the panel text if the panel was closed immediately.
+        if (percent < 0.01f) return;
+
         getReaderModeBarControl().setBarText(R.string.reader_view_text);
         mReaderBarTextOpacity = 1.0f;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagementDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagementDelegate.java
index b587693..6df690b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagementDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagementDelegate.java
@@ -86,4 +86,9 @@
      * @return An OverlayContentDelegate to watch events on the panel's content.
      */
     OverlayContentDelegate getOverlayContentDelegate();
+
+    /**
+     * Log the current state of Contextual Search.
+     */
+    void logCurrentState();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index 742ea2b..ce7689c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
-import android.app.Activity;
 import android.content.Context;
 import android.text.TextUtils;
 import android.view.View;
@@ -12,9 +11,6 @@
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
 
-import org.chromium.base.ActivityState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.SysUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -72,7 +68,7 @@
 public class ContextualSearchManager extends ContextualSearchObservable
         implements ContextualSearchManagementDelegate,
                 ContextualSearchNetworkCommunicator, ContextualSearchSelectionHandler,
-                ContextualSearchClient, ActivityStateListener {
+                ContextualSearchClient {
 
     private static final String TAG = "ContextualSearch";
 
@@ -222,7 +218,6 @@
         mDidStartLoadingResolvedSearchRequest = false;
         mWereSearchResultsSeen = false;
         mNetworkCommunicator = this;
-        ApplicationStatus.registerStateListenerForActivity(this, mActivity);
         mIsInitialized = true;
     }
 
@@ -262,7 +257,6 @@
         nativeDestroy(mNativeContextualSearchManagerPtr);
         stopListeningForHideNotifications();
         mTabRedirectHandler.clear();
-        ApplicationStatus.unregisterActivityStateListener(this);
         if (mFindToolbarManager != null) {
             mFindToolbarManager.removeObserver(mFindToolbarObserver);
             mFindToolbarManager = null;
@@ -601,16 +595,6 @@
         }
     }
 
-    @Override
-    public void onActivityStateChange(Activity activity, int newState) {
-        if (newState == ActivityState.RESUMED || newState == ActivityState.STOPPED
-                || newState == ActivityState.DESTROYED) {
-            hideContextualSearch(StateChangeReason.UNKNOWN);
-        } else if (newState == ActivityState.PAUSED) {
-            mPolicy.logCurrentState(getBaseContentView());
-        }
-    }
-
     /**
      * Clears our private member referencing the native manager.
      */
@@ -1110,6 +1094,13 @@
     }
 
     @Override
+    public void logCurrentState() {
+        if (mPolicy != null) {
+            mPolicy.logCurrentState(getBaseContentView());
+        }
+    }
+
+    @Override
     public void logPromoOutcome() {
         ContextualSearchUma.logPromoOutcome(mWasActivatedByTap);
         mDidLogPromoOutcome = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 29b1996..7a1339f3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -472,7 +472,7 @@
         if (id == R.id.focus_url_bar || id == R.id.all_bookmarks_menu_id
                 || id == R.id.bookmark_this_page_id || id == R.id.print_id || id == R.id.help_id
                 || id == R.id.recent_tabs_menu_id || id == R.id.new_incognito_tab_menu_id
-                || id == R.id.new_tab_menu_id) {
+                || id == R.id.new_tab_menu_id || id == R.id.open_history_menu_id) {
             return true;
         } else if (id == R.id.open_in_chrome_id) {
             String url = getTabModelSelector().getCurrentTab().getUrl();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index ad4bd08..90d84a2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -327,6 +327,14 @@
         return getManager(notificationId) != null;
     }
 
+    @VisibleForTesting
+    @Nullable
+    protected static MediaNotificationInfo getNotificationInfoForTesting(int notificationId) {
+        MediaNotificationManager manager = getManager(notificationId);
+        if (manager == null) return null;
+        return manager.mMediaNotificationInfo;
+    }
+
     private final Context mContext;
 
     // ListenerService running for the notification. Only non-null when showing.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
index 4dce275..b0f07d4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
@@ -142,6 +142,16 @@
         }
 
         @Override
+        public void onTitleUpdated(Tab tab) {
+            assert tab == mTab;
+            if (mNotificationInfoBuilder == null) return;
+
+            mNotificationInfoBuilder.setTitle(sanitizeMediaTitle(mTab.getTitle()));
+            MediaNotificationManager.show(ApplicationStatus.getApplicationContext(),
+                    mNotificationInfoBuilder.build());
+        }
+
+        @Override
         public void onDestroyed(Tab tab) {
             assert mTab == tab;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/qualityprovider/ExternalEstimateProviderAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/net/qualityprovider/ExternalEstimateProviderAndroid.java
index a7a806e..18fa8692 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/net/qualityprovider/ExternalEstimateProviderAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/net/qualityprovider/ExternalEstimateProviderAndroid.java
@@ -14,7 +14,7 @@
 /**
  * This class provides a base class implementation and may be overridden on operating systems that
  * provide more useful APIs. All method calls from native code will happen on the thread where
- * thisobject is constructed, but calls from subclasses (specifically,
+ * this object is constructed, but calls from subclasses (specifically,
  * {@link #notifyExternalEstimateProviderAndroidUpdate()} can happen on other threads.
  */
 @JNINamespace("chrome::android")
@@ -35,14 +35,6 @@
     }
 
     /**
-     * Temporary constructor.
-     * TODO(bauerb): Remove when the downstream subclass is updated.
-     */
-    protected ExternalEstimateProviderAndroid() {
-        this(0);
-    }
-
-    /**
      * Creates an instance of {@link ExternalEstimateProviderAndroid}.
      */
     protected ExternalEstimateProviderAndroid(long nativePtr) {
@@ -118,7 +110,6 @@
         }
     }
 
-    // TODO(bauerb): Make this private when the downstream subclass is updated.
-    protected native void nativeNotifyExternalEstimateProviderAndroidUpdate(
+    private native void nativeNotifyExternalEstimateProviderAndroidUpdate(
             long nativeExternalEstimateProviderAndroid);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/DocumentRecentTabsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/DocumentRecentTabsManager.java
index 04b5f5a..48d8bfa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/DocumentRecentTabsManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/DocumentRecentTabsManager.java
@@ -116,6 +116,7 @@
         ThreadUtils.postOnUiThreadDelayed(new Runnable() {
             @Override
             public void run() {
+                if (isDestroyed()) return;
                 DocumentRecentTabsManager.super.openForeignSessionTab(
                         session, tab, WindowOpenDisposition.NEW_FOREGROUND_TAB);
                 if (mDialog != null) mDialog.dismiss();
@@ -131,6 +132,7 @@
         ThreadUtils.postOnUiThreadDelayed(new Runnable() {
             @Override
             public void run() {
+                if (isDestroyed()) return;
                 DocumentRecentTabsManager.super.openRecentlyClosedTab(
                         tab, WindowOpenDisposition.NEW_FOREGROUND_TAB);
                 if (mDialog != null) mDialog.dismiss();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
index 445f69b..5f2749c0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
@@ -67,6 +67,7 @@
     private SigninManager mSignInManager;
     private UpdatedCallback mUpdatedCallback;
     private ProfileDataCache mProfileDataCache;
+    private boolean mIsDestroyed;
 
     /**
      * Create an RecentTabsManager to be used with RecentTabsPage and RecentTabsRowAdapter.
@@ -98,6 +99,7 @@
      * Should be called when this object is no longer needed. Performs necessary listener tear down.
      */
     public void destroy() {
+        mIsDestroyed = true;
         AndroidSyncSettings.unregisterObserver(mContext, this);
 
         mSignInManager.removeSignInStateObserver(this);
@@ -125,6 +127,13 @@
         InvalidationController.get(mContext).onRecentTabsPageClosed();
     }
 
+    /**
+     * Returns true if destroy() has been called.
+     */
+    public boolean isDestroyed() {
+        return mIsDestroyed;
+    }
+
     private static ForeignSessionHelper buildForeignSessionHelper(Profile profile) {
         return new ForeignSessionHelper(profile);
     }
@@ -420,6 +429,7 @@
         ThreadUtils.runOnUiThread(new Runnable() {
             @Override
             public void run() {
+                if (mIsDestroyed) return;
                 updateForeignSessions();
                 postUpdate();
                 for (AndroidSyncSettingsObserver observer : mObservers) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java
new file mode 100644
index 0000000..d505fbe8
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java
@@ -0,0 +1,132 @@
+// Copyright 2015 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.media.ui;
+
+import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
+import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_PHONE;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.ObserverList;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.Restriction;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.test.ChromeActivityTestCaseBase;
+import org.chromium.chrome.test.util.browser.TabTitleObserver;
+import org.chromium.content.browser.test.util.JavaScriptUtils;
+import org.chromium.content_public.browser.WebContentsObserver;
+
+/**
+ * Test of media notifications to see whether the text updates when the tab title changes
+ */
+public class NotificationTitleUpdatedTest extends ChromeActivityTestCaseBase<ChromeActivity> {
+    private static final int NOTIFICATION_ID = R.id.media_playback_notification;
+
+    private Tab mTab;
+
+    public NotificationTitleUpdatedTest() {
+        super(ChromeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mTab = getActivity().getActivityTab();
+        simulateUpdateTitle(mTab, "title1");
+    }
+
+    @SmallTest
+    public void testSessionStatePlaying() throws InterruptedException {
+        simulateMediaSessionStateChanged(mTab, true, false);
+        assertTitleMatches("title1");
+        simulateUpdateTitle(mTab, "title2");
+        assertTitleMatches("title2");
+    }
+
+    @SmallTest
+    public void testSessionStatePaused() {
+        simulateMediaSessionStateChanged(mTab, true, true);
+        assertTitleMatches("title1");
+        simulateUpdateTitle(mTab, "title2");
+        assertTitleMatches("title2");
+    }
+
+    @SmallTest
+    public void testSessionStateUncontrollable() {
+        simulateMediaSessionStateChanged(mTab, true, false);
+        assertTitleMatches("title1");
+        simulateMediaSessionStateChanged(mTab, false, false);
+        simulateUpdateTitle(mTab, "title2");
+    }
+
+    /**
+     * Test if a notification accepts the title update from another tab, using the following steps:
+     *   1. set the title of mTab, start the media session, a notification should show up;
+     *   2. stop the media session of mTab, the notification shall hide;
+     *   3. create newTab, set the title of mTab, start the media session of mTab,
+     *      a notification should show up;
+     *   4. change the title of newTab and then mTab to different names,
+     *      the notification should have the title of newTab.
+     */
+    @SmallTest
+    @Restriction({RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
+    public void testMultipleTabs() throws Throwable {
+        simulateMediaSessionStateChanged(mTab, true, false);
+        assertTitleMatches("title1");
+        simulateMediaSessionStateChanged(mTab, false, false);
+
+        Tab newTab = loadUrlInNewTab("about:blank");
+        assertNotNull(newTab);
+
+        simulateMediaSessionStateChanged(newTab, true, false);
+        simulateUpdateTitle(newTab, "title3");
+        simulateUpdateTitle(mTab, "title2");
+        assertTitleMatches("title3");
+    }
+
+    @Override
+    public void startMainActivity() throws InterruptedException {
+        startMainActivityOnBlankPage();
+    }
+
+    private void simulateMediaSessionStateChanged(
+            final Tab tab, final boolean isControllable, final boolean isSuspended) {
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                @Override
+                public void run() {
+                    ObserverList.RewindableIterator<WebContentsObserver> observers =
+                            tab.getWebContents().getObserversForTesting();
+                    while (observers.hasNext()) {
+                        observers.next().mediaSessionStateChanged(
+                                isControllable, isSuspended);
+                    }
+                }
+            });
+    }
+
+    private void simulateUpdateTitle(Tab tab, String title) {
+        try {
+            TabTitleObserver observer = new TabTitleObserver(tab, title);
+            JavaScriptUtils.executeJavaScriptAndWaitForResult(
+                    tab.getWebContents(),
+                    "document.title = '" + title + "';");
+            observer.waitForTitleUpdate(5);
+        } catch (Exception e) {
+            throw new RuntimeException(e + "failed to update title");
+        }
+    }
+
+    void assertTitleMatches(final String title) {
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                @Override
+                public void run() {
+                    assertEquals(title, MediaNotificationManager
+                            .getNotificationInfoForTesting(NOTIFICATION_ID).title);
+                }
+            });
+    }
+}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 4ff216c..05b70ce 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -478,7 +478,7 @@
   if (enable_nacl) {
     sources +=
         rebase_path(gypi_values.chrome_browser_nacl_sources, ".", "//chrome")
-    deps += [ "//components/nacl:nacl_browser" ]
+    deps += [ "//components/nacl/browser" ]
   }
 
   if (enable_configuration_policy) {
diff --git a/chrome/browser/android/accessibility/font_size_prefs_android.cc b/chrome/browser/android/accessibility/font_size_prefs_android.cc
index 56e94ed..528b4c0 100644
--- a/chrome/browser/android/accessibility/font_size_prefs_android.cc
+++ b/chrome/browser/android/accessibility/font_size_prefs_android.cc
@@ -12,6 +12,8 @@
 #include "chrome/common/pref_names.h"
 #include "jni/FontSizePrefs_jni.h"
 
+using base::android::JavaRef;
+
 FontSizePrefsAndroid::FontSizePrefsAndroid(JNIEnv* env, jobject obj)
     : pref_service_(ProfileManager::GetActiveUserProfile()->GetPrefs()) {
   java_ref_.Reset(env, obj);
@@ -31,28 +33,32 @@
 }
 
 void FontSizePrefsAndroid::SetFontScaleFactor(JNIEnv* env,
-                                              jobject obj,
+                                              const JavaRef<jobject>& obj,
                                               jfloat font_size) {
   pref_service_->SetDouble(prefs::kWebKitFontScaleFactor,
                            static_cast<double>(font_size));
 }
 
-float FontSizePrefsAndroid::GetFontScaleFactor(JNIEnv* env, jobject obj) {
+float FontSizePrefsAndroid::GetFontScaleFactor(
+    JNIEnv* env,
+    const JavaRef<jobject>& obj) {
   return pref_service_->GetDouble(prefs::kWebKitFontScaleFactor);
 }
 
 void FontSizePrefsAndroid::SetForceEnableZoom(JNIEnv* env,
-                                              jobject obj,
+                                              const JavaRef<jobject>& obj,
                                               jboolean enabled) {
   pref_service_->SetBoolean(prefs::kWebKitForceEnableZoom, enabled);
 }
 
-bool FontSizePrefsAndroid::GetForceEnableZoom(JNIEnv* env, jobject obj) {
+bool FontSizePrefsAndroid::GetForceEnableZoom(
+    JNIEnv* env,
+    const JavaRef<jobject>& obj) {
   return pref_service_->GetBoolean(prefs::kWebKitForceEnableZoom);
 }
 
 void FontSizePrefsAndroid::AddObserver(JNIEnv* env,
-                                       jobject obj,
+                                       const JavaRef<jobject>& obj,
                                        jlong observer_ptr) {
   FontSizePrefsObserverAndroid* font_size_prefs_observer_android =
       reinterpret_cast<FontSizePrefsObserverAndroid*>(observer_ptr);
@@ -60,7 +66,7 @@
 }
 
 void FontSizePrefsAndroid::RemoveObserver(JNIEnv* env,
-                                          jobject obj,
+                                          const JavaRef<jobject>& obj,
                                           jlong observer_ptr) {
   FontSizePrefsObserverAndroid* font_size_prefs_observer_android =
       reinterpret_cast<FontSizePrefsObserverAndroid*>(observer_ptr);
@@ -81,7 +87,7 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   FOR_EACH_OBSERVER(Observer,
                     observers_,
-                    OnChangeFontSize(GetFontScaleFactor(env, java_ref_.obj())));
+                    OnChangeFontSize(GetFontScaleFactor(env, java_ref_)));
 }
 
 void FontSizePrefsAndroid::OnForceEnableZoomPrefsChanged() {
@@ -89,7 +95,7 @@
   FOR_EACH_OBSERVER(
       Observer,
       observers_,
-      OnChangeForceEnableZoom(GetForceEnableZoom(env, java_ref_.obj())));
+      OnChangeForceEnableZoom(GetForceEnableZoom(env, java_ref_)));
 }
 
 FontSizePrefsObserverAndroid::FontSizePrefsObserverAndroid(JNIEnv* env,
@@ -104,8 +110,9 @@
   return RegisterNativesImpl(env);
 }
 
-void FontSizePrefsObserverAndroid::DestroyObserverAndroid(JNIEnv* env,
-                                                          jobject obj) {
+void FontSizePrefsObserverAndroid::DestroyObserverAndroid(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   delete this;
 }
 
diff --git a/chrome/browser/android/accessibility/font_size_prefs_android.h b/chrome/browser/android/accessibility/font_size_prefs_android.h
index c89639e..4ef5432e 100644
--- a/chrome/browser/android/accessibility/font_size_prefs_android.h
+++ b/chrome/browser/android/accessibility/font_size_prefs_android.h
@@ -27,13 +27,23 @@
   FontSizePrefsAndroid(JNIEnv* env, jobject obj);
   ~FontSizePrefsAndroid();
 
-  void SetFontScaleFactor(JNIEnv* env, jobject obj, jfloat font);
-  float GetFontScaleFactor(JNIEnv* env, jobject obj);
-  void SetForceEnableZoom(JNIEnv* env, jobject obj, jboolean enabled);
-  bool GetForceEnableZoom(JNIEnv* env, jobject obj);
+  void SetFontScaleFactor(JNIEnv* env,
+                          const base::android::JavaRef<jobject>& obj,
+                          jfloat font);
+  float GetFontScaleFactor(JNIEnv* env,
+                           const base::android::JavaRef<jobject>& obj);
+  void SetForceEnableZoom(JNIEnv* env,
+                          const base::android::JavaRef<jobject>& obj,
+                          jboolean enabled);
+  bool GetForceEnableZoom(JNIEnv* env,
+                          const base::android::JavaRef<jobject>& obj);
 
-  void AddObserver(JNIEnv* env, jobject obj, jlong obs);
-  void RemoveObserver(JNIEnv* env, jobject obj, jlong obs);
+  void AddObserver(JNIEnv* env,
+                   const base::android::JavaRef<jobject>& obj,
+                   jlong obs);
+  void RemoveObserver(JNIEnv* env,
+                      const base::android::JavaRef<jobject>& obj,
+                      jlong obs);
 
   static bool Register(JNIEnv* env);
 
@@ -59,7 +69,8 @@
  public:
   FontSizePrefsObserverAndroid(JNIEnv* env, jobject obj);
   virtual ~FontSizePrefsObserverAndroid();
-  void DestroyObserverAndroid(JNIEnv* env, jobject obj);
+  void DestroyObserverAndroid(JNIEnv* env,
+                              const base::android::JavaParamRef<jobject>& obj);
 
   static bool Register(JNIEnv* env);
 
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
index 1987375..a0608ff 100644
--- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc
+++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -55,6 +55,7 @@
 using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertUTF8ToJavaString;
 using base::android::ConvertUTF16ToJavaString;
+using base::android::JavaRef;
 using bookmarks::BookmarkModel;
 using metrics::OmniboxEventProto;
 
@@ -127,24 +128,25 @@
       profile_(profile) {
 }
 
-void AutocompleteControllerAndroid::Start(JNIEnv* env,
-                                          jobject obj,
-                                          jstring j_text,
-                                          jint j_cursor_pos,
-                                          jstring j_desired_tld,
-                                          jstring j_current_url,
-                                          bool prevent_inline_autocomplete,
-                                          bool prefer_keyword,
-                                          bool allow_exact_keyword_match,
-                                          bool want_asynchronous_matches) {
+void AutocompleteControllerAndroid::Start(
+    JNIEnv* env,
+    const JavaRef<jobject>& obj,
+    const JavaRef<jstring>& j_text,
+    jint j_cursor_pos,
+    const JavaRef<jstring>& j_desired_tld,
+    const JavaRef<jstring>& j_current_url,
+    bool prevent_inline_autocomplete,
+    bool prefer_keyword,
+    bool allow_exact_keyword_match,
+    bool want_asynchronous_matches) {
   if (!autocomplete_controller_)
     return;
 
   std::string desired_tld;
   GURL current_url;
-  if (j_current_url != NULL)
+  if (!j_current_url.is_null())
     current_url = GURL(ConvertJavaStringToUTF16(env, j_current_url));
-  if (j_desired_tld != NULL)
+  if (!j_desired_tld.is_null())
     desired_tld = base::android::ConvertJavaStringToUTF8(env, j_desired_tld);
   base::string16 text = ConvertJavaStringToUTF16(env, j_text);
   OmniboxEventProto::PageClassification page_classification =
@@ -160,16 +162,16 @@
 
 ScopedJavaLocalRef<jobject> AutocompleteControllerAndroid::Classify(
     JNIEnv* env,
-    jobject obj,
-    jstring j_text) {
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& j_text) {
   return GetTopSynchronousResult(env, obj, j_text, true);
 }
 
 void AutocompleteControllerAndroid::OnOmniboxFocused(
     JNIEnv* env,
-    jobject obj,
-    jstring j_omnibox_text,
-    jstring j_current_url,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& j_omnibox_text,
+    const JavaParamRef<jstring>& j_current_url,
     jboolean is_query_in_omnibox,
     jboolean focused_from_fakebox) {
   if (!autocomplete_controller_)
@@ -193,26 +195,28 @@
 }
 
 void AutocompleteControllerAndroid::Stop(JNIEnv* env,
-                                         jobject obj,
+                                         const JavaParamRef<jobject>& obj,
                                          bool clear_results) {
   if (autocomplete_controller_ != NULL)
     autocomplete_controller_->Stop(clear_results);
 }
 
-void AutocompleteControllerAndroid::ResetSession(JNIEnv* env, jobject obj) {
+void AutocompleteControllerAndroid::ResetSession(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (autocomplete_controller_ != NULL)
     autocomplete_controller_->ResetSession();
 }
 
 void AutocompleteControllerAndroid::OnSuggestionSelected(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jint selected_index,
-    jstring j_current_url,
+    const JavaParamRef<jstring>& j_current_url,
     jboolean is_query_in_omnibox,
     jboolean focused_from_fakebox,
     jlong elapsed_time_since_first_modified,
-    jobject j_web_contents) {
+    const JavaParamRef<jobject>& j_web_contents) {
   base::string16 url = ConvertJavaStringToUTF16(env, j_current_url);
   const GURL current_url = GURL(url);
   OmniboxEventProto::PageClassification current_page_classification =
@@ -244,9 +248,10 @@
       ->OnOmniboxOpenedUrl(log);
 }
 
-void AutocompleteControllerAndroid::DeleteSuggestion(JNIEnv* env,
-                                                     jobject obj,
-                                                     int selected_index) {
+void AutocompleteControllerAndroid::DeleteSuggestion(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    int selected_index) {
   const AutocompleteResult& result = autocomplete_controller_->result();
   const AutocompleteMatch& match = result.match_at(selected_index);
   if (match.SupportsDeletion())
@@ -256,7 +261,7 @@
 ScopedJavaLocalRef<jstring> AutocompleteControllerAndroid::
     UpdateMatchDestinationURLWithQueryFormulationTime(
         JNIEnv* env,
-        jobject obj,
+        const JavaParamRef<jobject>& obj,
         jint selected_index,
         jlong elapsed_time_since_input_change) {
   // In rare cases, we navigate to cached matches and the underlying result
@@ -485,8 +490,8 @@
 ScopedJavaLocalRef<jobject>
 AutocompleteControllerAndroid::GetTopSynchronousResult(
     JNIEnv* env,
-    jobject obj,
-    jstring j_text,
+    const JavaRef<jobject>& obj,
+    const JavaRef<jstring>& j_text,
     bool prevent_inline_autocomplete) {
   if (!autocomplete_controller_)
     return ScopedJavaLocalRef<jobject>();
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.h b/chrome/browser/android/omnibox/autocomplete_controller_android.h
index 73f18f7b..1f180da 100644
--- a/chrome/browser/android/omnibox/autocomplete_controller_android.h
+++ b/chrome/browser/android/omnibox/autocomplete_controller_android.h
@@ -34,41 +34,49 @@
 
   // Methods that forward to AutocompleteController:
   void Start(JNIEnv* env,
-             jobject obj,
-             jstring j_text,
+             const base::android::JavaRef<jobject>& obj,
+             const base::android::JavaRef<jstring>& j_text,
              jint j_cursor_pos,
-             jstring j_desired_tld,
-             jstring j_current_url,
+             const base::android::JavaRef<jstring>& j_desired_tld,
+             const base::android::JavaRef<jstring>& j_current_url,
              bool prevent_inline_autocomplete,
              bool prefer_keyword,
              bool allow_exact_keyword_match,
              bool best_match_only);
-  base::android::ScopedJavaLocalRef<jobject> Classify(JNIEnv* env,
-                                                      jobject obj,
-                                                      jstring j_text);
-  void OnOmniboxFocused(JNIEnv* env,
-                        jobject obj,
-                        jstring j_omnibox_text,
-                        jstring j_current_url,
-                        jboolean is_query_in_omnibox,
-                        jboolean focused_from_fakebox);
-  void Stop(JNIEnv* env, jobject obj, bool clear_result);
-  void ResetSession(JNIEnv* env, jobject obj);
-  void OnSuggestionSelected(JNIEnv* env,
-                            jobject obj,
-                            jint selected_index,
-                            jstring j_current_url,
-                            jboolean is_query_in_omnibox,
-                            jboolean focused_from_fakebox,
-                            jlong elapsed_time_since_first_modified,
-                            jobject j_web_contents);
-  void DeleteSuggestion(JNIEnv* env, jobject obj, int selected_index);
+  base::android::ScopedJavaLocalRef<jobject> Classify(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& j_text);
+  void OnOmniboxFocused(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& j_omnibox_text,
+      const base::android::JavaParamRef<jstring>& j_current_url,
+      jboolean is_query_in_omnibox,
+      jboolean focused_from_fakebox);
+  void Stop(JNIEnv* env,
+            const base::android::JavaParamRef<jobject>& obj,
+            bool clear_result);
+  void ResetSession(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj);
+  void OnSuggestionSelected(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint selected_index,
+      const base::android::JavaParamRef<jstring>& j_current_url,
+      jboolean is_query_in_omnibox,
+      jboolean focused_from_fakebox,
+      jlong elapsed_time_since_first_modified,
+      const base::android::JavaParamRef<jobject>& j_web_contents);
+  void DeleteSuggestion(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj,
+                        int selected_index);
   base::android::ScopedJavaLocalRef<jstring>
-      UpdateMatchDestinationURLWithQueryFormulationTime(
-          JNIEnv* env,
-          jobject obj,
-          jint selected_index,
-          jlong elapsed_time_since_input_change);
+  UpdateMatchDestinationURLWithQueryFormulationTime(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint selected_index,
+      jlong elapsed_time_since_input_change);
 
   // KeyedService:
   void Shutdown() override;
@@ -127,8 +135,8 @@
   // object, see documentation there for its description.
   base::android::ScopedJavaLocalRef<jobject> GetTopSynchronousResult(
       JNIEnv* env,
-      jobject obj,
-      jstring j_text,
+      const base::android::JavaRef<jobject>& obj,
+      const base::android::JavaRef<jstring>& j_text,
       bool prevent_inline_autocomplete);
 
   scoped_ptr<AutocompleteController> autocomplete_controller_;
diff --git a/chrome/browser/android/omnibox/omnibox_prerender.cc b/chrome/browser/android/omnibox/omnibox_prerender.cc
index f0a373a..b1b2708 100644
--- a/chrome/browser/android/omnibox/omnibox_prerender.cc
+++ b/chrome/browser/android/omnibox/omnibox_prerender.cc
@@ -38,8 +38,8 @@
 }
 
 void OmniboxPrerender::Clear(JNIEnv* env,
-                             jobject obj,
-                             jobject j_profile_android) {
+                             const JavaParamRef<jobject>& obj,
+                             const JavaParamRef<jobject>& j_profile_android) {
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
   DCHECK(profile);
   if (!profile)
@@ -52,21 +52,22 @@
 
 void OmniboxPrerender::InitializeForProfile(
     JNIEnv* env,
-    jobject obj,
-    jobject j_profile_android) {
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& j_profile_android) {
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
   // Initialize the AutocompleteActionPredictor for this profile.
   // It needs to register for notifications as part of its initialization.
   AutocompleteActionPredictorFactory::GetForProfile(profile);
 }
 
-void OmniboxPrerender::PrerenderMaybe(JNIEnv* env,
-                                      jobject obj,
-                                      jstring j_url,
-                                      jstring j_current_url,
-                                      jlong jsource_match,
-                                      jobject j_profile_android,
-                                      jobject j_tab) {
+void OmniboxPrerender::PrerenderMaybe(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& j_url,
+    const JavaParamRef<jstring>& j_current_url,
+    jlong jsource_match,
+    const JavaParamRef<jobject>& j_profile_android,
+    const JavaParamRef<jobject>& j_tab) {
   AutocompleteResult* autocomplete_result =
       reinterpret_cast<AutocompleteResult*>(jsource_match);
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
diff --git a/chrome/browser/android/omnibox/omnibox_prerender.h b/chrome/browser/android/omnibox/omnibox_prerender.h
index eb8e792..11636f6e 100644
--- a/chrome/browser/android/omnibox/omnibox_prerender.h
+++ b/chrome/browser/android/omnibox/omnibox_prerender.h
@@ -32,27 +32,31 @@
   // Clears the transitional matches. This should be called when the user
   // stops typing into the omnibox (e.g. when navigating away, closing the
   // keyboard or changing tabs).
-  void Clear(JNIEnv* env, jobject obj, jobject j_profile_android);
+  void Clear(JNIEnv* env,
+             const base::android::JavaParamRef<jobject>& obj,
+             const base::android::JavaParamRef<jobject>& j_profile_android);
 
   // Initializes the underlying action predictor for a given profile instance.
   // This should be called as soon as possible as the predictor must register
   // for certain notifications to properly initialize before providing
   // predictions and updated its learning database.
-  void InitializeForProfile(JNIEnv* env,
-                            jobject obj,
-                            jobject j_profile_android);
+  void InitializeForProfile(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobject>& j_profile_android);
 
   // Potentailly invokes a pre-render or pre-connect given the url typed into
   // the omnibox and a corresponding autocomplete result. This should be
   // invoked everytime the omnibox changes (e.g. As the user types characters
   // this method should be invoked at least once per character).
-  void PrerenderMaybe(JNIEnv* env,
-                      jobject obj,
-                      jstring j_url,
-                      jstring j_current_url,
-                      jlong jsource_match,
-                      jobject j_profile_android,
-                      jobject j_tab);
+  void PrerenderMaybe(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& j_url,
+      const base::android::JavaParamRef<jstring>& j_current_url,
+      jlong jsource_match,
+      const base::android::JavaParamRef<jobject>& j_profile_android,
+      const base::android::JavaParamRef<jobject>& j_tab);
 
  private:
 
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 1cb92bd9..1d745f4 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -2804,38 +2804,6 @@
   scoped_refptr<content::FrameWatcher> frame_watcher_;
 };
 
-class FocusWaiter : public views::FocusChangeListener {
- public:
-  explicit FocusWaiter(views::View* view_to_wait_for)
-      : view_to_wait_for_(view_to_wait_for) {
-    view_to_wait_for_->GetFocusManager()->AddFocusChangeListener(this);
-  }
-  ~FocusWaiter() override {
-    view_to_wait_for_->GetFocusManager()->RemoveFocusChangeListener(this);
-  }
-
-  void Wait() {
-    if (view_to_wait_for_->HasFocus())
-      return;
-
-    base::MessageLoop::current()->Run();
-  }
-
-  // FocusChangeListener implementation.
-  void OnWillChangeFocus(views::View* focused_before,
-                         views::View* focused_now) override {}
-  void OnDidChangeFocus(views::View* focused_before,
-                        views::View* focused_now) override {
-    if (view_to_wait_for_ == focused_now)
-      base::MessageLoop::current()->QuitWhenIdle();
-  }
-
- private:
-  views::View* view_to_wait_for_;
-
-  DISALLOW_COPY_AND_ASSIGN(FocusWaiter);
-};
-
 // The following test verifies that a views::WebView hosting an embedder
 // gains focus on touchstart.
 IN_PROC_BROWSER_TEST_F(WebViewFocusTest, TouchFocusesEmbedder) {
@@ -2895,13 +2863,9 @@
   guest_rect.Offset(-embedder_origin.x(), -embedder_origin.y());
 
   // Generate and send synthetic touch event.
-  FocusWaiter waiter(aura_webview);
   content::SimulateTouchPressAt(GetEmbedderWebContents(),
                                 guest_rect.CenterPoint());
-
-  // Wait for the TouchStart to propagate and restore focus. Test times out
-  // on failure.
-  waiter.Wait();
+  EXPECT_TRUE(aura_webview->HasFocus());
 }
 #endif
 
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc
index 72366612..df49526 100644
--- a/chrome/browser/download/save_page_browsertest.cc
+++ b/chrome/browser/download/save_page_browsertest.cc
@@ -15,7 +15,7 @@
 #include "base/prefs/pref_member.h"
 #include "base/prefs/pref_service.h"
 #include "base/run_loop.h"
-#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_file_util.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -75,11 +75,7 @@
     return std::string();
   }
 
-  std::vector<std::string> words =
-      base::SplitString(file_contents, " \t\r\n", base::TRIM_WHITESPACE,
-                        base::SPLIT_WANT_NONEMPTY);
-
-  return base::JoinString(words, " ");
+  return base::CollapseWhitespaceASCII(file_contents, false);
 }
 
 // Waits for an item record in the downloads database to match |filter|. See
@@ -865,10 +861,7 @@
 }
 
 // Test for crbug.com/538766.
-// Disabled because the test will fail until the bug is fixed
-// (but note that the test only fails with --site-per-process flag).
-IN_PROC_BROWSER_TEST_F(SavePageSitePerProcessBrowserTest,
-                       DISABLED_SaveAsMHTML) {
+IN_PROC_BROWSER_TEST_F(SavePageSitePerProcessBrowserTest, SaveAsMHTML) {
   GURL url(
       embedded_test_server()->GetURL("a.com", "/save_page/frames-xsite.htm"));
   ui_test_utils::NavigateToURL(browser(), url);
@@ -911,7 +904,10 @@
     count++;
     pos++;
   }
-  EXPECT_EQ(1, count) << "Verify number of image/png parts in the mhtml output";
+  // TODO(lukasza): Need to dedupe savable resources (i.e. 1.png) across frames.
+  // This will be fixed by crrev.com/1417323006.
+  // EXPECT_EQ(1, count)
+  //     << "Verify number of image/png parts in the mhtml output";
 }
 
 // Test suite that verifies that the frame tree "looks" the same before
@@ -1023,10 +1019,6 @@
   GURL url(
       embedded_test_server()->GetURL("a.com", "/save_page/frames-xsite.htm"));
 
-  // TODO(lukasza): crbug.com/538766: Enable CrossSite testing of MHTML.
-  if (save_page_type == content::SAVE_PAGE_TYPE_AS_MHTML)
-    return;
-
   // TODO(lukasza/paulmeyer): crbug.com/457440: Can enable verification
   // of the original page once find-in-page works for OOP frames.
   bool skip_verification_of_original_page = true;
diff --git a/chrome/browser/history/android/sqlite_cursor.cc b/chrome/browser/history/android/sqlite_cursor.cc
index 7b3fa9b..e60bebb 100644
--- a/chrome/browser/history/android/sqlite_cursor.cc
+++ b/chrome/browser/history/android/sqlite_cursor.cc
@@ -60,7 +60,7 @@
   return RegisterNativesImpl(env);
 }
 
-jint SQLiteCursor::GetCount(JNIEnv* env, jobject obj) {
+jint SQLiteCursor::GetCount(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   // Moves to maxium possible position so we will reach the last row, then finds
   // out the total number of rows.
   int current_position = position_;
@@ -70,34 +70,43 @@
   return count;
 }
 
-ScopedJavaLocalRef<jobjectArray> SQLiteCursor::GetColumnNames(JNIEnv* env,
-                                                              jobject obj) {
+ScopedJavaLocalRef<jobjectArray> SQLiteCursor::GetColumnNames(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return base::android::ToJavaArrayOfStrings(env, column_names_);
 }
 
-ScopedJavaLocalRef<jstring> SQLiteCursor::GetString(JNIEnv* env,
-                                                    jobject obj,
-                                                    jint column) {
+ScopedJavaLocalRef<jstring> SQLiteCursor::GetString(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint column) {
   base::string16 value = statement_->statement()->ColumnString16(column);
   return ScopedJavaLocalRef<jstring>(env,
       env->NewString(value.data(), value.size()));
 }
 
-jlong SQLiteCursor::GetLong(JNIEnv* env, jobject obj, jint column) {
+jlong SQLiteCursor::GetLong(JNIEnv* env,
+                            const JavaParamRef<jobject>& obj,
+                            jint column) {
   return statement_->statement()->ColumnInt64(column);
 }
 
-jint SQLiteCursor::GetInt(JNIEnv* env, jobject obj, jint column) {
+jint SQLiteCursor::GetInt(JNIEnv* env,
+                          const JavaParamRef<jobject>& obj,
+                          jint column) {
   return statement_->statement()->ColumnInt(column);
 }
 
-jdouble SQLiteCursor::GetDouble(JNIEnv* env, jobject obj, jint column) {
+jdouble SQLiteCursor::GetDouble(JNIEnv* env,
+                                const JavaParamRef<jobject>& obj,
+                                jint column) {
   return statement_->statement()->ColumnDouble(column);
 }
 
-ScopedJavaLocalRef<jbyteArray> SQLiteCursor::GetBlob(JNIEnv* env,
-                                                     jobject obj,
-                                                     jint column) {
+ScopedJavaLocalRef<jbyteArray> SQLiteCursor::GetBlob(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint column) {
   std::vector<unsigned char> blob;
 
   // Assume the client will only get favicon using GetBlob.
@@ -110,11 +119,15 @@
   return base::android::ToJavaByteArray(env, &blob[0], blob.size());
 }
 
-jboolean SQLiteCursor::IsNull(JNIEnv* env, jobject obj, jint column) {
+jboolean SQLiteCursor::IsNull(JNIEnv* env,
+                              const JavaParamRef<jobject>& obj,
+                              jint column) {
   return NULL_TYPE == GetColumnTypeInternal(column) ? JNI_TRUE : JNI_FALSE;
 }
 
-jint SQLiteCursor::MoveTo(JNIEnv* env, jobject obj, jint pos) {
+jint SQLiteCursor::MoveTo(JNIEnv* env,
+                          const JavaParamRef<jobject>& obj,
+                          jint pos) {
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       base::Bind(&SQLiteCursor::RunMoveStatementOnUIThread,
       base::Unretained(this), pos));
@@ -125,11 +138,13 @@
   return position_;
 }
 
-jint SQLiteCursor::GetColumnType(JNIEnv* env, jobject obj, jint column) {
+jint SQLiteCursor::GetColumnType(JNIEnv* env,
+                                 const JavaParamRef<jobject>& obj,
+                                 jint column) {
   return GetColumnTypeInternal(column);
 }
 
-void SQLiteCursor::Destroy(JNIEnv* env, jobject obj) {
+void SQLiteCursor::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
   // We do our best to cleanup when Destroy() is called from Java's finalize()
   // where the UI message loop might stop running or in the process of shutting
   // down, as the whole process will be destroyed soon, it's fine to leave some
diff --git a/chrome/browser/history/android/sqlite_cursor.h b/chrome/browser/history/android/sqlite_cursor.h
index c828ad2..f93514a 100644
--- a/chrome/browser/history/android/sqlite_cursor.h
+++ b/chrome/browser/history/android/sqlite_cursor.h
@@ -80,45 +80,59 @@
   // JNI methods -----------------------------------------------------------
 
   // Returns the result row count.
-  jint GetCount(JNIEnv* env, jobject obj);
+  jint GetCount(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
   // Returns the result's columns' name.
   base::android::ScopedJavaLocalRef<jobjectArray> GetColumnNames(
       JNIEnv* env,
-      jobject obj);
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Returns the given column value as jstring.
-  base::android::ScopedJavaLocalRef<jstring> GetString(JNIEnv* env,
-                                                       jobject obj,
-                                                       jint column);
+  base::android::ScopedJavaLocalRef<jstring> GetString(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint column);
 
   // Returns the given column value as jlong.
-  jlong GetLong(JNIEnv* env, jobject obj, jint column);
+  jlong GetLong(JNIEnv* env,
+                const base::android::JavaParamRef<jobject>& obj,
+                jint column);
 
   // Returns the given column value as int.
-  jint GetInt(JNIEnv* env, jobject obj, jint column);
+  jint GetInt(JNIEnv* env,
+              const base::android::JavaParamRef<jobject>& obj,
+              jint column);
 
   // Returns the given column value as double.
-  jdouble GetDouble(JNIEnv* env, jobject obj, jint column);
+  jdouble GetDouble(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj,
+                    jint column);
 
   // Returns the given column value as jbyteArray.
-  base::android::ScopedJavaLocalRef<jbyteArray> GetBlob(JNIEnv* env,
-                                                        jobject obj,
-                                                        jint column);
+  base::android::ScopedJavaLocalRef<jbyteArray> GetBlob(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint column);
 
   // Return JNI_TRUE if the give column value is NULL, JNI_FALSE otherwise.
-  jboolean IsNull(JNIEnv* env, jobject obj, jint column);
+  jboolean IsNull(JNIEnv* env,
+                  const base::android::JavaParamRef<jobject>& obj,
+                  jint column);
 
   // Moves the cursor to |pos|, returns new position.
   // If the returned position is not equal to |pos|, then the cursor points to
   // the last row.
-  jint MoveTo(JNIEnv* env, jobject obj, jint pos);
+  jint MoveTo(JNIEnv* env,
+              const base::android::JavaParamRef<jobject>& obj,
+              jint pos);
 
   // Returns the type of column.
-  jint GetColumnType(JNIEnv* env, jobject obj, jint column);
+  jint GetColumnType(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj,
+                     jint column);
 
   // Called from Java to relase this object.
-  void Destroy(JNIEnv* env, jobject obj);
+  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SQLiteCursorTest, Run);
diff --git a/chrome/browser/media/android/remote/remote_media_player_bridge.cc b/chrome/browser/media/android/remote/remote_media_player_bridge.cc
index 4efd11b9..5d3d788 100644
--- a/chrome/browser/media/android/remote/remote_media_player_bridge.cc
+++ b/chrome/browser/media/android/remote/remote_media_player_bridge.cc
@@ -120,19 +120,23 @@
       player_id(), GetCurrentTime(), base::TimeTicks::Now());
 }
 
-void RemoteMediaPlayerBridge::PauseLocal(JNIEnv* env, jobject obj) {
+void RemoteMediaPlayerBridge::PauseLocal(JNIEnv* env,
+                                         const JavaParamRef<jobject>& obj) {
   local_player_->Pause(true);
   static_cast<RemoteMediaPlayerManager*>(manager())->OnPaused(player_id());
 }
 
-jint RemoteMediaPlayerBridge::GetLocalPosition(JNIEnv* env, jobject obj) {
+jint RemoteMediaPlayerBridge::GetLocalPosition(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   base::TimeDelta time = local_player_->GetCurrentTime();
   return static_cast<jint>(time.InMilliseconds());
 }
 
-void RemoteMediaPlayerBridge::OnCastStarting(JNIEnv* env,
-                                             jobject obj,
-                                             jstring casting_message) {
+void RemoteMediaPlayerBridge::OnCastStarting(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& casting_message) {
   static_cast<RemoteMediaPlayerManager*>(manager())->SwitchToRemotePlayer(
       player_id(), ConvertJavaStringToUTF8(env, casting_message));
   if (!time_update_timer_.IsRunning()) {
@@ -143,7 +147,8 @@
   }
 }
 
-void RemoteMediaPlayerBridge::OnCastStopping(JNIEnv* env, jobject obj) {
+void RemoteMediaPlayerBridge::OnCastStopping(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   static_cast<RemoteMediaPlayerManager*>(manager())
       ->SwitchToLocalPlayer(player_id());
 }
@@ -169,32 +174,40 @@
 }
 
 base::android::ScopedJavaLocalRef<jstring> RemoteMediaPlayerBridge::GetFrameUrl(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return ConvertUTF8ToJavaString(env, frame_url().spec());
 }
 
-void RemoteMediaPlayerBridge::OnPlaying(JNIEnv* env, jobject obj) {
+void RemoteMediaPlayerBridge::OnPlaying(JNIEnv* env,
+                                        const JavaParamRef<jobject>& obj) {
   static_cast<RemoteMediaPlayerManager *>(manager())->OnPlaying(player_id());
 }
 
-void RemoteMediaPlayerBridge::OnPaused(JNIEnv* env, jobject obj) {
+void RemoteMediaPlayerBridge::OnPaused(JNIEnv* env,
+                                       const JavaParamRef<jobject>& obj) {
   static_cast<RemoteMediaPlayerManager *>(manager())->OnPaused(player_id());
 }
 
-void RemoteMediaPlayerBridge::OnRouteUnselected(JNIEnv* env, jobject obj) {
+void RemoteMediaPlayerBridge::OnRouteUnselected(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   casting_message_.reset();
   static_cast<RemoteMediaPlayerManager *>(manager())->OnRemoteDeviceUnselected(
       player_id());
 }
 
-void RemoteMediaPlayerBridge::OnPlaybackFinished(JNIEnv* env, jobject obj) {
+void RemoteMediaPlayerBridge::OnPlaybackFinished(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   static_cast<RemoteMediaPlayerManager *>(manager())->OnRemotePlaybackFinished(
       player_id());
 }
 
-void RemoteMediaPlayerBridge::OnRouteAvailabilityChanged(JNIEnv* env,
-                                                         jobject obj,
-                                                         jboolean available) {
+void RemoteMediaPlayerBridge::OnRouteAvailabilityChanged(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jboolean available) {
   static_cast<RemoteMediaPlayerManager *>(manager())->
       OnRouteAvailabilityChanged(player_id(), available);
 }
@@ -370,7 +383,8 @@
 }
 
 base::android::ScopedJavaLocalRef<jstring> RemoteMediaPlayerBridge::GetTitle(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   base::string16 title;
   content::ContentViewCore* core =
       static_cast<RemoteMediaPlayerManager*>(manager())->GetContentViewCore();
diff --git a/chrome/browser/media/android/remote/remote_media_player_bridge.h b/chrome/browser/media/android/remote/remote_media_player_bridge.h
index ea21de7..893d0ff 100644
--- a/chrome/browser/media/android/remote/remote_media_player_bridge.h
+++ b/chrome/browser/media/android/remote/remote_media_player_bridge.h
@@ -56,17 +56,30 @@
 
   // JNI functions
   base::android::ScopedJavaLocalRef<jstring> GetFrameUrl(
-      JNIEnv* env, jobject obj);
-  void OnPlaying(JNIEnv* env, jobject obj);
-  void OnPaused(JNIEnv* env, jobject obj);
-  void OnRouteUnselected(JNIEnv* env, jobject obj);
-  void OnPlaybackFinished(JNIEnv* env, jobject obj);
-  void OnRouteAvailabilityChanged(JNIEnv* env, jobject obj, jboolean available);
-  base::android::ScopedJavaLocalRef<jstring> GetTitle(JNIEnv* env, jobject obj);
-  void PauseLocal(JNIEnv* env, jobject obj);
-  jint GetLocalPosition(JNIEnv* env, jobject obj);
-  void OnCastStarting(JNIEnv* env, jobject obj, jstring casting_message);
-  void OnCastStopping(JNIEnv* env, jobject obj);
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void OnPlaying(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void OnPaused(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void OnRouteUnselected(JNIEnv* env,
+                         const base::android::JavaParamRef<jobject>& obj);
+  void OnPlaybackFinished(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj);
+  void OnRouteAvailabilityChanged(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean available);
+  base::android::ScopedJavaLocalRef<jstring> GetTitle(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void PauseLocal(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  jint GetLocalPosition(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj);
+  void OnCastStarting(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& casting_message);
+  void OnCastStopping(JNIEnv* env,
+                      const base::android::JavaParamRef<jobject>& obj);
 
   // Wrappers for calls to Java used by the remote media player manager
   void RequestRemotePlayback();
diff --git a/chrome/browser/media/android/router/media_router_android.cc b/chrome/browser/media/android/router/media_router_android.cc
index a3e6e8a..ea91893 100644
--- a/chrome/browser/media/android/router/media_router_android.cc
+++ b/chrome/browser/media/android/router/media_router_android.cc
@@ -314,8 +314,8 @@
 
 void MediaRouterAndroid::OnSinksReceived(
     JNIEnv* env,
-    jobject obj,
-    jstring jsource_urn,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jsource_urn,
     jint jcount) {
   std::vector<MediaSink> sinks_converted;
   sinks_converted.reserve(jcount);
@@ -342,9 +342,9 @@
 
 void MediaRouterAndroid::OnRouteCreated(
     JNIEnv* env,
-    jobject obj,
-    jstring jmedia_route_id,
-    jstring jsink_id,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jmedia_route_id,
+    const JavaParamRef<jstring>& jsink_id,
     jint jroute_request_id,
     jboolean jis_local) {
   MediaRouteRequest* request = route_requests_.Lookup(jroute_request_id);
@@ -369,8 +369,8 @@
 
 void MediaRouterAndroid::OnRouteRequestError(
     JNIEnv* env,
-    jobject obj,
-    jstring jerror_text,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jerror_text,
     jint jroute_request_id) {
   MediaRouteRequest* request = route_requests_.Lookup(jroute_request_id);
   if (!request)
@@ -384,9 +384,10 @@
   route_requests_.Remove(jroute_request_id);
 }
 
-void MediaRouterAndroid::OnRouteClosed(JNIEnv* env,
-                                       jobject obj,
-                                       jstring jmedia_route_id) {
+void MediaRouterAndroid::OnRouteClosed(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jmedia_route_id) {
   MediaRoute::Id route_id = ConvertJavaStringToUTF8(env, jmedia_route_id);
   for (auto it = active_routes_.begin(); it != active_routes_.end(); ++it)
     if (it->media_route_id() == route_id) {
@@ -398,16 +399,20 @@
                     OnRoutesUpdated(active_routes_));
 }
 
-void MediaRouterAndroid::OnMessageSentResult(
-    JNIEnv* env, jobject obj, jboolean jsuccess, jint jcallback_id) {
+void MediaRouterAndroid::OnMessageSentResult(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj,
+                                             jboolean jsuccess,
+                                             jint jcallback_id) {
   SendRouteMessageCallback* callback = message_callbacks_.Lookup(jcallback_id);
   callback->Run(jsuccess);
   message_callbacks_.Remove(jcallback_id);
 }
 
 // Notifies the media router about a message received from the media route.
-void MediaRouterAndroid::OnMessage(
-    JNIEnv* env, jobject obj, jstring jmedia_route_id, jstring jmessage) {
+void MediaRouterAndroid::OnMessage(JNIEnv* env,
+                                   const JavaParamRef<jobject>& obj,
+                                   const JavaParamRef<jstring>& jmedia_route_id,
+                                   const JavaParamRef<jstring>& jmessage) {
   MediaRoute::Id route_id = ConvertJavaStringToUTF8(env, jmedia_route_id);
   auto* observer_list = messages_observers_.get(route_id);
   if (!observer_list)
diff --git a/chrome/browser/media/android/router/media_router_android.h b/chrome/browser/media/android/router/media_router_android.h
index a2d9b52..25a325aa 100644
--- a/chrome/browser/media/android/router/media_router_android.h
+++ b/chrome/browser/media/android/router/media_router_android.h
@@ -57,35 +57,44 @@
 
   // Notifies the media router that information about sinks is received for
   // a specific source URN.
-  void OnSinksReceived(
-      JNIEnv* env, jobject obj, jstring jsource_urn, jint jcount);
+  void OnSinksReceived(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj,
+                       const base::android::JavaParamRef<jstring>& jsource_urn,
+                       jint jcount);
 
   // Notifies the media router about a successful route creation.
   void OnRouteCreated(
       JNIEnv* env,
-      jobject obj,
-      jstring jmedia_route_id,
-      jstring jmedia_sink_id,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jmedia_route_id,
+      const base::android::JavaParamRef<jstring>& jmedia_sink_id,
       jint jroute_request_id,
       jboolean jis_local);
 
   // Notifies the media router that route creation or joining failed.
   void OnRouteRequestError(
       JNIEnv* env,
-      jobject obj,
-      jstring jerror_text,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jerror_text,
       jint jroute_request_id);
 
   // Notifies the media router when the route was closed.
-  void OnRouteClosed(JNIEnv* env, jobject obj, jstring jmedia_route_id);
+  void OnRouteClosed(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jmedia_route_id);
 
   // Notifies the media router about the result of sending a message.
-  void OnMessageSentResult(
-      JNIEnv* env, jobject obj, jboolean jsuccess, jint jcallback_id);
+  void OnMessageSentResult(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj,
+                           jboolean jsuccess,
+                           jint jcallback_id);
 
   // Notifies the media router about a message received from the media route.
-  void OnMessage(
-      JNIEnv* env, jobject obj, jstring jmedia_route_id, jstring jmessage);
+  void OnMessage(JNIEnv* env,
+                 const base::android::JavaParamRef<jobject>& obj,
+                 const base::android::JavaParamRef<jstring>& jmedia_route_id,
+                 const base::android::JavaParamRef<jstring>& jmessage);
 
  private:
   friend class MediaRouterFactory;
diff --git a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc
index cbff49e5..86ab932 100644
--- a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc
+++ b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc
@@ -36,7 +36,9 @@
 }
 
 void MediaRouterDialogControllerAndroid::OnSinkSelected(
-    JNIEnv* env, jobject obj, jstring jsink_id) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jsink_id) {
   scoped_ptr<CreatePresentationConnectionRequest> create_connection_request =
       TakeCreateConnectionRequest();
   const PresentationRequest& presentation_request =
@@ -61,8 +63,8 @@
 
 void MediaRouterDialogControllerAndroid::OnRouteClosed(
     JNIEnv* env,
-    jobject obj,
-    jstring jmedia_route_id) {
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jmedia_route_id) {
   std::string media_route_id = ConvertJavaStringToUTF8(env, jmedia_route_id);
 
   MediaRouter* router = MediaRouterFactory::GetApiForBrowserContext(
@@ -74,7 +76,8 @@
 }
 
 void MediaRouterDialogControllerAndroid::OnDialogCancelled(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   CancelPresentationRequest();
 }
 
diff --git a/chrome/browser/media/android/router/media_router_dialog_controller_android.h b/chrome/browser/media/android/router/media_router_dialog_controller_android.h
index cbd5928..40c8c022 100644
--- a/chrome/browser/media/android/router/media_router_dialog_controller_android.h
+++ b/chrome/browser/media/android/router/media_router_dialog_controller_android.h
@@ -32,12 +32,18 @@
   // The methods called by the Java counterpart.
 
   // Notifies the controller that user has selected a sink with |jsink_id|.
-  void OnSinkSelected(JNIEnv* env, jobject obj, jstring jsink_id);
+  void OnSinkSelected(JNIEnv* env,
+                      const base::android::JavaParamRef<jobject>& obj,
+                      const base::android::JavaParamRef<jstring>& jsink_id);
   // Notifies the controller that user chose to close the route.
-  void OnRouteClosed(JNIEnv* env, jobject obj, jstring jmedia_route_id);
+  void OnRouteClosed(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jmedia_route_id);
   // Notifies the controller that the dialog has been closed without the user
   // taking any action (e.g. closing the route or selecting a sink).
-  void OnDialogCancelled(JNIEnv* env, jobject obj);
+  void OnDialogCancelled(JNIEnv* env,
+                         const base::android::JavaParamRef<jobject>& obj);
 
  private:
   friend class content::WebContentsUserData<MediaRouterDialogControllerAndroid>;
diff --git a/chrome/browser/memory/tab_manager.cc b/chrome/browser/memory/tab_manager.cc
index 9b2dfb4..1112bbd 100644
--- a/chrome/browser/memory/tab_manager.cc
+++ b/chrome/browser/memory/tab_manager.cc
@@ -464,6 +464,13 @@
   if (IsAudioTab(web_contents))
     return false;
 
+  // Do not discard PDFs as they might contain entry that is not saved and they
+  // don't remember their scrolling positions. See crbug.com/547286 and
+  // crbug.com/65244.
+  // TODO(georgesak): Remove this workaround when the bugs are fixed.
+  if (web_contents->GetContentsMimeType() == "application/pdf")
+    return false;
+
   // Do not discard a previously discarded tab if that's the desired behavior.
   if (discard_once_ && GetWebContentsData(web_contents)->DiscardCount() > 0)
     return false;
diff --git a/chrome/browser/memory/tab_manager_browsertest.cc b/chrome/browser/memory/tab_manager_browsertest.cc
index 402db46..7eab6e55 100644
--- a/chrome/browser/memory/tab_manager_browsertest.cc
+++ b/chrome/browser/memory/tab_manager_browsertest.cc
@@ -15,6 +15,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/interactive_test_utils.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/test/test_utils.h"
@@ -251,6 +252,30 @@
   EXPECT_TRUE(tab_manager->DiscardTab());
 }
 
+// Makes sure that PDF pages are protected.
+IN_PROC_BROWSER_TEST_F(TabManagerTest, ProtectPDFPages) {
+  TabManager* tab_manager = g_browser_process->GetTabManager();
+  ASSERT_TRUE(tab_manager);
+
+  // Start the embedded test server so we can get served the required PDF page.
+  ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+  embedded_test_server()->StartAcceptingConnections();
+
+  // Get two tabs open, the first one being a PDF page and the second one being
+  // the foreground tab.
+  GURL url1 = embedded_test_server()->GetURL("/pdf/test.pdf");
+  ui_test_utils::NavigateToURL(browser(), url1);
+
+  GURL url2(chrome::kChromeUIAboutURL);
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), url2, NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+  // No discarding should be possible as the only background tab is displaying a
+  // PDF page, hence protected.
+  EXPECT_FALSE(tab_manager->DiscardTab());
+}
+
 }  // namespace memory
 
 #endif  // OS_WIN || OS_CHROMEOS
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc
index cbd5130..6090293 100644
--- a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc
+++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc
@@ -32,76 +32,90 @@
 }
 
 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyAllowed(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->Allowed();
 }
 
 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyPromoAllowed(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->PromoAllowed();
 }
 
 jboolean DataReductionProxySettingsAndroid::IsIncludedInAltFieldTrial(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return false;
 }
 
 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyEnabled(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->IsDataReductionProxyEnabled();
 }
 
 jboolean DataReductionProxySettingsAndroid::CanUseDataReductionProxy(
-    JNIEnv* env, jobject obj, jstring url) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& url) {
   return Settings()->CanUseDataReductionProxy(
       GURL(base::android::ConvertJavaStringToUTF16(env, url)));
 }
 
 jboolean DataReductionProxySettingsAndroid::WasLoFiModeActiveOnMainFrame(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->WasLoFiModeActiveOnMainFrame();
 }
 
 jboolean DataReductionProxySettingsAndroid::WasLoFiLoadImageRequestedBefore(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->WasLoFiLoadImageRequestedBefore();
 }
 
 void DataReductionProxySettingsAndroid::SetLoFiLoadImageRequested(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   Settings()->SetLoFiLoadImageRequested();
 }
 
 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyManaged(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->IsDataReductionProxyManaged();
 }
 
 void DataReductionProxySettingsAndroid::IncrementLoFiSnackbarShown(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   Settings()->IncrementLoFiSnackbarShown();
 }
 
 void DataReductionProxySettingsAndroid::IncrementLoFiUserRequestsForImages(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   Settings()->IncrementLoFiUserRequestsForImages();
 }
 
 void DataReductionProxySettingsAndroid::SetDataReductionProxyEnabled(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jboolean enabled) {
   Settings()->SetDataReductionProxyEnabled(enabled);
 }
 
 jlong DataReductionProxySettingsAndroid::GetDataReductionLastUpdateTime(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->GetDataReductionLastUpdateTime();
 }
 
 base::android::ScopedJavaLocalRef<jobject>
-DataReductionProxySettingsAndroid::GetContentLengths(JNIEnv* env,
-                                                     jobject obj) {
+DataReductionProxySettingsAndroid::GetContentLengths(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   int64 original_content_length;
   int64 received_content_length;
   int64 last_update_internal;
@@ -118,20 +132,23 @@
 
 ScopedJavaLocalRef<jlongArray>
 DataReductionProxySettingsAndroid::GetDailyOriginalContentLengths(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return GetDailyContentLengths(
       env, data_reduction_proxy::prefs::kDailyHttpOriginalContentLength);
 }
 
 ScopedJavaLocalRef<jlongArray>
 DataReductionProxySettingsAndroid::GetDailyReceivedContentLengths(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return GetDailyContentLengths(
       env, data_reduction_proxy::prefs::kDailyHttpReceivedContentLength);
 }
 
 jboolean DataReductionProxySettingsAndroid::IsDataReductionProxyUnreachable(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return Settings()->IsDataReductionProxyUnreachable();
 }
 
@@ -160,7 +177,7 @@
 
 ScopedJavaLocalRef<jstring> DataReductionProxySettingsAndroid::GetHttpProxyList(
     JNIEnv* env,
-    jobject obj) {
+    const JavaParamRef<jobject>& obj) {
   data_reduction_proxy::DataReductionProxyEventStore* event_store =
       Settings()->GetEventStore();
   if (!event_store)
@@ -170,7 +187,9 @@
 }
 
 ScopedJavaLocalRef<jstring>
-DataReductionProxySettingsAndroid::GetHttpsProxyList(JNIEnv* env, jobject obj) {
+DataReductionProxySettingsAndroid::GetHttpsProxyList(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   data_reduction_proxy::DataReductionProxyEventStore* event_store =
       Settings()->GetEventStore();
   if (!event_store)
@@ -188,8 +207,9 @@
 }
 
 ScopedJavaLocalRef<jstring>
-DataReductionProxySettingsAndroid::GetLastBypassEvent(JNIEnv* env,
-                                                      jobject obj) {
+DataReductionProxySettingsAndroid::GetLastBypassEvent(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   data_reduction_proxy::DataReductionProxyEventStore* event_store =
       Settings()->GetEventStore();
   if (!event_store)
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.h b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.h
index e79be28..2512284 100644
--- a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.h
+++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.h
@@ -34,34 +34,67 @@
   void InitDataReductionProxySettings(Profile* profile);
 
   // JNI wrapper interfaces to the indentically-named superclass methods.
-  jboolean IsDataReductionProxyAllowed(JNIEnv* env, jobject obj);
-  jboolean IsDataReductionProxyPromoAllowed(JNIEnv* env, jobject obj);
-  jboolean IsIncludedInAltFieldTrial(JNIEnv* env, jobject obj);
-  jboolean IsDataReductionProxyEnabled(JNIEnv* env, jobject obj);
-  jboolean CanUseDataReductionProxy(JNIEnv* env, jobject obj, jstring url);
-  jboolean WasLoFiModeActiveOnMainFrame(JNIEnv* env, jobject obj);
-  jboolean WasLoFiLoadImageRequestedBefore(JNIEnv* env, jobject obj);
-  void SetLoFiLoadImageRequested(JNIEnv* env, jobject obj);
-  jboolean IsDataReductionProxyManaged(JNIEnv* env, jobject obj);
-  void IncrementLoFiSnackbarShown(JNIEnv* env, jobject obj);
-  void IncrementLoFiUserRequestsForImages(JNIEnv* env, jobject obj);
-  void SetDataReductionProxyEnabled(JNIEnv* env, jobject obj, jboolean enabled);
+  jboolean IsDataReductionProxyAllowed(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsDataReductionProxyPromoAllowed(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsIncludedInAltFieldTrial(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsDataReductionProxyEnabled(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean CanUseDataReductionProxy(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& url);
+  jboolean WasLoFiModeActiveOnMainFrame(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean WasLoFiLoadImageRequestedBefore(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void SetLoFiLoadImageRequested(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsDataReductionProxyManaged(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void IncrementLoFiSnackbarShown(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void IncrementLoFiUserRequestsForImages(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  void SetDataReductionProxyEnabled(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean enabled);
 
-  jlong GetDataReductionLastUpdateTime(JNIEnv* env, jobject obj);
-  ScopedJavaLocalRef<jlongArray> GetDailyOriginalContentLengths(JNIEnv* env,
-                                                                jobject obj);
-  ScopedJavaLocalRef<jlongArray> GetDailyReceivedContentLengths(JNIEnv* env,
-                                                                jobject obj);
+  jlong GetDataReductionLastUpdateTime(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  ScopedJavaLocalRef<jlongArray> GetDailyOriginalContentLengths(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  ScopedJavaLocalRef<jlongArray> GetDailyReceivedContentLengths(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Return a Java |ContentLengths| object wrapping the results of a call to
   // DataReductionProxySettings::GetContentLengths.
-  base::android::ScopedJavaLocalRef<jobject> GetContentLengths(JNIEnv* env,
-                                                               jobject obj);
+  base::android::ScopedJavaLocalRef<jobject> GetContentLengths(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Determines whether the data reduction proxy is unreachable. This is
   // done by keeping a count of requests which go through proxy vs those
   // which should have gone through the proxy based on the config.
-  jboolean IsDataReductionProxyUnreachable(JNIEnv* env, jobject obj);
+  jboolean IsDataReductionProxyUnreachable(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   ScopedJavaLocalRef<jstring> GetTokenForAuthChallenge(JNIEnv* env,
                                                        jobject obj,
@@ -70,15 +103,21 @@
 
   // Returns a Java string of the Data Reduction Proxy proxy list for HTTP
   // origins as a semi-colon delimited list.
-  ScopedJavaLocalRef<jstring> GetHttpProxyList(JNIEnv* env, jobject obj);
+  ScopedJavaLocalRef<jstring> GetHttpProxyList(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Returns a Java string of the Data Reduction Proxy proxy list for HTTPS
   // origins as a semi-colon delimited list.
-  ScopedJavaLocalRef<jstring> GetHttpsProxyList(JNIEnv* env, jobject obj);
+  ScopedJavaLocalRef<jstring> GetHttpsProxyList(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Returns a Java string of the last Data Reduction Proxy bypass event as
   // a JSON object.
-  ScopedJavaLocalRef<jstring> GetLastBypassEvent(JNIEnv* env, jobject obj);
+  ScopedJavaLocalRef<jstring> GetLastBypassEvent(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Registers the native methods to be call from Java.
   static bool Register(JNIEnv* env);
diff --git a/chrome/browser/notifications/notification_ui_manager_android.cc b/chrome/browser/notifications/notification_ui_manager_android.cc
index 9943969..cf2b78a 100644
--- a/chrome/browser/notifications/notification_ui_manager_android.cc
+++ b/chrome/browser/notifications/notification_ui_manager_android.cc
@@ -55,10 +55,10 @@
 
 bool NotificationUIManagerAndroid::OnNotificationClicked(
     JNIEnv* env,
-    jobject java_object,
+    const JavaParamRef<jobject>& java_object,
     jlong persistent_notification_id,
-    jstring java_origin,
-    jstring java_tag,
+    const JavaParamRef<jstring>& java_origin,
+    const JavaParamRef<jstring>& java_tag,
     jint action_index) {
   GURL origin(ConvertJavaStringToUTF8(env, java_origin));
   std::string tag = ConvertJavaStringToUTF8(env, java_tag);
@@ -80,10 +80,10 @@
 
 bool NotificationUIManagerAndroid::OnNotificationClosed(
     JNIEnv* env,
-    jobject java_object,
+    const JavaParamRef<jobject>& java_object,
     jlong persistent_notification_id,
-    jstring java_origin,
-    jstring java_tag,
+    const JavaParamRef<jstring>& java_origin,
+    const JavaParamRef<jstring>& java_tag,
     jboolean by_user) {
   GURL origin(ConvertJavaStringToUTF8(env, java_origin));
   std::string tag = ConvertJavaStringToUTF8(env, java_tag);
diff --git a/chrome/browser/notifications/notification_ui_manager_android.h b/chrome/browser/notifications/notification_ui_manager_android.h
index 41a0af3..33f37f3 100644
--- a/chrome/browser/notifications/notification_ui_manager_android.h
+++ b/chrome/browser/notifications/notification_ui_manager_android.h
@@ -30,20 +30,22 @@
   ~NotificationUIManagerAndroid() override;
 
   // Called by the Java implementation when the notification has been clicked.
-  bool OnNotificationClicked(JNIEnv* env,
-                             jobject java_object,
-                             jlong persistent_notification_id,
-                             jstring java_origin,
-                             jstring java_tag,
-                             jint action_index);
+  bool OnNotificationClicked(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& java_object,
+      jlong persistent_notification_id,
+      const base::android::JavaParamRef<jstring>& java_origin,
+      const base::android::JavaParamRef<jstring>& java_tag,
+      jint action_index);
 
   // Called by the Java implementation when the notification has been closed.
-  bool OnNotificationClosed(JNIEnv* env,
-                            jobject java_object,
-                            jlong persistent_notification_id,
-                            jstring java_origin,
-                            jstring java_tag,
-                            jboolean by_user);
+  bool OnNotificationClosed(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& java_object,
+      jlong persistent_notification_id,
+      const base::android::JavaParamRef<jstring>& java_origin,
+      const base::android::JavaParamRef<jstring>& java_tag,
+      jboolean by_user);
 
   // NotificationUIManager implementation.
   void Add(const Notification& notification, Profile* profile) override;
diff --git a/chrome/browser/permissions/permission_update_infobar_delegate_android.cc b/chrome/browser/permissions/permission_update_infobar_delegate_android.cc
index 4a876d1..1999ae0 100644
--- a/chrome/browser/permissions/permission_update_infobar_delegate_android.cc
+++ b/chrome/browser/permissions/permission_update_infobar_delegate_android.cc
@@ -119,7 +119,9 @@
 }
 
 void PermissionUpdateInfoBarDelegate::OnPermissionResult(
-    JNIEnv* env, jobject obj, jboolean all_permissions_granted) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jboolean all_permissions_granted) {
   base::ResetAndReturn(&callback_).Run(all_permissions_granted);
   infobar()->RemoveSelf();
 }
diff --git a/chrome/browser/permissions/permission_update_infobar_delegate_android.h b/chrome/browser/permissions/permission_update_infobar_delegate_android.h
index dc3b1cb..34db3c7a 100644
--- a/chrome/browser/permissions/permission_update_infobar_delegate_android.h
+++ b/chrome/browser/permissions/permission_update_infobar_delegate_android.h
@@ -55,8 +55,9 @@
 
   static bool RegisterPermissionUpdateInfoBarDelegate(JNIEnv* env);
 
-  void OnPermissionResult(
-      JNIEnv* env, jobject obj, jboolean all_permissions_granted);
+  void OnPermissionResult(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj,
+                          jboolean all_permissions_granted);
 
  private:
   PermissionUpdateInfoBarDelegate(
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
index 51dbe4e..a6e56397 100644
--- a/chrome/browser/plugins/plugin_power_saver_browsertest.cc
+++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -385,12 +385,8 @@
   LoadHTML(
       "<object id='plugin' data='fake.swf' "
       "    type='application/x-ppapi-tests' width='400' height='100'>"
-      "</object>"
-      "<object id='plugin_poster' data='fake.swf' poster='click_me.png' "
-      "    type='application/x-ppapi-tests' width='400' height='100'>"
       "</object>");
   VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin");
-  VerifyPluginMarkedEssential(GetActiveWebContents(), "plugin_poster");
 }
 
 IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, SmallCrossOrigin) {
diff --git a/chrome/browser/prerender/external_prerender_handler_android.cc b/chrome/browser/prerender/external_prerender_handler_android.cc
index e02dfee..8714710b 100644
--- a/chrome/browser/prerender/external_prerender_handler_android.cc
+++ b/chrome/browser/prerender/external_prerender_handler_android.cc
@@ -22,14 +22,15 @@
 
 namespace prerender {
 
-bool ExternalPrerenderHandlerAndroid::AddPrerender(JNIEnv* env,
-                                                   jobject obj,
-                                                   jobject jprofile,
-                                                   jobject jweb_contents,
-                                                   jstring jurl,
-                                                   jstring jreferrer,
-                                                   jint width,
-                                                   jint height) {
+bool ExternalPrerenderHandlerAndroid::AddPrerender(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& jprofile,
+    const JavaParamRef<jobject>& jweb_contents,
+    const JavaParamRef<jstring>& jurl,
+    const JavaParamRef<jstring>& jreferrer,
+    jint width,
+    jint height) {
   Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
 
   GURL url = GURL(ConvertJavaStringToUTF16(env, jurl));
@@ -60,8 +61,9 @@
   return true;
 }
 
-void ExternalPrerenderHandlerAndroid::CancelCurrentPrerender(JNIEnv* env,
-                                                             jobject object) {
+void ExternalPrerenderHandlerAndroid::CancelCurrentPrerender(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& object) {
   if (!prerender_handle_)
     return;
   prerender_handle_->OnCancel();
diff --git a/chrome/browser/prerender/external_prerender_handler_android.h b/chrome/browser/prerender/external_prerender_handler_android.h
index 329dac40b..4430cbc 100644
--- a/chrome/browser/prerender/external_prerender_handler_android.h
+++ b/chrome/browser/prerender/external_prerender_handler_android.h
@@ -28,16 +28,18 @@
   // Add a prerender with the given url and referrer on the PrerenderManager of
   // the given profile. This is restricted to a single prerender at a time.
   bool AddPrerender(JNIEnv* env,
-                    jobject obj,
-                    jobject profile,
-                    jobject jweb_contents,
-                    jstring url,
-                    jstring referrer,
+                    const base::android::JavaParamRef<jobject>& obj,
+                    const base::android::JavaParamRef<jobject>& profile,
+                    const base::android::JavaParamRef<jobject>& jweb_contents,
+                    const base::android::JavaParamRef<jstring>& url,
+                    const base::android::JavaParamRef<jstring>& referrer,
                     jint width,
                     jint height);
 
   // Cancel the prerender associated with the prerender_handle_
-  void CancelCurrentPrerender(JNIEnv* env, jobject object);
+  void CancelCurrentPrerender(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& object);
 
   // Whether the PrerenderManager associated with the given profile has any
   // prerenders for the url.
diff --git a/chrome/browser/profiles/profile_android.cc b/chrome/browser/profiles/profile_android.cc
index 9c92901c..2ec4bbb 100644
--- a/chrome/browser/profiles/profile_android.cc
+++ b/chrome/browser/profiles/profile_android.cc
@@ -65,14 +65,16 @@
   return ScopedJavaLocalRef<jobject>(profile_android->obj_);
 }
 
-void ProfileAndroid::DestroyWhenAppropriate(JNIEnv* env, jobject obj) {
+void ProfileAndroid::DestroyWhenAppropriate(JNIEnv* env,
+                                            const JavaParamRef<jobject>& obj) {
   // Don't delete the Profile directly because the corresponding
   // RenderViewHost might not be deleted yet.
   ProfileDestroyer::DestroyProfileWhenAppropriate(profile_);
 }
 
 base::android::ScopedJavaLocalRef<jobject> ProfileAndroid::GetOriginalProfile(
-    JNIEnv* env, jobject obj) {
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   ProfileAndroid* original_profile = ProfileAndroid::FromProfile(
       profile_->GetOriginalProfile());
   DCHECK(original_profile);
@@ -80,18 +82,22 @@
 }
 
 base::android::ScopedJavaLocalRef<jobject>
-ProfileAndroid::GetOffTheRecordProfile(JNIEnv* env, jobject obj) {
+ProfileAndroid::GetOffTheRecordProfile(JNIEnv* env,
+                                       const JavaParamRef<jobject>& obj) {
   ProfileAndroid* otr_profile = ProfileAndroid::FromProfile(
       profile_->GetOffTheRecordProfile());
   DCHECK(otr_profile);
   return otr_profile->GetJavaObject();
 }
 
-jboolean ProfileAndroid::HasOffTheRecordProfile(JNIEnv* env, jobject obj) {
+jboolean ProfileAndroid::HasOffTheRecordProfile(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return profile_->HasOffTheRecordProfile();
 }
 
-jboolean ProfileAndroid::IsOffTheRecord(JNIEnv* env, jobject obj) {
+jboolean ProfileAndroid::IsOffTheRecord(JNIEnv* env,
+                                        const JavaParamRef<jobject>& obj) {
   return profile_->IsOffTheRecord();
 }
 
diff --git a/chrome/browser/profiles/profile_android.h b/chrome/browser/profiles/profile_android.h
index e6ed2c8..b7a55d3e7 100644
--- a/chrome/browser/profiles/profile_android.h
+++ b/chrome/browser/profiles/profile_android.h
@@ -26,11 +26,13 @@
       jclass clazz);
 
   // Destroys this Profile when possible.
-  void DestroyWhenAppropriate(JNIEnv* env, jobject obj);
+  void DestroyWhenAppropriate(JNIEnv* env,
+                              const base::android::JavaParamRef<jobject>& obj);
 
   // Return the original profile.
   base::android::ScopedJavaLocalRef<jobject> GetOriginalProfile(
-      JNIEnv* env, jobject obj);
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Return the incognito profile.
   //
@@ -38,13 +40,17 @@
   // exist. If this isn't what you want, you need to check
   // HasOffTheRecordProfile() first.
   base::android::ScopedJavaLocalRef<jobject> GetOffTheRecordProfile(
-      JNIEnv* env, jobject obj);
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Return whether an off the record profile exists.
-  jboolean HasOffTheRecordProfile(JNIEnv* env, jobject obj);
+  jboolean HasOffTheRecordProfile(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
 
   // Whether this profile is off the record.
-  jboolean IsOffTheRecord(JNIEnv* env, jobject obj);
+  jboolean IsOffTheRecord(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj);
 
   explicit ProfileAndroid(Profile* profile);
   ~ProfileAndroid() override;
diff --git a/chrome/browser/profiles/profile_attributes_storage_unittest.cc b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
index 9f8a153..15bb566 100644
--- a/chrome/browser/profiles/profile_attributes_storage_unittest.cc
+++ b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
@@ -105,18 +106,16 @@
   }
 
   void AddTestingProfile() {
-    unsigned long number_of_profiles =
-        static_cast<unsigned long>(storage()->GetNumberOfProfiles());
+    size_t number_of_profiles = storage()->GetNumberOfProfiles();
 
     storage()->AddProfile(
-        GetProfilePath(
-            base::StringPrintf("testing_profile_path%lu", number_of_profiles)),
-        base::ASCIIToUTF16(
-            base::StringPrintf("testing_profile_name%lu", number_of_profiles)),
-        std::string(
-            base::StringPrintf("testing_profile_gaia%lu", number_of_profiles)),
-        base::ASCIIToUTF16(
-            base::StringPrintf("testing_profile_user%lu", number_of_profiles)),
+        GetProfilePath(base::StringPrintf("testing_profile_path%" PRIuS,
+                                          number_of_profiles)),
+        base::ASCIIToUTF16(base::StringPrintf("testing_profile_name%" PRIuS,
+                                              number_of_profiles)),
+        base::StringPrintf("testing_profile_gaia%" PRIuS, number_of_profiles),
+        base::ASCIIToUTF16(base::StringPrintf("testing_profile_user%" PRIuS,
+                                              number_of_profiles)),
         number_of_profiles,
         std::string(""));
 
diff --git a/chrome/browser/resources/pdf/navigator.js b/chrome/browser/resources/pdf/navigator.js
index e6bd7ad..9a2f6aa 100644
--- a/chrome/browser/resources/pdf/navigator.js
+++ b/chrome/browser/resources/pdf/navigator.js
@@ -73,11 +73,21 @@
    *    position.
    */
   onViewportReceived_: function(viewportPosition) {
+    var originalUrl = this.originalUrl_;
+    var hashIndex = originalUrl.search('#');
+    if (hashIndex != -1)
+      originalUrl = originalUrl.substring(0, hashIndex);
+
+    var newUrl = viewportPosition.url;
+    hashIndex = newUrl.search('#');
+    if (hashIndex != -1)
+      newUrl = newUrl.substring(0, hashIndex);
+
     var pageNumber = viewportPosition.page;
-    if (pageNumber != undefined)
+    if (pageNumber != undefined && originalUrl == newUrl)
       this.viewport_.goToPage(pageNumber);
     else
-      this.navigateInCurrentTabCallback_(viewportPosition['url']);
+      this.navigateInCurrentTabCallback_(viewportPosition.url);
   },
 
   /**
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html
index 1bbdc278..2b8eac5d 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.html
+++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -1,5 +1,4 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
 <link rel="import" href="chrome://md-settings/advanced_page/advanced_page.html">
 <link rel="import" href="chrome://md-settings/basic_page/basic_page.html">
 
@@ -7,15 +6,17 @@
   <link rel="import" type="css" href="settings_main.css">
   <template>
     <content select="paper-icon-button"></content>
-    <iron-pages id="pageContainer" attr-for-selected="data-route-page"
-        selected="[[getSelectedPage_(currentRoute)]]">
-      <settings-basic-page data-route-page="basic" prefs="{{prefs}}"
-          current-route="{{currentRoute}}">
-      </settings-basic-page>
-      <settings-advanced-page data-route-page="advanced" prefs="{{prefs}}"
-          current-route="{{currentRoute}}">
-      </settings-advanced-page>
-    </iron-pages>
+    <div id="pageContainer">
+      <template is="dom-if" if="[[!showAdvancedPage_]]">
+        <settings-basic-page prefs="{{prefs}}" current-route="{{currentRoute}}">
+        </settings-basic-page>
+      </template>
+      <template is="dom-if" if="[[showAdvancedPage_]]">
+        <settings-advanced-page prefs="{{prefs}}"
+            current-route="{{currentRoute}}">
+        </settings-advanced-page>
+      </template>
+    </div>
   </template>
   <script src="settings_main.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.js b/chrome/browser/resources/settings/settings_main/settings_main.js
index 1033b51..f683d47 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.js
+++ b/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -38,6 +38,12 @@
       notify: true,
       observer: 'currentRouteChanged_',
     },
+
+    // If false the 'basic' page should be shown.
+    showAdvancedPage_: {
+      type: Boolean,
+      value: false
+    }
   },
 
   listeners: {
@@ -46,6 +52,8 @@
 
   /** @private */
   currentRouteChanged_: function(newRoute, oldRoute) {
+    this.showAdvancedPage_ = newRoute.page == 'advanced';
+
     var pageContainer = this.$.pageContainer;
     if (!oldRoute) {
       pageContainer.classList.toggle('expanded', newRoute.section);
@@ -69,9 +77,4 @@
       pageContainer.scrollTop = 0;
     }
   },
-
-  /** @private */
-  getSelectedPage_: function(currentRoute) {
-    return currentRoute.page || 'basic';
-  },
 });
diff --git a/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win.cc b/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win.cc
index e55eec2..6c17833 100644
--- a/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win.cc
@@ -64,7 +64,7 @@
                KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
     while (true) {
       void* buffer = data->empty() ? nullptr : &(*data)[0];
-      DWORD buffer_size = base::saturated_cast<DWORD, size_t>(data->size());
+      DWORD buffer_size = base::saturated_cast<DWORD>(data->size());
       LONG result =
           key.ReadValue(value_name.c_str(), buffer, &buffer_size, nullptr);
       // Trim the output string and return if all data was read.
@@ -91,7 +91,7 @@
       key.DeleteValue(GetValueNameForProfile(profile).c_str());
     } else {
       key.WriteValue(GetValueNameForProfile(profile).c_str(), &data[0],
-                     base::saturated_cast<DWORD, size_t>(data.size()),
+                     base::saturated_cast<DWORD>(data.size()),
                      REG_BINARY);
     }
   }
diff --git a/chrome/browser/search_engines/template_url_service_android.cc b/chrome/browser/search_engines/template_url_service_android.cc
index 8ab11e0..8e88588 100644
--- a/chrome/browser/search_engines/template_url_service_android.cc
+++ b/chrome/browser/search_engines/template_url_service_android.cc
@@ -44,13 +44,14 @@
   template_url_service_->RemoveObserver(this);
 }
 
-void TemplateUrlServiceAndroid::Load(JNIEnv* env, jobject obj) {
+void TemplateUrlServiceAndroid::Load(JNIEnv* env,
+                                     const JavaParamRef<jobject>& obj) {
   template_url_service_->Load();
 }
 
 void TemplateUrlServiceAndroid::SetUserSelectedDefaultSearchProvider(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jint selected_index) {
   std::vector<TemplateURL*> template_urls =
       template_url_service_->GetTemplateURLs();
@@ -64,8 +65,9 @@
   template_url_service_->SetUserSelectedDefaultSearchProvider(template_url);
 }
 
-jint TemplateUrlServiceAndroid::GetDefaultSearchProvider(JNIEnv* env,
-                                                         jobject obj) {
+jint TemplateUrlServiceAndroid::GetDefaultSearchProvider(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   std::vector<TemplateURL*> template_urls =
       template_url_service_->GetTemplateURLs();
   TemplateURL* default_search_provider =
@@ -77,21 +79,26 @@
   return -1;
 }
 
-jboolean TemplateUrlServiceAndroid::IsLoaded(JNIEnv* env, jobject obj) {
+jboolean TemplateUrlServiceAndroid::IsLoaded(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   return template_url_service_->loaded();
 }
 
-jint TemplateUrlServiceAndroid::GetTemplateUrlCount(JNIEnv* env, jobject obj) {
+jint TemplateUrlServiceAndroid::GetTemplateUrlCount(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return template_url_service_->GetTemplateURLs().size();
 }
 
-jboolean TemplateUrlServiceAndroid::IsSearchProviderManaged(JNIEnv* env,
-                                                            jobject obj) {
+jboolean TemplateUrlServiceAndroid::IsSearchProviderManaged(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   return template_url_service_->is_default_search_managed();
 }
 
-jboolean TemplateUrlServiceAndroid::IsSearchByImageAvailable(JNIEnv* env,
-                                                             jobject obj) {
+jboolean TemplateUrlServiceAndroid::IsSearchByImageAvailable(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   const TemplateURL* default_search_provider =
       template_url_service_->GetDefaultSearchProvider();
   return default_search_provider &&
@@ -100,8 +107,9 @@
           template_url_service_->search_terms_data());
 }
 
-jboolean TemplateUrlServiceAndroid::IsDefaultSearchEngineGoogle(JNIEnv* env,
-                                                                jobject obj) {
+jboolean TemplateUrlServiceAndroid::IsDefaultSearchEngineGoogle(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   TemplateURL* default_search_provider =
       template_url_service_->GetDefaultSearchProvider();
   return default_search_provider &&
@@ -110,9 +118,10 @@
 }
 
 base::android::ScopedJavaLocalRef<jobject>
-TemplateUrlServiceAndroid::GetPrepopulatedTemplateUrlAt(JNIEnv* env,
-                                                        jobject obj,
-                                                        jint index) {
+TemplateUrlServiceAndroid::GetPrepopulatedTemplateUrlAt(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint index) {
   TemplateURL* template_url = template_url_service_->GetTemplateURLs()[index];
   if (!IsPrepopulatedTemplate(template_url) &&
       !template_url->created_by_policy())
@@ -149,9 +158,10 @@
 }
 
 base::android::ScopedJavaLocalRef<jstring>
-TemplateUrlServiceAndroid::GetUrlForSearchQuery(JNIEnv* env,
-                                                jobject obj,
-                                                jstring jquery) {
+TemplateUrlServiceAndroid::GetUrlForSearchQuery(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jquery) {
   const TemplateURL* default_provider =
       template_url_service_->GetDefaultSearchProvider();
 
@@ -171,9 +181,10 @@
 }
 
 base::android::ScopedJavaLocalRef<jstring>
-TemplateUrlServiceAndroid::GetUrlForVoiceSearchQuery(JNIEnv* env,
-                                                     jobject obj,
-                                                     jstring jquery) {
+TemplateUrlServiceAndroid::GetUrlForVoiceSearchQuery(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jquery) {
   base::string16 query(base::android::ConvertJavaStringToUTF16(env, jquery));
   std::string url;
 
@@ -188,10 +199,11 @@
 }
 
 base::android::ScopedJavaLocalRef<jstring>
-TemplateUrlServiceAndroid::ReplaceSearchTermsInUrl(JNIEnv* env,
-                                                   jobject obj,
-                                                   jstring jquery,
-                                                   jstring jcurrent_url) {
+TemplateUrlServiceAndroid::ReplaceSearchTermsInUrl(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jquery,
+    const JavaParamRef<jstring>& jcurrent_url) {
   TemplateURL* default_provider =
       template_url_service_->GetDefaultSearchProvider();
 
@@ -212,9 +224,9 @@
 base::android::ScopedJavaLocalRef<jstring>
 TemplateUrlServiceAndroid::GetUrlForContextualSearchQuery(
     JNIEnv* env,
-    jobject obj,
-    jstring jquery,
-    jstring jalternate_term,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& jquery,
+    const JavaParamRef<jstring>& jalternate_term,
     jboolean jshould_prefetch) {
   base::string16 query(base::android::ConvertJavaStringToUTF16(env, jquery));
   std::string url;
@@ -246,7 +258,7 @@
 base::android::ScopedJavaLocalRef<jstring>
 TemplateUrlServiceAndroid::GetSearchEngineUrlFromTemplateUrl(
     JNIEnv* env,
-    jobject obj,
+    const JavaParamRef<jobject>& obj,
     jint index) {
   TemplateURL* template_url = template_url_service_->GetTemplateURLs()[index];
   std::string url(template_url->url_ref().ReplaceSearchTerms(
diff --git a/chrome/browser/search_engines/template_url_service_android.h b/chrome/browser/search_engines/template_url_service_android.h
index 091ccd9d..0ba635f 100644
--- a/chrome/browser/search_engines/template_url_service_android.h
+++ b/chrome/browser/search_engines/template_url_service_android.h
@@ -21,40 +21,53 @@
  public:
   TemplateUrlServiceAndroid(JNIEnv* env, jobject obj);
 
-  void Load(JNIEnv* env, jobject obj);
-  void SetUserSelectedDefaultSearchProvider(JNIEnv* env,
-                                            jobject obj,
-                                            jint selected_index);
-  jint GetDefaultSearchProvider(JNIEnv* env, jobject obj);
-  jint GetTemplateUrlCount(JNIEnv* env, jobject obj);
-  jboolean IsLoaded(JNIEnv* env, jobject obj);
-  base::android::ScopedJavaLocalRef<jobject>
-      GetPrepopulatedTemplateUrlAt(JNIEnv* env, jobject obj, jint index);
-  jboolean IsSearchProviderManaged(JNIEnv* env, jobject obj);
-  jboolean IsSearchByImageAvailable(JNIEnv* env, jobject obj);
-  jboolean IsDefaultSearchEngineGoogle(JNIEnv* env, jobject obj);
+  void Load(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void SetUserSelectedDefaultSearchProvider(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint selected_index);
+  jint GetDefaultSearchProvider(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jint GetTemplateUrlCount(JNIEnv* env,
+                           const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsLoaded(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj);
+  base::android::ScopedJavaLocalRef<jobject> GetPrepopulatedTemplateUrlAt(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint index);
+  jboolean IsSearchProviderManaged(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsSearchByImageAvailable(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  jboolean IsDefaultSearchEngineGoogle(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
   base::android::ScopedJavaLocalRef<jstring> GetUrlForSearchQuery(
       JNIEnv* env,
-      jobject obj,
-      jstring jquery);
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jquery);
   base::android::ScopedJavaLocalRef<jstring> GetUrlForVoiceSearchQuery(
       JNIEnv* env,
-      jobject obj,
-      jstring jquery);
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jquery);
   base::android::ScopedJavaLocalRef<jstring> ReplaceSearchTermsInUrl(
       JNIEnv* env,
-      jobject obj,
-      jstring jquery,
-      jstring jcurrent_url);
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jquery,
+      const base::android::JavaParamRef<jstring>& jcurrent_url);
   base::android::ScopedJavaLocalRef<jstring> GetUrlForContextualSearchQuery(
       JNIEnv* env,
-      jobject obj,
-      jstring jquery,
-      jstring jalternate_term,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jquery,
+      const base::android::JavaParamRef<jstring>& jalternate_term,
       jboolean jshould_prefetch);
   base::android::ScopedJavaLocalRef<jstring> GetSearchEngineUrlFromTemplateUrl(
       JNIEnv* env,
-      jobject obj,
+      const base::android::JavaParamRef<jobject>& obj,
       jint index);
 
   static bool Register(JNIEnv* env);
diff --git a/chrome/browser/sessions/tab_restore_browsertest.cc b/chrome/browser/sessions/tab_restore_browsertest.cc
index 97b9eed..cc65c1d 100644
--- a/chrome/browser/sessions/tab_restore_browsertest.cc
+++ b/chrome/browser/sessions/tab_restore_browsertest.cc
@@ -24,7 +24,6 @@
 #include "components/sessions/core/tab_restore_service.h"
 #include "components/sessions/core/tab_restore_service_observer.h"
 #include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
@@ -85,9 +84,6 @@
     url2_ = ui_test_utils::GetTestUrl(
         base::FilePath().AppendASCII("session_history"),
         base::FilePath().AppendASCII("bot2.html"));
-    url3_ = ui_test_utils::GetTestUrl(
-        base::FilePath().AppendASCII("session_history"),
-        base::FilePath().AppendASCII("bot3.html"));
   }
 
  protected:
@@ -196,15 +192,8 @@
     observer.Wait();
   }
 
-  bool RemoveTabByLastVisit(
-      Browser* browser, const GURL& url, const base::Time& time) {
-    return TabRestoreServiceFactory::GetForProfile(
-        browser->profile())->RemoveTabByLastVisit(url, time);
-  }
-
   GURL url1_;
   GURL url2_;
-  GURL url3_;
 
   const BrowserList* active_browser_list_;
 
@@ -645,82 +634,3 @@
   EXPECT_EQ(url1_,
             browser()->tab_strip_model()->GetWebContentsAt(1)->GetURL());
 }
-
-IN_PROC_BROWSER_TEST_F(TabRestoreTest, DontRestoreRemovedVisit) {
-  // Navigate to |url1_| and close the tab.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), url1_, NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  CloseTab(1);
-
-  // Navigate to |url2_|, then |url3_|, then go back to |url2_|
-  // and close the tab. Remove the entry corresponding to the visit of |url2_|.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), url2_, NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), url3_, CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  GoBack(browser());
-  base::Time visit_time(browser()->tab_strip_model()->GetWebContentsAt(1)->
-                            GetController().GetVisibleEntry()->GetTimestamp());
-  CloseTab(1);
-  ASSERT_TRUE(RemoveTabByLastVisit(browser(), url2_, visit_time));
-
-  // Restore the most recent tab. Although the tab visiting |url2_| and |url3_|
-  // was closed more recently, it was deleted, so we expect the restored tab
-  // to be the one navigating to |url1_|.
-  ASSERT_NO_FATAL_FAILURE(RestoreTab(0, 1));
-  ASSERT_EQ(url1_, browser()->tab_strip_model()->GetWebContentsAt(1)->
-                GetController().GetVisibleEntry()->GetURL());
-}
-
-IN_PROC_BROWSER_TEST_F(TabRestoreTest, DontRestoreRemovedVisitInWindow) {
-  // Open a window with 3 new tabs.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), GURL(chrome::kChromeUINewTabURL), NEW_WINDOW,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), url1_, CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), url2_, NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), url3_, NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
-
-  // Remember the last navigation time of the second tab.
-  base::Time visit_time(browser()->tab_strip_model()->GetWebContentsAt(1)->
-                            GetController().GetVisibleEntry()->GetTimestamp());
-
-  // Close the window.
-  content::WindowedNotificationObserver close_window_observer(
-      chrome::NOTIFICATION_BROWSER_CLOSED,
-      content::NotificationService::AllSources());
-  chrome::CloseWindow(browser());
-  close_window_observer.Wait();
-
-  // Remove the tab corresponding to the last navigation of the second tab;
-  // which is, of course, the second tab.
-  RemoveTabByLastVisit(GetBrowser(0), url2_, visit_time);
-
-  // Restore the closed window.
-  content::WindowedNotificationObserver open_window_observer(
-      chrome::NOTIFICATION_BROWSER_OPENED,
-      content::NotificationService::AllSources());
-  content::WindowedNotificationObserver load_stop_observer(
-      content::NOTIFICATION_LOAD_STOP,
-      content::NotificationService::AllSources());
-  chrome::RestoreTab(GetBrowser(0));
-  open_window_observer.Wait();
-  load_stop_observer.Wait();
-  TabStripModel* tabs = GetBrowser(1)->tab_strip_model();
-
-  // It should have two tabs navigated to |url1_| and |url3_|. The latter
-  // should still be active.
-  ASSERT_EQ(2, tabs->count());
-  ASSERT_EQ(url1_, tabs->GetWebContentsAt(0)->GetVisibleURL());
-  ASSERT_EQ(url3_, tabs->GetWebContentsAt(1)->GetVisibleURL());
-  ASSERT_EQ(1, tabs->active_index());
-}
diff --git a/chrome/browser/speech/tts_android.cc b/chrome/browser/speech/tts_android.cc
index e8ec307e..3d22831 100644
--- a/chrome/browser/speech/tts_android.cc
+++ b/chrome/browser/speech/tts_android.cc
@@ -100,23 +100,27 @@
   }
 }
 
-void TtsPlatformImplAndroid::VoicesChanged(JNIEnv* env, jobject obj) {
+void TtsPlatformImplAndroid::VoicesChanged(JNIEnv* env,
+                                           const JavaParamRef<jobject>& obj) {
   TtsController::GetInstance()->VoicesChanged();
 }
 
-void TtsPlatformImplAndroid::OnEndEvent(
-    JNIEnv* env, jobject obj, jint utterance_id) {
+void TtsPlatformImplAndroid::OnEndEvent(JNIEnv* env,
+                                        const JavaParamRef<jobject>& obj,
+                                        jint utterance_id) {
   SendFinalTtsEvent(utterance_id, TTS_EVENT_END,
                     static_cast<int>(utterance_.size()));
 }
 
-void TtsPlatformImplAndroid::OnErrorEvent(
-    JNIEnv* env, jobject obj, jint utterance_id) {
+void TtsPlatformImplAndroid::OnErrorEvent(JNIEnv* env,
+                                          const JavaParamRef<jobject>& obj,
+                                          jint utterance_id) {
   SendFinalTtsEvent(utterance_id, TTS_EVENT_ERROR, 0);
 }
 
-void TtsPlatformImplAndroid::OnStartEvent(
-    JNIEnv* env, jobject obj, jint utterance_id) {
+void TtsPlatformImplAndroid::OnStartEvent(JNIEnv* env,
+                                          const JavaParamRef<jobject>& obj,
+                                          jint utterance_id) {
   if (utterance_id != utterance_id_)
     return;
 
diff --git a/chrome/browser/speech/tts_android.h b/chrome/browser/speech/tts_android.h
index f38d674..19ef66d5 100644
--- a/chrome/browser/speech/tts_android.h
+++ b/chrome/browser/speech/tts_android.h
@@ -26,10 +26,17 @@
   void GetVoices(std::vector<VoiceData>* out_voices) override;
 
   // Methods called from Java via JNI.
-  void VoicesChanged(JNIEnv* env, jobject obj);
-  void OnEndEvent(JNIEnv* env, jobject obj, jint utterance_id);
-  void OnErrorEvent(JNIEnv* env, jobject obj, jint utterance_id);
-  void OnStartEvent(JNIEnv* env, jobject obj, jint utterance_id);
+  void VoicesChanged(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj);
+  void OnEndEvent(JNIEnv* env,
+                  const base::android::JavaParamRef<jobject>& obj,
+                  jint utterance_id);
+  void OnErrorEvent(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj,
+                    jint utterance_id);
+  void OnStartEvent(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj,
+                    jint utterance_id);
 
   // Static functions.
   static TtsPlatformImplAndroid* GetInstance();
diff --git a/chrome/browser/spellchecker/spellchecker_session_bridge_android.cc b/chrome/browser/spellchecker/spellchecker_session_bridge_android.cc
index cf02f8c..c10fedf 100644
--- a/chrome/browser/spellchecker/spellchecker_session_bridge_android.cc
+++ b/chrome/browser/spellchecker/spellchecker_session_bridge_android.cc
@@ -62,9 +62,9 @@
 
 void SpellCheckerSessionBridge::ProcessSpellCheckResults(
     JNIEnv* env,
-    jobject jobj,
-    jintArray offset_array,
-    jintArray length_array) {
+    const JavaParamRef<jobject>& jobj,
+    const JavaParamRef<jintArray>& offset_array,
+    const JavaParamRef<jintArray>& length_array) {
   std::vector<int> offsets;
   std::vector<int> lengths;
 
diff --git a/chrome/browser/spellchecker/spellchecker_session_bridge_android.h b/chrome/browser/spellchecker/spellchecker_session_bridge_android.h
index 23353bb8..6c56fae3 100644
--- a/chrome/browser/spellchecker/spellchecker_session_bridge_android.h
+++ b/chrome/browser/spellchecker/spellchecker_session_bridge_android.h
@@ -29,10 +29,11 @@
 
   // Receives information from Java side about the typos in a given string
   // of text, processes these and sends them to the renderer.
-  void ProcessSpellCheckResults(JNIEnv* env,
-                                jobject jobj,
-                                jintArray offset_array,
-                                jintArray length_array);
+  void ProcessSpellCheckResults(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& jobj,
+      const base::android::JavaParamRef<jintArray>& offset_array,
+      const base::android::JavaParamRef<jintArray>& length_array);
 
   // Sets the handle to the Java SpellCheckerSessionBridge object to null,
   // marking the Java object for garbage collection.
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 2c46aeb..791bfb6 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -16,7 +16,7 @@
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/run_loop.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
@@ -526,9 +526,7 @@
 
     sync_service_->RegisterDataTypeController(CreateDataTypeController(type));
     sync_service_->Initialize();
-
-    base::RunLoop run_loop;
-    run_loop.Run();
+    base::MessageLoop::current()->Run();
 
     // It's possible this test triggered an unrecoverable error, in which case
     // we can't get the sync count.
@@ -1268,7 +1266,8 @@
   ASSERT_EQ(0U, new_sync_profiles.size());
 }
 
-TEST_F(ProfileSyncServiceAutofillTest, ServerChangeRace) {
+// http://crbug.com/57884
+TEST_F(ProfileSyncServiceAutofillTest, DISABLED_ServerChangeRace) {
   // Once for MergeDataAndStartSyncing() and twice for ProcessSyncChanges(), via
   // LoadAutofillData().
   EXPECT_CALL(autofill_table_, GetAllAutofillEntries(_)).
@@ -1305,10 +1304,6 @@
   // to clean up.
   updater->CreateNewEntryAndWait(MakeAutofillEntry("server2", "entry2", 3));
 
-  // Let callbacks posted on UI thread execute.
-  base::RunLoop run_loop;
-  run_loop.RunUntilIdle();
-
   std::vector<AutofillEntry> sync_entries;
   std::vector<AutofillProfile> sync_profiles;
   ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
diff --git a/chrome/browser/sync/test/integration/multiple_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/multiple_client_preferences_sync_test.cc
deleted file mode 100644
index 638fd36..0000000
--- a/chrome/browser/sync/test/integration/multiple_client_preferences_sync_test.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2011 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/guid.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "chrome/browser/sync/test/integration/preferences_helper.h"
-#include "chrome/browser/sync/test/integration/sync_test.h"
-#include "chrome/common/pref_names.h"
-
-using preferences_helper::AwaitStringPrefMatches;
-using preferences_helper::ChangeStringPref;
-using preferences_helper::GetPrefs;
-
-class MultipleClientPreferencesSyncTest : public SyncTest {
- public:
-  MultipleClientPreferencesSyncTest() : SyncTest(MULTIPLE_CLIENT) {}
-  ~MultipleClientPreferencesSyncTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MultipleClientPreferencesSyncTest);
-};
-
-IN_PROC_BROWSER_TEST_F(MultipleClientPreferencesSyncTest, E2E_ENABLED(Sanity)) {
-  DisableVerifier();
-  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-  ASSERT_TRUE(AwaitStringPrefMatches(prefs::kHomePage));
-  const std::string new_home_page = base::StringPrintf(
-      "https://example.com/%s", base::GenerateGUID().c_str());
-  ChangeStringPref(0, prefs::kHomePage, new_home_page);
-  ASSERT_TRUE(AwaitStringPrefMatches(prefs::kHomePage));
-  for (int i = 0; i < num_clients(); ++i) {
-    ASSERT_EQ(new_home_page, GetPrefs(i)->GetString(prefs::kHomePage));
-  }
-}
diff --git a/chrome/browser/sync/test/integration/multiple_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/multiple_client_sessions_sync_test.cc
deleted file mode 100644
index fec489fd..0000000
--- a/chrome/browser/sync/test/integration/multiple_client_sessions_sync_test.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2012 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/guid.h"
-#include "base/strings/stringprintf.h"
-#include "chrome/browser/sessions/session_service.h"
-#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
-#include "chrome/browser/sync/test/integration/sessions_helper.h"
-#include "chrome/browser/sync/test/integration/sync_test.h"
-
-using sessions_helper::AwaitCheckForeignSessionsAgainst;
-using sessions_helper::CheckInitialState;
-using sessions_helper::OpenTabAndGetLocalWindows;
-using sessions_helper::ScopedWindowMap;
-using sessions_helper::SessionWindowMap;
-using sessions_helper::SyncedSessionVector;
-
-class MultipleClientSessionsSyncTest : public SyncTest {
- public:
-  MultipleClientSessionsSyncTest() : SyncTest(MULTIPLE_CLIENT) {}
-  ~MultipleClientSessionsSyncTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MultipleClientSessionsSyncTest);
-};
-
-// Timeout on Windows, see http://crbug.com/99819
-#if defined(OS_WIN)
-#define MAYBE_AllChanged DISABLED_AllChanged
-#define MAYBE_EncryptedAndChanged DISABLED_EncryptedAndChanged
-#else
-#define MAYBE_AllChanged AllChanged
-#define MAYBE_EncryptedAndChanged EncryptedAndChanged
-#endif
-
-IN_PROC_BROWSER_TEST_F(MultipleClientSessionsSyncTest,
-                       E2E_ENABLED(MAYBE_AllChanged)) {
-  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-
-  // Open tabs on all clients and retain window information.
-  std::vector<ScopedWindowMap> client_windows(num_clients());
-  for (int i = 0; i < num_clients(); ++i) {
-    SessionWindowMap windows;
-    std::string url = base::StringPrintf("http://127.0.0.1/bubba%s",
-        base::GenerateGUID().c_str());
-    ASSERT_TRUE(OpenTabAndGetLocalWindows(i, GURL(url), &windows));
-    client_windows[i].Reset(&windows);
-  }
-
-  // Get foreign session data from all clients and check it against all
-  // client_windows.
-  for (int i = 0; i < num_clients(); ++i) {
-    ASSERT_TRUE(AwaitCheckForeignSessionsAgainst(i, client_windows));
-  }
-}
-
-IN_PROC_BROWSER_TEST_F(MultipleClientSessionsSyncTest,
-                       MAYBE_EncryptedAndChanged) {
-  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-  std::vector<ScopedWindowMap> client_windows(num_clients());
-
-  for (int i = 0; i < num_clients(); ++i) {
-    ASSERT_TRUE(CheckInitialState(i));
-  }
-
-  // Enable encryption on client 0, should propagate to all other clients.
-  ASSERT_TRUE(EnableEncryption(0));
-
-  // Wait for sync.
-  // TODO(zea): Fix sync completion detection so we don't need this. For now,
-  // the profile sync service harness detects completion before all encryption
-  // changes are propagated.
-  ASSERT_TRUE(GetClient(0)->AwaitGroupSyncCycleCompletion(clients()));
-
-  // Open tabs on all clients and retain window information.
-  for (int i = 0; i < num_clients(); ++i) {
-    SessionWindowMap windows;
-    ASSERT_TRUE(OpenTabAndGetLocalWindows(
-        i, GURL(base::StringPrintf("http://127.0.0.1/bubba%i", i)), &windows));
-    client_windows[i].Reset(&windows);
-  }
-
-  // Get foreign session data from all clients and check it against all
-  // client_windows.
-  for (int i = 0; i < num_clients(); ++i) {
-    ASSERT_TRUE(AwaitCheckForeignSessionsAgainst(i, client_windows));
-    ASSERT_TRUE(IsEncryptionComplete(i));
-  }
-}
diff --git a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
index 3ba4e4b..dd52c82c 100644
--- a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
+
+#include "base/guid.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/sync/test/integration/preferences_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
@@ -31,6 +35,19 @@
   DISALLOW_COPY_AND_ASSIGN(TwoClientPreferencesSyncTest);
 };
 
+IN_PROC_BROWSER_TEST_F(TwoClientPreferencesSyncTest, E2E_ONLY(Sanity)) {
+  DisableVerifier();
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+  ASSERT_TRUE(AwaitStringPrefMatches(prefs::kHomePage));
+  const std::string new_home_page = base::StringPrintf(
+      "https://example.com/%s", base::GenerateGUID().c_str());
+  ChangeStringPref(0, prefs::kHomePage, new_home_page);
+  ASSERT_TRUE(AwaitStringPrefMatches(prefs::kHomePage));
+  for (int i = 0; i < num_clients(); ++i) {
+    ASSERT_EQ(new_home_page, GetPrefs(i)->GetString(prefs::kHomePage));
+  }
+}
+
 IN_PROC_BROWSER_TEST_F(TwoClientPreferencesSyncTest, BooleanPref) {
   ASSERT_TRUE(SetupSync());
   ASSERT_TRUE(AwaitBooleanPrefMatches(prefs::kHomePageIsNewTabPage));
diff --git a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc
index ce730d50..2a48d93 100644
--- a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
+
 #include "base/guid.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/sessions/session_service.h"
@@ -44,10 +46,12 @@
 #define MAYBE_SingleClientChanged DISABLED_SingleClientChanged
 #define MAYBE_BothChanged DISABLED_BothChanged
 #define MAYBE_DeleteIdleSession DISABLED_DeleteIdleSession
+#define MAYBE_AllChanged DISABLED_AllChanged
 #else
 #define MAYBE_SingleClientChanged SingleClientChanged
 #define MAYBE_BothChanged BothChanged
 #define MAYBE_DeleteIdleSession DeleteIdleSession
+#define MAYBE_AllChanged AllChanged
 #endif
 
 
@@ -70,6 +74,27 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest,
+                       E2E_ENABLED(MAYBE_AllChanged)) {
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+  // Open tabs on all clients and retain window information.
+  std::vector<ScopedWindowMap> client_windows(num_clients());
+  for (int i = 0; i < num_clients(); ++i) {
+    SessionWindowMap windows;
+    std::string url = base::StringPrintf("http://127.0.0.1/bubba%s",
+        base::GenerateGUID().c_str());
+    ASSERT_TRUE(OpenTabAndGetLocalWindows(i, GURL(url), &windows));
+    client_windows[i].Reset(&windows);
+  }
+
+  // Get foreign session data from all clients and check it against all
+  // client_windows.
+  for (int i = 0; i < num_clients(); ++i) {
+    ASSERT_TRUE(AwaitCheckForeignSessionsAgainst(i, client_windows));
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest,
                        SingleClientEnabledEncryption) {
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
 
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index cab10f70..358df54d 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -324,7 +324,8 @@
       password_manager::ContentPasswordManagerDriver::GetForRenderFrameHost(
           rfh);
   if (driver) {
-    driver->GetPasswordGenerationManager()->DetectAccountCreationForms(forms);
+    driver->GetPasswordGenerationManager()->DetectFormsEligibleForGeneration(
+        forms);
     driver->GetPasswordManager()->ProcessAutofillPredictions(driver, forms);
   }
 }
diff --git a/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm b/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm
index 6f35b926..35720f1 100644
--- a/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/passwords/passwords_bubble_cocoa_unittest.mm
@@ -180,10 +180,12 @@
   ShowBubble(false);
   EXPECT_TRUE(ManagePasswordsBubbleCocoa::instance());
   EXPECT_FALSE([controller() shouldOpenAsKeyWindow]);
+  EXPECT_FALSE([bubbleWindow() defaultButtonCell]);
 }
 
 TEST_F(ManagePasswordsBubbleCocoaTest, OpenWithFocus) {
   ShowBubble(true);
   EXPECT_TRUE(ManagePasswordsBubbleCocoa::instance());
   EXPECT_TRUE([controller() shouldOpenAsKeyWindow]);
+  EXPECT_TRUE([bubbleWindow() defaultButtonCell]);
 }
diff --git a/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller.mm b/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller.mm
index efc37c9e..6bd11ee 100644
--- a/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller.mm
@@ -86,7 +86,6 @@
   } else {
     NOTREACHED();
   }
-  [self performLayout];
 }
 
 - (void)performLayout {
@@ -97,7 +96,7 @@
   NSWindow* window = [self window];
   [[window contentView] setSubviews:@[ [currentController_ view] ]];
   NSButton* button = [currentController_ defaultButton];
-  if (button)
+  if (button && [self shouldOpenAsKeyWindow])
     [window setDefaultButtonCell:[button cell]];
 
   NSPoint anchorPoint;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 4155826..ce10108 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -637,8 +637,7 @@
     toolbar_bounds.Inset(kClientEdgeThickness, 0);
     BrowserView::Paint1pxHorizontalLine(
         canvas,
-        ThemeProperties::GetDefaultColor(
-            ThemeProperties::COLOR_TOOLBAR_SEPARATOR),
+        tp->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR),
         toolbar_bounds, true);
   } else {
     // Gross hack: We split the toolbar images into two pieces, since sometimes
@@ -696,17 +695,15 @@
     canvas->FillRect(
         gfx::Rect(x + kClientEdgeThickness,
                   toolbar_bounds.bottom() - kClientEdgeThickness,
-                  w - (2 * kClientEdgeThickness),
-                  kClientEdgeThickness),
-        ThemeProperties::GetDefaultColor(
-            ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
+                  w - (2 * kClientEdgeThickness), kClientEdgeThickness),
+        tp->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
   }
 }
 
 void BrowserNonClientFrameViewAsh::PaintContentEdge(gfx::Canvas* canvas) {
   DCHECK(!UsePackagedAppHeaderStyle() && !UseWebAppHeaderStyle());
-  canvas->FillRect(gfx::Rect(0, caption_button_container_->bounds().bottom(),
-                             width(), kClientEdgeThickness),
-                   ThemeProperties::GetDefaultColor(
-                       ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
+  canvas->FillRect(
+      gfx::Rect(0, caption_button_container_->bounds().bottom(), width(),
+                kClientEdgeThickness),
+      GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
 }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
index 0acd143..a6410b5e 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
@@ -587,8 +587,7 @@
     // Draw the content/toolbar separator.
     toolbar_bounds.Inset(kClientEdgeThickness, 0);
     BrowserView::Paint1pxHorizontalLine(
-        canvas, ThemeProperties::GetDefaultColor(
-                    ThemeProperties::COLOR_TOOLBAR_SEPARATOR),
+        canvas, tp->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR),
         toolbar_bounds, true);
   } else {
     // Gross hack: We split the toolbar images into two pieces, since sometimes
@@ -639,15 +638,14 @@
         gfx::Rect(x + kClientEdgeThickness,
                   toolbar_bounds.bottom() - kClientEdgeThickness,
                   w - (2 * kClientEdgeThickness), kClientEdgeThickness),
-        ThemeProperties::GetDefaultColor(
-            ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
+        tp->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
   }
 }
 
 void BrowserNonClientFrameViewMus::PaintContentEdge(gfx::Canvas* canvas) {
   DCHECK(!UsePackagedAppHeaderStyle() && !UseWebAppHeaderStyle());
   const int bottom = frame_values().normal_insets.bottom();
-  canvas->FillRect(gfx::Rect(0, bottom, width(), kClientEdgeThickness),
-                   ThemeProperties::GetDefaultColor(
-                       ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
+  canvas->FillRect(
+      gfx::Rect(0, bottom, width(), kClientEdgeThickness),
+      GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
 }
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 4f94cfe..e994d6a 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -293,15 +293,12 @@
     // Draw the separator below the Bookmarks Bar; this is fading in/out.
     if (ui::MaterialDesignController::IsModeMaterial()) {
       BrowserView::Paint1pxHorizontalLine(
-          canvas,
-          ThemeProperties::GetDefaultColor(
-              ThemeProperties::COLOR_TOOLBAR_SEPARATOR),
+          canvas, view->GetThemeProvider()->GetColor(
+                      ThemeProperties::COLOR_TOOLBAR_SEPARATOR),
           view->GetLocalBounds(), true);
     } else {
-      PaintHorizontalBorder(canvas,
-                            view,
-                            false,
-                            ThemeProperties::GetDefaultColor(
+      PaintHorizontalBorder(canvas, view, false,
+                            view->GetThemeProvider()->GetColor(
                                 ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
     }
   }
@@ -2110,8 +2107,7 @@
 
   contents_container_ = new views::View();
   contents_container_->set_background(views::Background::CreateSolidBackground(
-      ThemeProperties::GetDefaultColor(
-          ThemeProperties::COLOR_CONTROL_BACKGROUND)));
+      GetThemeProvider()->GetColor(ThemeProperties::COLOR_CONTROL_BACKGROUND)));
   contents_container_->AddChildView(devtools_web_view_);
   contents_container_->AddChildView(contents_web_view_);
   contents_container_->SetLayoutManager(new ContentsLayoutManager(
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index 2b19ade..7cf36e67 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -450,8 +450,7 @@
     canvas->FillRect(
         gfx::Rect(0, 0, width(),
                   views::NonClientFrameView::kClientEdgeThickness),
-        ThemeProperties::GetDefaultColor(
-            ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
+        GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
   }
 
   // Bottom border.
diff --git a/chrome/browser/ui/webui/browsing_history_handler.cc b/chrome/browser/ui/webui/browsing_history_handler.cc
index 9a081a6..86b83ff 100644
--- a/chrome/browser/ui/webui/browsing_history_handler.cc
+++ b/chrome/browser/ui/webui/browsing_history_handler.cc
@@ -24,7 +24,6 @@
 #include "chrome/browser/history/history_utils.h"
 #include "chrome/browser/history/web_history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/tab_restore_service_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/chrome_pages.h"
@@ -40,7 +39,6 @@
 #include "components/history/core/browser/web_history_service.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/query_parser/snippet.h"
-#include "components/sessions/core/tab_restore_service.h"
 #include "components/sync_driver/device_info.h"
 #include "components/sync_driver/device_info_tracker.h"
 #include "components/url_formatter/url_formatter.h"
@@ -448,8 +446,6 @@
                                            ServiceAccessType::EXPLICIT_ACCESS);
   history::WebHistoryService* web_history =
       WebHistoryServiceFactory::GetForProfile(profile);
-  sessions::TabRestoreService* tab_service =
-      TabRestoreServiceFactory::GetForProfile(profile);
 
   base::Time now = base::Time::Now();
   std::vector<history::ExpireHistoryArgs> expire_list;
@@ -487,8 +483,8 @@
         continue;
       }
       base::Time visit_time = base::Time::FromJsTime(timestamp);
-      GURL gurl(url);
       if (!expire_args) {
+        GURL gurl(url);
         expire_list.resize(expire_list.size() + 1);
         expire_args = &expire_list.back();
         expire_args->SetTimeRangeForOneDay(visit_time);
@@ -497,9 +493,6 @@
       }
       // The local visit time is treated as a global ID for the visit.
       global_id_directive->add_global_id(visit_time.ToInternalValue());
-
-      // Remove this entry from the recent tabs menu.
-      tab_service->RemoveTabByLastVisit(gurl, visit_time);
     }
 
     // Set the start and end time in microseconds since the Unix epoch.
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index aadd069..ad6a146 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -178,8 +178,6 @@
       'renderer/plugins/chrome_plugin_placeholder.h',
       'renderer/plugins/plugin_preroller.cc',
       'renderer/plugins/plugin_preroller.h',
-      'renderer/plugins/power_saver_info.cc',
-      'renderer/plugins/power_saver_info.h',
     ],
     # For safe_browsing==1 or safe_browsing==2.
     'chrome_renderer_basic_safe_browsing_sources': [
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 1047ae4..688be06 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -989,9 +989,10 @@
       'test/data/webui/polymer_browser_test_base.js',
       'test/data/webui/print_preview.js',
       'test/data/webui/sandboxstatus_browsertest.js',
+      'test/data/webui/settings/advanced_page_browsertest.js',
       'test/data/webui/settings/appearance_browsertest.js',
+      'test/data/webui/settings/basic_page_browsertest.js',
       'test/data/webui/settings/cr_settings_browsertest.js',
-      'test/data/webui/settings/main_page_browsertest.js',
       'test/data/webui/settings/settings_page_browsertest.js',
       'test/data/webui/settings/settings_subpage_browsertest.js',
     ],
@@ -1434,8 +1435,6 @@
       'browser/sync/test/integration/migration_test.cc',
       'browser/sync/test/integration/multiple_client_dictionary_sync_test.cc',
       'browser/sync/test/integration/multiple_client_passwords_sync_test.cc',
-      'browser/sync/test/integration/multiple_client_preferences_sync_test.cc',
-      'browser/sync/test/integration/multiple_client_sessions_sync_test.cc',
       'browser/sync/test/integration/single_client_app_list_sync_test.cc',
       'browser/sync/test/integration/single_client_apps_sync_test.cc',
       'browser/sync/test/integration/single_client_backup_rollback_test.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 40dfb668..d4aca77 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -229,7 +229,6 @@
       'browser/storage/durable_storage_permission_context_unittest.cc',
       'browser/sync/abstract_profile_sync_service_test.cc',
       'browser/sync/abstract_profile_sync_service_test.h',
-      'browser/sync/glue/search_engine_data_type_controller_unittest.cc',
       'browser/sync/profile_sync_service_autofill_unittest.cc',
       'browser/sync/profile_sync_service_bookmark_unittest.cc',
       'browser/sync/profile_sync_service_factory_unittest.cc',
@@ -1480,8 +1479,6 @@
       'browser/font_family_cache_unittest.cc',
       'browser/importer/firefox_profile_lock_unittest.cc',
       'browser/importer/profile_writer_unittest.cc',
-      # Android uses a different invalidator.
-      'browser/invalidation/gcm_invalidation_bridge_unittest.cc',
       'browser/media_galleries/fileapi/native_media_file_util_unittest.cc',
       'browser/media_galleries/gallery_watch_manager_unittest.cc',
       'browser/media_galleries/linux/mtp_device_object_enumerator_unittest.cc',
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 1912a22..9c79ff1 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -83,6 +83,7 @@
     "//components/metrics",
     "//components/metrics:net",
     "//components/nacl/common:process_type",
+    "//components/nacl/common:switches",
     "//components/omnibox/common",
     "//components/policy:policy_component_common",
     "//components/strings",
@@ -190,7 +191,7 @@
   }
 
   if (enable_nacl) {
-    public_deps += [ "//components/nacl:nacl_common" ]
+    public_deps += [ "//components/nacl/common" ]
   }
 
   # Printing.
@@ -333,13 +334,10 @@
     "//base",
     "//base/third_party/dynamic_annotations",
     "//components/bookmarks/common",
+    "//components/nacl/common:switches",
     "//third_party/widevine/cdm:version_h",
   ]
 
-  if (enable_nacl) {
-    deps += [ "//components/nacl:nacl_switches" ]
-  }
-
   if (is_android) {
     # This dependency must only be added for Android.
     #
diff --git a/chrome/installer/linux/rpm/expected_deps_i386 b/chrome/installer/linux/rpm/expected_deps_i386
index dd79bf27..1cad4ee 100644
--- a/chrome/installer/linux/rpm/expected_deps_i386
+++ b/chrome/installer/linux/rpm/expected_deps_i386
@@ -7,8 +7,8 @@
 libc.so.6
 libc.so.6(GLIBC_2.0)
 libc.so.6(GLIBC_2.1)
-libc.so.6(GLIBC_2.1.3)
 libc.so.6(GLIBC_2.11)
+libc.so.6(GLIBC_2.1.3)
 libc.so.6(GLIBC_2.2)
 libc.so.6(GLIBC_2.2.3)
 libc.so.6(GLIBC_2.3)
diff --git a/chrome/installer/linux/rpm/expected_deps_x86_64 b/chrome/installer/linux/rpm/expected_deps_x86_64
index 4e76fa8..188685d 100644
--- a/chrome/installer/linux/rpm/expected_deps_x86_64
+++ b/chrome/installer/linux/rpm/expected_deps_x86_64
@@ -7,9 +7,9 @@
 libc.so.6()(64bit)
 libc.so.6(GLIBC_2.11)(64bit)
 libc.so.6(GLIBC_2.2.5)(64bit)
-libc.so.6(GLIBC_2.3)(64bit)
 libc.so.6(GLIBC_2.3.2)(64bit)
 libc.so.6(GLIBC_2.3.4)(64bit)
+libc.so.6(GLIBC_2.3)(64bit)
 libc.so.6(GLIBC_2.4)(64bit)
 libc.so.6(GLIBC_2.6)(64bit)
 libc.so.6(GLIBC_2.7)(64bit)
diff --git a/chrome/installer/util/prebuild/create_string_rc.py b/chrome/installer/util/prebuild/create_string_rc.py
index 3ea154a..2ff941a0 100755
--- a/chrome/installer/util/prebuild/create_string_rc.py
+++ b/chrome/installer/util/prebuild/create_string_rc.py
@@ -159,14 +159,14 @@
 
     Args:
       translation_ids: a mapping of translation ids to their string
-        identifiers for the translations to be extracted.
+        identifiers list for the translations to be extracted.
     """
     sax.handler.ContentHandler.__init__(self)
     self.lang = None
     self.translations = None
     self.__translation_ids = translation_ids
     self.__element_stack = []
-    self.__string_id = None
+    self.__string_ids = None
     self.__text_scraps = []
     self.__characters_callback = None
 
@@ -198,9 +198,9 @@
     self.lang = lang.replace('-', '_').upper()
 
   def __OnOpenTranslation(self, translation_id):
-    assert self.__string_id is None
-    self.__string_id = self.__translation_ids.get(translation_id)
-    if self.__string_id is not None:
+    assert self.__string_ids is None
+    self.__string_ids = self.__translation_ids.get(translation_id)
+    if self.__string_ids:
       self.__characters_callback = self.__OnTranslationText
 
   def __OnTranslationText(self, containing_element, message_text):
@@ -208,9 +208,11 @@
       self.__text_scraps.append(message_text)
 
   def __OnCloseTranslation(self):
-    if self.__string_id is not None:
-      self.translations[self.__string_id] = ''.join(self.__text_scraps).strip()
-      self.__string_id = None
+    if self.__string_ids:
+      translated_string = ''.join(self.__text_scraps).strip()
+      for string_id in self.__string_ids:
+        self.translations[string_id] = translated_string
+      self.__string_ids = None
       self.__text_scraps = []
       self.__characters_callback = None
 
@@ -292,11 +294,13 @@
                                                        message_text))
 
     # Generate the message ID for each source string to correlate it with its
-    # translations in the .xtb files.
-    translation_ids = {
-      tclib.GenerateMessageId(message_text): string_id
-      for (string_id, message_text) in source_strings.iteritems()
-    }
+    # translations in the .xtb files. Multiple source strings may have the same
+    # message text; hence the message id is mapped to a list of string ids
+    # instead of a single value.
+    translation_ids = {}
+    for (string_id, message_text) in source_strings.iteritems():
+      message_id = tclib.GenerateMessageId(message_text)
+      translation_ids.setdefault(message_id, []).append(string_id);
 
     # Gather the translated strings from the .xtb files. Use the en-US string
     # for any message lacking a translation.
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 5882515..41b08b7 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -79,8 +79,8 @@
 
   if (enable_nacl) {
     deps += [
-      "//components/nacl",
-      "//components/nacl:nacl_renderer",
+      "//components/nacl/loader",
+      "//components/nacl/renderer",
     ]
   }
 
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
index 33a3d269..6b88db0 100644
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -1823,8 +1823,7 @@
 
   SetNotBlacklistedMessage(password_generation_, kFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 2);
 
   SimulateUsernameChange("NewGuy");
   SimulatePasswordChange("NewPassword");
@@ -1844,8 +1843,7 @@
 
   SetNotBlacklistedMessage(password_generation_, kFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 2);
 
   base::string16 password = base::ASCIIToUTF16("NewPass22");
   AutofillMsg_GeneratedPasswordAccepted msg(0, password);
@@ -1884,8 +1882,7 @@
   SetNotBlacklistedMessage(password_generation_,
                            kSignupFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
 
   // Simulate the field being clicked to start typing. This should trigger
   // generation but not password autofill.
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
index 118576e..bb792da 100644
--- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -181,6 +181,16 @@
     "  };"
     "</script>";
 
+const char kPasswordChangeFormHTML[] =
+    "<FORM name = 'ChangeWithUsernameForm' action = 'http://www.bidule.com'> "
+    "  <INPUT type = 'text' id = 'username'/> "
+    "  <INPUT type = 'password' id = 'password'/> "
+    "  <INPUT type = 'password' id = 'newpassword'/> "
+    "  <INPUT type = 'password' id = 'confirmpassword'/> "
+    "  <INPUT type = 'button' id = 'dummy'/> "
+    "  <INPUT type = 'submit' value = 'Login'/> "
+    "</FORM>";
+
 TEST_F(PasswordGenerationAgentTest, DetectionTest) {
   // Don't shown the icon for non account creation forms.
   LoadHTMLWithUserGesture(kSigninFormHTML);
@@ -196,8 +206,7 @@
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", true);
 
   // Hidden fields are not treated differently.
@@ -205,8 +214,7 @@
   SetNotBlacklistedMessage(password_generation_,
                            kHiddenPasswordAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", true);
 
   // This doesn't trigger because the form action is invalid.
@@ -214,8 +222,7 @@
   SetNotBlacklistedMessage(password_generation_,
                            kInvalidActionAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", false);
 }
 
@@ -226,8 +233,7 @@
   LoadHTMLWithUserGesture(html.c_str());
   SetNotBlacklistedMessage(password_generation_, html.c_str());
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
 
   WebDocument document = GetMainFrame()->document();
   WebElement element =
@@ -278,8 +284,7 @@
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
 
   WebDocument document = GetMainFrame()->document();
   WebElement element =
@@ -328,8 +333,7 @@
   // icon.
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", false);
 
   // Receive one not blacklisted message for non account creation form. Don't
@@ -337,8 +341,7 @@
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kSigninFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", false);
 
   // Receive one not blacklisted message for account creation form. Show
@@ -346,8 +349,7 @@
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", true);
 
   // Receive two not blacklisted messages, one is for account creation form and
@@ -356,8 +358,7 @@
   SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kSigninFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", true);
 }
 
@@ -373,8 +374,7 @@
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", true);
 }
 
@@ -384,8 +384,7 @@
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
   ExpectGenerationAvailable("first_password", true);
 
   WebDocument document = GetMainFrame()->document();
@@ -469,8 +468,7 @@
 
   // This needs to come after the DOM has been modified.
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         1);
+                                         GetMainFrame()->document(), 1, 1);
 
   // TODO(gcasto): I'm slightly worried about flakes in this test where
   // didAssociateFormControls() isn't called. If this turns out to be a problem
@@ -488,8 +486,7 @@
 
   // Should trigger on the second form.
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         1);
+                                         GetMainFrame()->document(), 1, 1);
 
   ExpectGenerationAvailable("password", false);
   ExpectGenerationAvailable("first_password", true);
@@ -499,8 +496,7 @@
   LoadHTMLWithUserGesture(kAccountCreationFormHTML);
   SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
 
   // Generation should be enabled.
   ExpectGenerationAvailable("first_password", true);
@@ -521,8 +517,7 @@
   SetNotBlacklistedMessage(password_generation_,
                            kDisabledElementAccountCreationFormHTML);
   SetAccountCreationFormsDetectedMessage(password_generation_,
-                                         GetMainFrame()->document(),
-                                         0);
+                                         GetMainFrame()->document(), 0, 1);
 
   // Focus on the first password field: password generation popup should show
   // up.
@@ -560,4 +555,17 @@
   ExpectGenerationAvailable("first_password", false);
 }
 
+TEST_F(PasswordGenerationAgentTest, ChangePasswordFormDetectionTest) {
+  // Verify that generation is shown on correct field after message receiving.
+  LoadHTMLWithUserGesture(kPasswordChangeFormHTML);
+  SetNotBlacklistedMessage(password_generation_, kPasswordChangeFormHTML);
+  ExpectGenerationAvailable("password", false);
+  ExpectGenerationAvailable("newpassword", false);
+
+  SetAccountCreationFormsDetectedMessage(password_generation_,
+                                         GetMainFrame()->document(), 0, 2);
+  ExpectGenerationAvailable("password", false);
+  ExpectGenerationAvailable("newpassword", true);
+}
+
 }  // namespace autofill
diff --git a/chrome/renderer/autofill/password_generation_test_utils.cc b/chrome/renderer/autofill/password_generation_test_utils.cc
index 339dfe3..79e5e6bc 100644
--- a/chrome/renderer/autofill/password_generation_test_utils.cc
+++ b/chrome/renderer/autofill/password_generation_test_utils.cc
@@ -9,6 +9,7 @@
 #include "components/autofill/content/common/autofill_messages.h"
 #include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/test_password_generation_agent.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebFormElement.h"
@@ -29,7 +30,8 @@
 void SetAccountCreationFormsDetectedMessage(
     TestPasswordGenerationAgent* generation_agent,
     blink::WebDocument document,
-    int form_index) {
+    int form_index,
+    int field_index) {
   blink::WebVector<blink::WebFormElement> web_forms;
   document.forms(web_forms);
 
@@ -38,9 +40,10 @@
       web_forms[form_index], blink::WebFormControlElement(),
       form_util::EXTRACT_NONE, &form_data, nullptr /* FormFieldData */);
 
-  std::vector<autofill::FormData> forms;
-  forms.push_back(form_data);
-  AutofillMsg_AccountCreationFormsDetected msg(0, forms);
+  std::vector<autofill::PasswordFormGenerationData> forms;
+  forms.push_back(autofill::PasswordFormGenerationData{
+      form_data.name, form_data.action, form_data.fields[field_index]});
+  AutofillMsg_FoundFormsEligibleForGeneration msg(0, forms);
   generation_agent->OnMessageReceived(msg);
 }
 
diff --git a/chrome/renderer/autofill/password_generation_test_utils.h b/chrome/renderer/autofill/password_generation_test_utils.h
index e58d8e1..7c454ffe 100644
--- a/chrome/renderer/autofill/password_generation_test_utils.h
+++ b/chrome/renderer/autofill/password_generation_test_utils.h
@@ -19,7 +19,8 @@
                               const char* form_str);
 void SetAccountCreationFormsDetectedMessage(TestPasswordGenerationAgent* agent,
                                             blink::WebDocument document,
-                                            int form_index);
+                                            int form_index,
+                                            int field_index);
 }  // namespace autofill
 
 #endif  // CHROME_RENDERER_AUTOFILL_PASSWORD_GENERATION_TEST_UTILS_H_
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index a2019a0..c596aadd 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -124,7 +124,6 @@
 
 #if defined(ENABLE_PLUGINS)
 #include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
-#include "chrome/renderer/plugins/power_saver_info.h"
 #endif
 
 #if defined(ENABLE_PRINTING)
@@ -261,6 +260,60 @@
 }
 #endif
 
+#if defined(ENABLE_PLUGINS)
+// Presence of the poster param within plugin object tags.
+// These numeric values are used in UMA logs; do not change them.
+enum PosterParamPresence {
+  POSTER_PRESENCE_NO_PARAM_PPS_DISABLED = 0,
+  POSTER_PRESENCE_NO_PARAM_PPS_ENABLED = 1,
+  POSTER_PRESENCE_PARAM_EXISTS_PPS_DISABLED = 2,
+  POSTER_PRESENCE_PARAM_EXISTS_PPS_ENABLED = 3,
+  POSTER_PRESENCE_NUM_ITEMS
+};
+
+const char kPluginPowerSaverPosterParamPresenceHistogram[] =
+    "Plugin.PowerSaver.PosterParamPresence";
+
+void RecordPosterParamPresence(PosterParamPresence presence) {
+  UMA_HISTOGRAM_ENUMERATION(kPluginPowerSaverPosterParamPresenceHistogram,
+                            presence, POSTER_PRESENCE_NUM_ITEMS);
+}
+
+void TrackPosterParamPresence(const blink::WebPluginParams& params,
+                              bool power_saver_enabled) {
+  DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
+
+  for (size_t i = 0; i < params.attributeNames.size(); ++i) {
+    if (params.attributeNames[i].utf8() == "poster") {
+      if (power_saver_enabled)
+        RecordPosterParamPresence(POSTER_PRESENCE_PARAM_EXISTS_PPS_ENABLED);
+      else
+        RecordPosterParamPresence(POSTER_PRESENCE_PARAM_EXISTS_PPS_DISABLED);
+
+      return;
+    }
+  }
+
+  if (power_saver_enabled)
+    RecordPosterParamPresence(POSTER_PRESENCE_NO_PARAM_PPS_ENABLED);
+  else
+    RecordPosterParamPresence(POSTER_PRESENCE_NO_PARAM_PPS_DISABLED);
+}
+
+std::string GetPluginInstancePosterAttribute(
+    const blink::WebPluginParams& params) {
+  DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
+
+  for (size_t i = 0; i < params.attributeNames.size(); ++i) {
+    if (params.attributeNames[i].utf8() == "poster" &&
+        !params.attributeValues[i].isEmpty()) {
+      return params.attributeValues[i].utf8();
+    }
+  }
+  return std::string();
+}
+#endif
+
 #if defined(ENABLE_EXTENSIONS)
 bool IsStandaloneExtensionProcess() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -675,13 +728,14 @@
     }
 #endif
 
-    auto create_blocked_plugin = [&render_frame, &frame, &params, &info,
-                                  &identifier, &group_name](
-        int template_id, const base::string16& message) {
-      return ChromePluginPlaceholder::CreateBlockedPlugin(
-          render_frame, frame, params, info, identifier, group_name,
-          template_id, message, PowerSaverInfo());
-    };
+    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+    auto create_blocked_plugin =
+        [&render_frame, &frame, &params, &info, &identifier, &group_name](
+            int template_id, const base::string16& message) {
+          return ChromePluginPlaceholder::CreateBlockedPlugin(
+              render_frame, frame, params, info, identifier, group_name,
+              template_id, message, PlaceholderPosterInfo());
+        };
     switch (status) {
       case ChromeViewHostMsg_GetPluginInfo_Status::kNotFound: {
         NOTREACHED();
@@ -700,8 +754,7 @@
           bool is_nacl_unrestricted = false;
           if (is_nacl_mime_type) {
             is_nacl_unrestricted =
-                base::CommandLine::ForCurrentProcess()->HasSwitch(
-                    switches::kEnableNaCl);
+                command_line->HasSwitch(switches::kEnableNaCl);
           } else if (is_pnacl_mime_type) {
             is_nacl_unrestricted = true;
           }
@@ -757,28 +810,54 @@
         bool is_prerendering =
             prerender::PrerenderHelper::IsPrerendering(render_frame);
 
+        bool is_flash = info.name == ASCIIToUTF16(content::kFlashPluginName);
+
+        std::string override_for_testing = command_line->GetSwitchValueASCII(
+            switches::kOverridePluginPowerSaverForTesting);
+
+        // This feature has only been tested throughly with Flash thus far.
+        // It is also enabled for the Power Saver test plugin for browser tests.
+        bool can_throttle_plugin_type =
+            is_flash || override_for_testing == "ignore-list";
+
         bool power_saver_setting_on =
             status ==
             ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent;
-        PowerSaverInfo power_saver_info =
-            PowerSaverInfo::Get(render_frame, power_saver_setting_on, params,
-                                info, frame->document().url());
-        if (power_saver_info.blocked_for_background_tab || is_prerendering ||
-            !power_saver_info.poster_attribute.empty()) {
+
+        bool power_saver_enabled =
+            override_for_testing == "always" ||
+            (power_saver_setting_on && can_throttle_plugin_type);
+        bool blocked_for_background_tab =
+            power_saver_enabled && render_frame->IsHidden();
+
+        PlaceholderPosterInfo poster_info;
+        if (power_saver_enabled) {
+          poster_info.poster_attribute =
+              GetPluginInstancePosterAttribute(params);
+          poster_info.base_url = frame->document().url();
+        }
+
+        if (is_flash)
+          TrackPosterParamPresence(params, power_saver_enabled);
+
+        if (blocked_for_background_tab || is_prerendering ||
+            !poster_info.poster_attribute.empty()) {
           placeholder = ChromePluginPlaceholder::CreateBlockedPlugin(
               render_frame, frame, params, info, identifier, group_name,
-              power_saver_info.poster_attribute.empty()
-                  ? IDR_BLOCKED_PLUGIN_HTML
-                  : IDR_PLUGIN_POSTER_HTML,
+              poster_info.poster_attribute.empty() ? IDR_BLOCKED_PLUGIN_HTML
+                                                   : IDR_PLUGIN_POSTER_HTML,
               l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name),
-              power_saver_info);
+              poster_info);
+          placeholder->set_blocked_for_background_tab(
+              blocked_for_background_tab);
           placeholder->set_blocked_for_prerendering(is_prerendering);
+          placeholder->set_power_saver_enabled(power_saver_enabled);
           placeholder->AllowLoading();
           break;
         }
 
         scoped_ptr<content::PluginInstanceThrottler> throttler;
-        if (power_saver_info.power_saver_enabled) {
+        if (power_saver_enabled) {
           throttler = PluginInstanceThrottler::Create();
           // PluginPreroller manages its own lifetime.
           new PluginPreroller(
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
index 61b7a70..56565bdd 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
@@ -110,7 +110,7 @@
     const base::string16& name,
     int template_id,
     const base::string16& message,
-    const PowerSaverInfo& power_saver_info) {
+    const PlaceholderPosterInfo& poster_info) {
   base::DictionaryValue values;
   values.SetString("message", message);
   values.SetString("name", name);
@@ -121,17 +121,16 @@
                        ? "document"
                        : "embedded");
 
-  if (!power_saver_info.poster_attribute.empty()) {
-    values.SetString("poster", power_saver_info.poster_attribute);
-    values.SetString("baseurl", power_saver_info.base_url.spec());
+  if (!poster_info.poster_attribute.empty()) {
+    values.SetString("poster", poster_info.poster_attribute);
+    values.SetString("baseurl", poster_info.base_url.spec());
 
-    if (!power_saver_info.custom_poster_size.IsEmpty()) {
+    if (!poster_info.custom_poster_size.IsEmpty()) {
       float zoom_factor =
           blink::WebView::zoomLevelToZoomFactor(frame->view()->zoomLevel());
-      int width =
-          roundf(power_saver_info.custom_poster_size.width() / zoom_factor);
+      int width = roundf(poster_info.custom_poster_size.width() / zoom_factor);
       int height =
-          roundf(power_saver_info.custom_poster_size.height() / zoom_factor);
+          roundf(poster_info.custom_poster_size.height() / zoom_factor);
       values.SetString("visibleWidth", base::IntToString(width) + "px");
       values.SetString("visibleHeight", base::IntToString(height) + "px");
     }
@@ -148,15 +147,10 @@
   ChromePluginPlaceholder* blocked_plugin = new ChromePluginPlaceholder(
       render_frame, frame, params, html_data, name);
 
-  if (!power_saver_info.poster_attribute.empty())
+  if (!poster_info.poster_attribute.empty())
     blocked_plugin->BlockForPowerSaverPoster();
   blocked_plugin->SetPluginInfo(info);
   blocked_plugin->SetIdentifier(identifier);
-
-  blocked_plugin->set_power_saver_enabled(power_saver_info.power_saver_enabled);
-  blocked_plugin->set_blocked_for_background_tab(
-      power_saver_info.blocked_for_background_tab);
-
   return blocked_plugin;
 }
 
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h
index 0236320b..85d49b7f 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.h
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.h
@@ -5,13 +5,29 @@
 #ifndef CHROME_RENDERER_PLUGINS_CHROME_PLUGIN_PLACEHOLDER_H_
 #define CHROME_RENDERER_PLUGINS_CHROME_PLUGIN_PLACEHOLDER_H_
 
-#include "chrome/renderer/plugins/power_saver_info.h"
 #include "components/plugins/renderer/loadable_plugin_placeholder.h"
 #include "content/public/renderer/context_menu_client.h"
 #include "content/public/renderer/render_process_observer.h"
 
+namespace gfx {
+class Size;
+}
+
 enum class ChromeViewHostMsg_GetPluginInfo_Status;
 
+// This contains information specifying the poster image of plugin placeholders.
+// The default constructor specifies no poster image.
+struct PlaceholderPosterInfo {
+  // The poster image specified in image 'srcset' attribute format.
+  std::string poster_attribute;
+
+  // Used to resolve relative paths in |poster_attribute|.
+  GURL base_url;
+
+  // Specify this to provide partially obscured plugins a centered poster image.
+  gfx::Size custom_poster_size;
+};
+
 class ChromePluginPlaceholder final
     : public plugins::LoadablePluginPlaceholder,
       public content::RenderProcessObserver,
@@ -29,7 +45,7 @@
       const base::string16& name,
       int resource_id,
       const base::string16& message,
-      const PowerSaverInfo& power_saver_info);
+      const PlaceholderPosterInfo& poster_info);
 
   // Creates a new WebViewPlugin with a MissingPlugin as a delegate.
   static ChromePluginPlaceholder* CreateLoadableMissingPlugin(
diff --git a/chrome/renderer/plugins/plugin_preroller.cc b/chrome/renderer/plugins/plugin_preroller.cc
index 7f7cdfd7..b35d3e5 100644
--- a/chrome/renderer/plugins/plugin_preroller.cc
+++ b/chrome/renderer/plugins/plugin_preroller.cc
@@ -7,7 +7,6 @@
 #include "base/base64.h"
 #include "chrome/grit/renderer_resources.h"
 #include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
-#include "chrome/renderer/plugins/power_saver_info.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
 #include "third_party/WebKit/public/web/WebElement.h"
 #include "third_party/WebKit/public/web/WebPlugin.h"
@@ -59,16 +58,16 @@
   if (!throttler_->IsThrottled())
     return;
 
-  PowerSaverInfo power_saver_info;
-  power_saver_info.power_saver_enabled = true;
-  power_saver_info.poster_attribute = keyframe_data_url_.spec();
-  power_saver_info.custom_poster_size = throttler_->GetSize();
+  PlaceholderPosterInfo poster_info;
+  poster_info.poster_attribute = keyframe_data_url_.spec();
+  poster_info.custom_poster_size = throttler_->GetSize();
 
   ChromePluginPlaceholder* placeholder =
       ChromePluginPlaceholder::CreateBlockedPlugin(
           render_frame(), frame_, params_, info_, identifier_, name_,
-          IDR_PLUGIN_POSTER_HTML, message_, power_saver_info);
+          IDR_PLUGIN_POSTER_HTML, message_, poster_info);
   placeholder->SetPremadePlugin(throttler_);
+  placeholder->set_power_saver_enabled(true);
   placeholder->AllowLoading();
 
   blink::WebPluginContainer* container =
diff --git a/chrome/renderer/plugins/power_saver_info.cc b/chrome/renderer/plugins/power_saver_info.cc
deleted file mode 100644
index 600a29c1..0000000
--- a/chrome/renderer/plugins/power_saver_info.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2015 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/metrics/histogram_macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/renderer/plugins/power_saver_info.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/webplugininfo.h"
-#include "content/public/renderer/render_frame.h"
-#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebPluginParams.h"
-#include "url/origin.h"
-
-namespace {
-
-// Presence of the poster param within plugin object tags.
-// These numeric values are used in UMA logs; do not change them.
-enum PosterParamPresence {
-  POSTER_PRESENCE_NO_PARAM_PPS_DISABLED = 0,
-  POSTER_PRESENCE_NO_PARAM_PPS_ENABLED = 1,
-  POSTER_PRESENCE_PARAM_EXISTS_PPS_DISABLED = 2,
-  POSTER_PRESENCE_PARAM_EXISTS_PPS_ENABLED = 3,
-  POSTER_PRESENCE_NUM_ITEMS
-};
-
-const char kPluginPowerSaverPosterParamPresenceHistogram[] =
-    "Plugin.PowerSaver.PosterParamPresence";
-
-void RecordPosterParamPresence(PosterParamPresence presence) {
-  UMA_HISTOGRAM_ENUMERATION(kPluginPowerSaverPosterParamPresenceHistogram,
-                            presence, POSTER_PRESENCE_NUM_ITEMS);
-}
-
-void TrackPosterParamPresence(const blink::WebPluginParams& params,
-                              bool power_saver_enabled) {
-  DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
-
-  for (size_t i = 0; i < params.attributeNames.size(); ++i) {
-    if (params.attributeNames[i].utf8() == "poster") {
-      RecordPosterParamPresence(
-          power_saver_enabled ? POSTER_PRESENCE_PARAM_EXISTS_PPS_ENABLED
-                              : POSTER_PRESENCE_PARAM_EXISTS_PPS_DISABLED);
-      return;
-    }
-  }
-
-  RecordPosterParamPresence(power_saver_enabled
-                                ? POSTER_PRESENCE_NO_PARAM_PPS_ENABLED
-                                : POSTER_PRESENCE_NO_PARAM_PPS_DISABLED);
-}
-
-std::string GetPluginInstancePosterAttribute(
-    const blink::WebPluginParams& params) {
-  DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
-
-  for (size_t i = 0; i < params.attributeNames.size(); ++i) {
-    if (params.attributeNames[i].utf8() == "poster" &&
-        !params.attributeValues[i].isEmpty()) {
-      return params.attributeValues[i].utf8();
-    }
-  }
-  return std::string();
-}
-
-}  // namespace
-
-PowerSaverInfo::PowerSaverInfo()
-    : power_saver_enabled(false), blocked_for_background_tab(false) {}
-
-PowerSaverInfo PowerSaverInfo::Get(content::RenderFrame* render_frame,
-                                   bool power_saver_setting_on,
-                                   const blink::WebPluginParams& params,
-                                   const content::WebPluginInfo& plugin_info,
-                                   const GURL& document_url) {
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  std::string override_for_testing = command_line->GetSwitchValueASCII(
-      switches::kOverridePluginPowerSaverForTesting);
-
-  // This feature has only been tested thoroughly with Flash thus far.
-  // It is also enabled for the Power Saver test plugin for browser tests.
-  bool is_flash =
-      plugin_info.name == base::ASCIIToUTF16(content::kFlashPluginName);
-  bool can_throttle_plugin_type =
-      is_flash || override_for_testing == "ignore-list";
-
-  PowerSaverInfo info;
-  info.power_saver_enabled =
-      override_for_testing == "always" ||
-      (power_saver_setting_on && can_throttle_plugin_type);
-
-  if (info.power_saver_enabled) {
-    // Even if we disable PPS in the next block because content is same-origin,
-    // it should still be eligible for background tab deferral if PPS is on.
-    info.blocked_for_background_tab = render_frame->IsHidden();
-
-    auto status = render_frame->GetPeripheralContentStatus(
-        render_frame->GetWebFrame()->top()->securityOrigin(),
-        url::Origin(params.url), gfx::Size());
-
-    // Early-exit from the whole Power Saver system if the content is
-    // same-origin or whitelisted-origin. We ignore the other possibilities,
-    // because we don't know the unobscured size of the plugin content yet.
-    //
-    // Once the plugin is loaded, the peripheral content status is re-tested
-    // with the actual unobscured plugin size.
-    if (status == content::RenderFrame::CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN ||
-        status == content::RenderFrame::
-                      CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED) {
-      info.power_saver_enabled = false;
-    } else {
-      info.poster_attribute = GetPluginInstancePosterAttribute(params);
-      info.base_url = document_url;
-    }
-  }
-
-  if (is_flash)
-    TrackPosterParamPresence(params, info.power_saver_enabled);
-
-  return info;
-}
diff --git a/chrome/renderer/plugins/power_saver_info.h b/chrome/renderer/plugins/power_saver_info.h
deleted file mode 100644
index 7da43e69..0000000
--- a/chrome/renderer/plugins/power_saver_info.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_RENDERER_PLUGINS_POWER_SAVER_INFO_H_
-#define CHROME_RENDERER_PLUGINS_POWER_SAVER_INFO_H_
-
-#include <string>
-
-#include "ui/gfx/geometry/size.h"
-#include "url/gurl.h"
-
-namespace blink {
-struct WebPluginParams;
-}
-
-namespace content {
-class RenderFrame;
-struct WebPluginInfo;
-}
-
-// This contains information specifying the plugin's Power Saver behavior.
-// The default constructor has Plugin Power Saver disabled.
-struct PowerSaverInfo {
-  PowerSaverInfo();
-
-  // Determines the PowerSaverInfo using the peripheral content heuristic.
-  static PowerSaverInfo Get(content::RenderFrame* render_frame,
-                            bool power_saver_setting_on,
-                            const blink::WebPluginParams& params,
-                            const content::WebPluginInfo& plugin_info,
-                            const GURL& document_url);
-
-  // Whether power saver should be enabled.
-  bool power_saver_enabled;
-
-  // Whether the plugin should be deferred because it is in a background tab.
-  bool blocked_for_background_tab;
-
-  // The poster image specified in image 'srcset' attribute format.
-  std::string poster_attribute;
-
-  // Used to resolve relative paths in |poster_attribute|.
-  GURL base_url;
-
-  // Specify this to provide partially obscured plugins a centered poster image.
-  gfx::Size custom_poster_size;
-};
-
-#endif  // CHROME_RENDERER_PLUGINS_POWER_SAVER_INFO_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8168d92b..f393d0e 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -447,8 +447,8 @@
 
       if (enable_nacl) {
         data_deps += [
-          "//components/nacl:nacl_helper",
-          "//components/nacl:helper_nonsfi",
+          "//components/nacl/loader:nacl_helper",
+          "//components/nacl/loader:helper_nonsfi",
         ]
       }
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
index 006b0d5..16a6b3a2 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
@@ -352,8 +352,8 @@
      * Load a url in a new tab. The {@link Tab} will pretend to be created from a link.
      * @param url The url of the page to load.
      */
-    public void loadUrlInNewTab(final String url) throws InterruptedException {
-        loadUrlInNewTab(url, false);
+    public Tab loadUrlInNewTab(final String url) throws InterruptedException {
+        return loadUrlInNewTab(url, false);
     }
 
     /**
@@ -361,7 +361,7 @@
      * @param url The url of the page to load.
      * @param incognito Whether the new tab should be incognito.
      */
-    public void loadUrlInNewTab(final String url, final boolean incognito)
+    public Tab loadUrlInNewTab(final String url, final boolean incognito)
             throws InterruptedException {
         Tab tab = null;
         if (FeatureUtilities.isDocumentMode(getInstrumentation().getContext())) {
@@ -405,6 +405,7 @@
         }
         ChromeTabUtils.waitForTabPageLoaded(tab, url);
         getInstrumentation().waitForIdleSync();
+        return tab;
     }
 
     /**
diff --git a/chrome/test/data/pdf/navigator_test.js b/chrome/test/data/pdf/navigator_test.js
index b9624ed..6d032c2 100644
--- a/chrome/test/data/pdf/navigator_test.js
+++ b/chrome/test/data/pdf/navigator_test.js
@@ -245,6 +245,15 @@
         navigateInCurrentTabCallback,
         navigateInNewTabCallback);
 
+    // Regression test for https://crbug.com/569040
+    doNavigationUrlTestInCurrentTabAndNewTab(
+        navigator,
+        'http://something.else/foo#page=5',
+        'http://something.else/foo#page=5',
+        mockCallback,
+        navigateInCurrentTabCallback,
+        navigateInNewTabCallback);
+
     chrome.test.succeed();
   },
   /**
diff --git a/chrome/test/data/webui/settings/main_page_browsertest.js b/chrome/test/data/webui/settings/advanced_page_browsertest.js
similarity index 66%
rename from chrome/test/data/webui/settings/main_page_browsertest.js
rename to chrome/test/data/webui/settings/advanced_page_browsertest.js
index 5035b445..1cead7f 100644
--- a/chrome/test/data/webui/settings/main_page_browsertest.js
+++ b/chrome/test/data/webui/settings/advanced_page_browsertest.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/** @fileoverview Suite of tests for the Settings main page. */
+/** @fileoverview Suite of tests for the Settings advanced page. */
 
 GEN_INCLUDE(['settings_page_browsertest.js']);
 
@@ -10,22 +10,25 @@
  * @constructor
  * @extends {SettingsPageBrowserTest}
 */
-function SettingsMainPageBrowserTest() {}
+function SettingsAdvancedPageBrowserTest() {}
 
-SettingsMainPageBrowserTest.prototype = {
-  __proto__: SettingsPageBrowserTest.prototype
+SettingsAdvancedPageBrowserTest.prototype = {
+  __proto__: SettingsPageBrowserTest.prototype,
+
+  /** @override */
+  browsePreload: 'chrome://md-settings/advanced',
 };
 
 // Times out on debug builders and may time out on memory bots because
 // the Settings page can take several seconds to load in a Release build
 // and several times that in a Debug build. See https://crbug.com/558434.
 GEN('#if defined(MEMORY_SANITIZER) || !defined(NDEBUG)');
-GEN('#define MAYBE_Main DISABLED_Main');
+GEN('#define MAYBE_Load DISABLED_Main');
 GEN('#else');
-GEN('#define MAYBE_Main Main');
+GEN('#define MAYBE_Load Main');
 GEN('#endif');
 
-TEST_F('SettingsMainPageBrowserTest', 'MAYBE_Main', function() {
+TEST_F('SettingsAdvancedPageBrowserTest', 'MAYBE_Load', function() {
   // Assign |self| to |this| instead of binding since 'this' in suite()
   // and test() will be a Mocha 'Suite' or 'Test' instance.
   var self = this;
@@ -36,19 +39,6 @@
       // This will fail if there are any asserts or errors in the Settings page.
     });
 
-    test('basic pages', function() {
-      var page = self.getPage('basic');
-      expectTrue(!!self.getSection(page, 'appearance'));
-      expectTrue(!!self.getSection(page, 'onStartup'));
-      expectTrue(!!self.getSection(page, 'people'));
-      expectTrue(!!self.getSection(page, 'search'));
-      if (!cr.isChromeOS) {
-        expectTrue(!!self.getSection(page, 'defaultBrowser'));
-      } else {
-        expectTrue(!!self.getSection(page, 'internet'));
-      }
-    });
-
     test('advanced pages', function() {
       var page = self.getPage('advanced');
       expectTrue(!!self.getSection(page, 'location'));
@@ -57,7 +47,6 @@
       expectTrue(!!self.getSection(page, 'languages'));
       expectTrue(!!self.getSection(page, 'downloads'));
       expectTrue(!!self.getSection(page, 'reset'));
-
       if (cr.isChromeOS) {
         expectTrue(!!self.getSection(page, 'dateTime'));
         expectTrue(!!self.getSection(page, 'bluetooth'));
diff --git a/chrome/test/data/webui/settings/appearance_browsertest.js b/chrome/test/data/webui/settings/appearance_browsertest.js
index 18b1fd9..5fbbaa4a 100644
--- a/chrome/test/data/webui/settings/appearance_browsertest.js
+++ b/chrome/test/data/webui/settings/appearance_browsertest.js
@@ -16,6 +16,11 @@
 AppearanceSettingsBrowserTest.prototype = {
   __proto__: SettingsPageBrowserTest.prototype,
 
+  /** @override */
+  extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([
+    'fake_settings_private.js',
+  ]),
+
   /** @return {string} */
   appearancePage: function(selector) {
     var section = this.getSection(this.getPage('basic'), 'appearance');
@@ -29,6 +34,11 @@
 };
 
 TEST_F('AppearanceSettingsBrowserTest', 'uiTests', function() {
+  /**
+   * The prefs API that will get a fake implementation.
+   * @type {!SettingsPrivate}
+   */
+  var settingsPrefs;
   var self = this;
 
   var fontSize = function() {
@@ -37,22 +47,31 @@
   };
 
   suite('AppearanceHandler', function() {
-    test('font settings', function(done) {
-      chrome.settingsPrivate.setPref(
-          'webkit.webprefs.default_font_size', 16, '', function(result) {
-        assertTrue(result);
-        assertEquals('Medium', fontSize());
-        chrome.settingsPrivate.setPref(
-            'webkit.webprefs.default_font_size', 20, '', function(result) {
-          assertTrue(result);
-          chrome.settingsPrivate.getPref(
-                'webkit.webprefs.default_font_size', function(pref) {
-              assertEquals(pref.value, 20);
-              assertEquals('Large', fontSize());
-              done();
-          });
-        });
-      });
+    var fakePrefs = [{
+      key: 'webkit.webprefs.default_font_size',
+      type: chrome.settingsPrivate.PrefType.NUMBER,
+      value: 1234,
+    }];
+
+    suiteSetup(function() {
+      settingsPrefs = document.querySelector(
+          'cr-settings').$$('settings-prefs');
+      assertTrue(!!settingsPrefs);
+      CrSettingsPrefs.resetForTesting();
+      settingsPrefs.resetForTesting();
+      var fakeApi = new settings.FakeSettingsPrivate(fakePrefs);
+      settingsPrefs.initializeForTesting(fakeApi);
+      return CrSettingsPrefs.initialized;
+    });
+
+    test('very small font', function() {
+      settingsPrefs.set('prefs.webkit.webprefs.default_font_size.value', 9);
+      assertEquals('Very small', fontSize());
+    });
+
+    test('large font', function() {
+      settingsPrefs.set('prefs.webkit.webprefs.default_font_size.value', 20);
+      assertEquals('Large', fontSize());
     });
 
     /**
@@ -60,18 +79,10 @@
      * then the menu label will be 'Custom' (rather than 'Medium', 'Large',
      * etc.).
      */
-    test('font size custom', function(done) {
-      chrome.settingsPrivate.setPref(
-          'webkit.webprefs.default_font_size', 19, '', function(result) {
-        assertTrue(result);
-        assertEquals('Custom', fontSize());
-        done();
-      });
-    });
-
-    test('home button', function() {
-      var homeButton = self.appearancePage('#showHomeButton');
-      assertEquals('false', homeButton.getAttribute('aria-pressed'));
+    test('custom font size', function() {
+      settingsPrefs.set(
+          'prefs.webkit.webprefs.default_font_size', 19);
+      assertEquals('Custom', fontSize());
     });
   });
   mocha.run();
diff --git a/chrome/test/data/webui/settings/main_page_browsertest.js b/chrome/test/data/webui/settings/basic_page_browsertest.js
similarity index 62%
copy from chrome/test/data/webui/settings/main_page_browsertest.js
copy to chrome/test/data/webui/settings/basic_page_browsertest.js
index 5035b445..f36bb92 100644
--- a/chrome/test/data/webui/settings/main_page_browsertest.js
+++ b/chrome/test/data/webui/settings/basic_page_browsertest.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/** @fileoverview Suite of tests for the Settings main page. */
+/** @fileoverview Suite of tests for the Settings basic page. */
 
 GEN_INCLUDE(['settings_page_browsertest.js']);
 
@@ -10,9 +10,9 @@
  * @constructor
  * @extends {SettingsPageBrowserTest}
 */
-function SettingsMainPageBrowserTest() {}
+function SettingsBasicPageBrowserTest() {}
 
-SettingsMainPageBrowserTest.prototype = {
+SettingsBasicPageBrowserTest.prototype = {
   __proto__: SettingsPageBrowserTest.prototype
 };
 
@@ -20,12 +20,12 @@
 // the Settings page can take several seconds to load in a Release build
 // and several times that in a Debug build. See https://crbug.com/558434.
 GEN('#if defined(MEMORY_SANITIZER) || !defined(NDEBUG)');
-GEN('#define MAYBE_Main DISABLED_Main');
+GEN('#define MAYBE_Load DISABLED_Main');
 GEN('#else');
-GEN('#define MAYBE_Main Main');
+GEN('#define MAYBE_Load Main');
 GEN('#endif');
 
-TEST_F('SettingsMainPageBrowserTest', 'MAYBE_Main', function() {
+TEST_F('SettingsBasicPageBrowserTest', 'MAYBE_Load', function() {
   // Assign |self| to |this| instead of binding since 'this' in suite()
   // and test() will be a Mocha 'Suite' or 'Test' instance.
   var self = this;
@@ -48,22 +48,6 @@
         expectTrue(!!self.getSection(page, 'internet'));
       }
     });
-
-    test('advanced pages', function() {
-      var page = self.getPage('advanced');
-      expectTrue(!!self.getSection(page, 'location'));
-      expectTrue(!!self.getSection(page, 'privacy'));
-      expectTrue(!!self.getSection(page, 'passwordsAndForms'));
-      expectTrue(!!self.getSection(page, 'languages'));
-      expectTrue(!!self.getSection(page, 'downloads'));
-      expectTrue(!!self.getSection(page, 'reset'));
-
-      if (cr.isChromeOS) {
-        expectTrue(!!self.getSection(page, 'dateTime'));
-        expectTrue(!!self.getSection(page, 'bluetooth'));
-        expectTrue(!!self.getSection(page, 'a11y'));
-      }
-    });
   });
 
   // Run all registered tests.
diff --git a/chrome/test/data/webui/settings/settings_subpage_browsertest.js b/chrome/test/data/webui/settings/settings_subpage_browsertest.js
index ca4a315..ab9ccabc 100644
--- a/chrome/test/data/webui/settings/settings_subpage_browsertest.js
+++ b/chrome/test/data/webui/settings/settings_subpage_browsertest.js
@@ -12,33 +12,21 @@
 /**
  * @constructor
  * @extends {SettingsPageBrowserTest}
+ *
+ * @param {string} pageId 'basic' or 'advanced'.
+ * @param {!Array<string>} subPages
 */
-function SettingsSubPageBrowserTest() {}
+function SettingsSubPageBrowserTest(pageId, subPages) {
+  /** @type {string} */
+  this.pageId = pageId;
+
+  /** @type {!Array<string>} */
+  this.subPages = subPages;
+}
 
 SettingsSubPageBrowserTest.prototype = {
   __proto__: SettingsPageBrowserTest.prototype,
 
-  basicPages_: [
-    'people',
-    'internet',
-    'appearance',
-    'onStartup',
-    'search',
-    'defaultBrowser'
-  ],
-
-  advancedPages_: [
-    'dateTime',
-    'location',
-    'privacy',
-    'bluetooth',
-    'passwordsAndForms',
-    'languages',
-    'downloads',
-    'reset',
-    'a11y'
-  ],
-
   /** @override */
   preLoad: function() {
     SettingsPageBrowserTest.prototype.preLoad.call(this);
@@ -53,22 +41,19 @@
     SettingsPageBrowserTest.prototype.setUp.call(this);
     // Explicitly hide all of the pages (not strictly required but is more
     // clear than relying on undefined -> hidden).
-    this.hideSubPages_('basic', this.basicPages_ );
-    this.hideSubPages_('advanced', this.advancedPages_ );
+    this.hideSubPages_();
   },
 
   /*
-   * This will hide all subpages in |subpages|. Note: any existing subpages
-   * not listed in |subpages| will be shown.
-   * @param {string} pageId
-   * @param {!Array<string>} subpages
+   * This will hide all subpages in |this.subPages|. Note: any existing subpages
+   * not listed in |this.subPages| will be shown.
    */
-  hideSubPages_: function(pageId, subpages) {
-    var page = this.getPage(pageId);
+  hideSubPages_: function() {
+    var page = this.getPage(this.pageId);
     var visibility = {};
-    for (var p of subpages) {
-      visibility[p] = false;
-    }
+    this.subPages.forEach(function(subPage) {
+      visibility[subPage] = false;
+    });
     assertEquals(0, Object.keys(page.pageVisibility).length);
     page.pageVisibility = visibility;
     // Ensure all pages are hidden.
@@ -76,54 +61,96 @@
     assertTrue(!!sections);
     assertEquals(0, sections.length);
   },
-};
 
-TEST_F('SettingsSubPageBrowserTest', 'SubPages', function() {
-  // Assign |self| to |this| instead of binding since 'this' in suite()
-  // and test() will be a Mocha 'Suite' or 'Test' instance.
-  var self = this;
-
-  // Ensures the subpage is initially hidden, then sets it to visible and
-  // times the result, outputting a (rough) approximation of load time for the
-  // subpage.
-  var testPage = function(page, subpage) {
+  /**
+   * Ensures the subpage is initially hidden, then sets it to visible and
+   * times the result, outputting a (rough) approximation of load time for the
+   * subpage.
+   * @param {Node} page
+   * @param {string} subpage
+   */
+  testPage: function(page, subPage) {
     Polymer.dom.flush();
-    expectFalse(!!self.getSection(page, subpage), subpage);
+    expectFalse(!!this.getSection(page, subPage));
     var startTime = window.performance.now();
-    page.set('pageVisibility.' + subpage, true);
+    page.set('pageVisibility.' + subPage, true);
     Polymer.dom.flush();
     var dtime = window.performance.now() - startTime;
-    console.log('Page: ' + subpage + ' Load time: ' + dtime.toFixed(0) + ' ms');
-    expectTrue(!!self.getSection(page, subpage), subpage);
-    // Hide the page so that it doesn't interfere with other subpages.
-    page.set('pageVisibility.' + subpage, false);
+    console.log('Page: ' + subPage + ' Load time: ' + dtime.toFixed(0) + ' ms');
+    expectTrue(!!this.getSection(page, subPage));
+    // Hide the page so that it doesn't interfere with other subPages.
+    page.set('pageVisibility.' + subPage, false);
     Polymer.dom.flush();
-  };
+  },
 
-  var includePage = function(id) {
+  testSubPages: function() {
+    var page = this.getPage(this.pageId);
+    this.subPages.forEach(function(subPage) {
+      if (this.includePage(subPage))
+        test(subPage, this.testPage.bind(this, page, subPage));
+    }.bind(this));
+  },
+
+  /**
+   * @param {string} id
+   * @return {boolean}
+   */
+  includePage: function(id) {
     if (cr.isChromeOS)
-      return id != 'defaultBrowser';
-    return id != 'internet' && id != 'dateTime' && id != 'bluetooth' &&
-           id != 'a11y';
-  };
+      return id != 'people' && id != 'defaultBrowser';
+    return id != 'internet' && id != 'users' && id != 'dateTime' &&
+           id != 'bluetooth' && id != 'a11y';
+  },
+};
 
-  // Register mocha tests.
-  suite('Basic', function() {
-    var page = self.getPage('basic');
-    for (var subPage of self.basicPages_) {
-      if (includePage(subPage))
-        test(subPage, testPage.bind(self, page, subPage));
-    }
-  });
+/** @constructor @extends {SettingsSubPageBrowserTest} */
+function SettingsBasicSubPageBrowserTest() {
+  var subPages = [
+    'people',
+    'internet',
+    'appearance',
+    'onStartup',
+    'search',
+    'defaultBrowser'
+  ];
 
-  suite('Advanced', function() {
-    var page = self.getPage('advanced');
-    for (var subPage of self.advancedPages_) {
-      if (includePage(subPage))
-        test(subPage, testPage.bind(self, page, subPage));
-    }
-  });
+  SettingsSubPageBrowserTest.call(this, 'basic', subPages);
+}
 
-  // Run all registered tests.
+SettingsBasicSubPageBrowserTest.prototype = {
+  __proto__: SettingsSubPageBrowserTest.prototype,
+};
+
+TEST_F('SettingsBasicSubPageBrowserTest', 'SubPages', function() {
+  suite('Basic', this.testSubPages.bind(this));
+  mocha.run();
+});
+
+/** @constructor @extends {SettingsSubPageBrowserTest} */
+function SettingsAdvancedSubPageBrowserTest() {
+  var subPages = [
+    'dateTime',
+    'location',
+    'privacy',
+    'bluetooth',
+    'passwordsAndForms',
+    'languages',
+    'downloads',
+    'reset',
+    'a11y'
+  ];
+
+  SettingsSubPageBrowserTest.call(this, 'advanced', subPages);
+};
+
+SettingsAdvancedSubPageBrowserTest.prototype = {
+  __proto__: SettingsSubPageBrowserTest.prototype,
+
+  /** @override */
+  browsePreload: 'chrome://md-settings/advanced',
+};
+
+TEST_F('SettingsAdvancedSubPageBrowserTest', 'SubPages', function() {
+  suite('Advanced', this.testSubPages.bind(this));
   mocha.run();
 });
diff --git a/chromecast/browser/cast_content_window.cc b/chromecast/browser/cast_content_window.cc
index 1cdb8cf..804ed51 100644
--- a/chromecast/browser/cast_content_window.cc
+++ b/chromecast/browser/cast_content_window.cc
@@ -78,7 +78,7 @@
     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, cast_screen);
   if (cast_screen->GetPrimaryDisplay().size() != initial_size)
     cast_screen->UpdateDisplaySize(initial_size);
-  media::VideoPlaneController::GetInstance()->OnGraphicsPlaneResolutionChanged(
+  media::VideoPlaneController::GetInstance()->SetGraphicsPlaneResolution(
       Size(initial_size.width(), initial_size.height()));
 
   CHECK(aura::Env::GetInstance());
diff --git a/chromecast/media/base/video_plane_controller.cc b/chromecast/media/base/video_plane_controller.cc
index 8bae226..8f07839f 100644
--- a/chromecast/media/base/video_plane_controller.cc
+++ b/chromecast/media/base/video_plane_controller.cc
@@ -16,6 +16,27 @@
 namespace chromecast {
 namespace media {
 
+namespace {
+
+bool RectFEqual(const RectF& r1, const RectF& r2) {
+  return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width &&
+         r1.height == r2.height;
+}
+
+bool SizeEqual(const Size& s1, const Size& s2) {
+  return s1.width == s2.width && s1.height == s2.height;
+}
+
+bool DisplayRectFValid(const RectF& r) {
+  return r.width >= 0 && r.height >= 0;
+}
+
+bool ResolutionSizeValid(const Size& s) {
+  return s.width >= 0 && s.height >= 0;
+}
+
+}  // namespace
+
 // Helper class for calling VideoPlane::SetGeometry with rate-limiting.
 // SetGeometry can take on the order of 100ms to run in some implementations
 // and can be called on the order of 20x / second (as fast as graphics frames
@@ -38,6 +59,7 @@
   void SetGeometry(const chromecast::RectF& display_rect,
                    VideoPlane::Transform transform) {
     DCHECK(task_runner_->BelongsToCurrentThread());
+    DCHECK(DisplayRectFValid(display_rect));
 
     base::TimeTicks now = base::TimeTicks::Now();
     base::TimeDelta elapsed = now - last_set_geometry_time_;
@@ -119,11 +141,89 @@
   return base::Singleton<VideoPlaneController>::get();
 }
 
+// TODO(esum): SetGeometry, SetDeviceResolution, and SetGraphicsPlaneResolution
+// follow the same pattern (copy/paste). Currently it's not worth modularizing
+// since there are only 3 fields. If more fields are needed in the future,
+// consider making a generic method to implement this pattern.
 void VideoPlaneController::SetGeometry(const RectF& display_rect,
                                        VideoPlane::Transform transform) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(DisplayRectFValid(display_rect));
+  if (have_video_plane_geometry_ &&
+      RectFEqual(display_rect, video_plane_display_rect_) &&
+      transform == video_plane_transform_) {
+    VLOG(2) << "No change found in geometry parameters.";
+    return;
+  }
+
+  VLOG(1) << "New geometry parameters "
+          << " rect=" << display_rect.width << "x" << display_rect.height
+          << " @" << display_rect.x << "," << display_rect.y << " transform "
+          << transform;
+
+  have_video_plane_geometry_ = true;
+  video_plane_display_rect_ = display_rect;
+  video_plane_transform_ = transform;
+
+  MaybeRunSetGeometry();
+}
+
+void VideoPlaneController::SetDeviceResolution(const Size& resolution) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(ResolutionSizeValid(resolution));
+  if (have_output_res_ && SizeEqual(resolution, output_res_)) {
+    VLOG(2) << "No change found in output resolution.";
+    return;
+  }
+
+  VLOG(1) << "New output resolution " << resolution.width << "x"
+          << resolution.height;
+
+  have_output_res_ = true;
+  output_res_ = resolution;
+
+  MaybeRunSetGeometry();
+}
+
+void VideoPlaneController::SetGraphicsPlaneResolution(const Size& resolution) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(ResolutionSizeValid(resolution));
+  if (have_graphics_res_ && SizeEqual(resolution, graphics_res_)) {
+    VLOG(2) << "No change found in graphics resolution.";
+    return;
+  }
+
+  VLOG(1) << "New graphics resolution " << resolution.width << "x"
+          << resolution.height;
+
+  have_graphics_res_ = true;
+  graphics_res_ = resolution;
+
+  MaybeRunSetGeometry();
+}
+
+VideoPlaneController::VideoPlaneController()
+    : have_output_res_(false),
+      have_graphics_res_(false),
+      output_res_(0, 0),
+      graphics_res_(0, 0),
+      have_video_plane_geometry_(false),
+      video_plane_display_rect_(0, 0),
+      video_plane_transform_(VideoPlane::TRANSFORM_NONE),
+      media_task_runner_(MediaMessageLoop::GetTaskRunner()),
+      video_plane_wrapper_(
+          new RateLimitedSetVideoPlaneGeometry(media_task_runner_)) {}
+
+VideoPlaneController::~VideoPlaneController() {}
+
+void VideoPlaneController::MaybeRunSetGeometry() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!HaveDataForSetGeometry())
+    return;
+
   DCHECK(graphics_res_.width != 0 && graphics_res_.height != 0);
 
-  RectF scaled_rect = display_rect;
+  RectF scaled_rect = video_plane_display_rect_;
   if (graphics_res_.width != output_res_.width ||
       graphics_res_.height != output_res_.height) {
     float sx = static_cast<float>(output_res_.width) / graphics_res_.width;
@@ -135,50 +235,15 @@
   }
 
   media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&RateLimitedSetVideoPlaneGeometry::SetGeometry,
-                            video_plane_wrapper_, scaled_rect, transform));
-
-  have_video_plane_geometry_ = true;
-  video_plane_display_rect_ = display_rect;
-  video_plane_transform_ = transform;
+      FROM_HERE,
+      base::Bind(&RateLimitedSetVideoPlaneGeometry::SetGeometry,
+                 video_plane_wrapper_, scaled_rect, video_plane_transform_));
 }
 
-void VideoPlaneController::OnDeviceResolutionChanged(const Size& resolution) {
-  if (output_res_.width == resolution.width &&
-      output_res_.height == resolution.height)
-    return;
-
-  output_res_ = resolution;
-
-  if (have_video_plane_geometry_) {
-    SetGeometry(video_plane_display_rect_, video_plane_transform_);
-  }
+bool VideoPlaneController::HaveDataForSetGeometry() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return have_output_res_ && have_graphics_res_ && have_video_plane_geometry_;
 }
 
-void VideoPlaneController::OnGraphicsPlaneResolutionChanged(
-    const Size& resolution) {
-  if (graphics_res_.width == resolution.width &&
-      graphics_res_.height == resolution.height)
-    return;
-
-  graphics_res_ = resolution;
-
-  if (have_video_plane_geometry_) {
-    SetGeometry(video_plane_display_rect_, video_plane_transform_);
-  }
-}
-
-VideoPlaneController::VideoPlaneController()
-    : output_res_(0, 0),
-      graphics_res_(0, 0),
-      have_video_plane_geometry_(false),
-      video_plane_display_rect_(0, 0),
-      video_plane_transform_(media::VideoPlane::TRANSFORM_NONE),
-      media_task_runner_(chromecast::media::MediaMessageLoop::GetTaskRunner()),
-      video_plane_wrapper_(
-          new RateLimitedSetVideoPlaneGeometry(media_task_runner_)) {}
-
-VideoPlaneController::~VideoPlaneController() {}
-
 }  // namespace media
 }  // namespace chromecast
diff --git a/chromecast/media/base/video_plane_controller.h b/chromecast/media/base/video_plane_controller.h
index c6ac581..302c8fa 100644
--- a/chromecast/media/base/video_plane_controller.h
+++ b/chromecast/media/base/video_plane_controller.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
+#include "base/threading/thread_checker.h"
 #include "chromecast/public/graphics_types.h"
 #include "chromecast/public/video_plane.h"
 
@@ -26,7 +27,12 @@
 // * coalesces multiple calls in short space of time to prevent flooding the
 //   media thread with SetGeometry calls (which are expensive on many
 //   platforms).
-// up to be informed of certain resolution changes.
+// The class collects/caches the data it needs before it can start operating.
+// This means SetGeometry, SetDeviceResolution, and SetGraphicsPlaneResolution
+// need to be called at least once in any order before the class starts making
+// calls to VideoPlane::SetGeometry. All calls to these methods beforehand just
+// set/update the cached parameters.
+// All calls to public methods should be from the same thread.
 class VideoPlaneController {
  public:
   static VideoPlaneController* GetInstance();
@@ -35,17 +41,22 @@
   // in *graphics plane coordinates*.
   //  * This should be called on UI thread (hopping to media thread is handled
   //    internally).
-  void SetGeometry(const RectF& display_rect,
-                   media::VideoPlane::Transform transform);
+  // If there is no change to video plane parameters from the last call to this
+  // method, it is a no-op.
+  void SetGeometry(const RectF& display_rect, VideoPlane::Transform transform);
 
-  // Handles a change in physical screen resolution.  This must be called when
-  // the final output resolution (HDMI signal or panel resolution) changes.
-  void OnDeviceResolutionChanged(const Size& resolution);
+  // Sets physical screen resolution.  This must be called at least once when
+  // the final output resolution (HDMI signal or panel resolution) is known,
+  // then later when it changes. If there is no change to the device resolution
+  // from the last call to this method, it is a no-op.
+  void SetDeviceResolution(const Size& resolution);
 
-  // Handles a change in graphics hardware plane resolution.  This must be
-  // called when the hardware graphics plane resolution changes (same resolution
-  // as gfx::Screen).
-  void OnGraphicsPlaneResolutionChanged(const Size& resolution);
+  // Sets graphics hardware plane resolution.  This must be called at least once
+  // when the hardware graphics plane resolution (same resolution as
+  // gfx::Screen) is known, then later when it changes. If there is no change to
+  // the graphics plane resolution from the last call to this method, it is a
+  // no-op.
+  void SetGraphicsPlaneResolution(const Size& resolution);
 
  private:
   class RateLimitedSetVideoPlaneGeometry;
@@ -54,7 +65,17 @@
   VideoPlaneController();
   ~VideoPlaneController();
 
+  // Check if HaveDataForSetGeometry. If not, this method is a no-op. Otherwise
+  // it scales the display rect from graphics to device resolution coordinates.
+  // Then posts task to media thread for VideoPlane::SetGeometry.
+  void MaybeRunSetGeometry();
+  // Checks if all data has been collected to make calls to
+  // VideoPlane::SetGeometry.
+  bool HaveDataForSetGeometry() const;
+
   // Current resolutions
+  bool have_output_res_;
+  bool have_graphics_res_;
   Size output_res_;
   Size graphics_res_;
 
@@ -67,6 +88,8 @@
   scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
   scoped_refptr<RateLimitedSetVideoPlaneGeometry> video_plane_wrapper_;
 
+  base::ThreadChecker thread_checker_;
+
   DISALLOW_COPY_AND_ASSIGN(VideoPlaneController);
 };
 
diff --git a/components/autofill.gypi b/components/autofill.gypi
index af4f855..b9cb375e 100644
--- a/components/autofill.gypi
+++ b/components/autofill.gypi
@@ -46,6 +46,7 @@
         'autofill/core/common/password_form_field_prediction_map.h',
         'autofill/core/common/password_form_fill_data.cc',
         'autofill/core/common/password_form_fill_data.h',
+        'autofill/core/common/password_form_generation_data.h',
         'autofill/core/common/password_generation_util.cc',
         'autofill/core/common/password_generation_util.h',
         'autofill/core/common/save_password_progress_logger.cc',
diff --git a/components/autofill/content/common/autofill_messages.h b/components/autofill/content/common/autofill_messages.h
index f1d3ea6a..f3977e5 100644
--- a/components/autofill/content/common/autofill_messages.h
+++ b/components/autofill/content/common/autofill_messages.h
@@ -17,6 +17,7 @@
 #include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_field_prediction_map.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
 #include "content/public/common/common_param_traits.h"
 #include "content/public/common/common_param_traits_macros.h"
 #include "ipc/ipc_message_macros.h"
@@ -70,6 +71,12 @@
   IPC_STRUCT_TRAITS_MEMBER(fields)
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(autofill::PasswordFormGenerationData)
+  IPC_STRUCT_TRAITS_MEMBER(name)
+  IPC_STRUCT_TRAITS_MEMBER(action)
+  IPC_STRUCT_TRAITS_MEMBER(generation_field)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(autofill::UsernamesCollectionKey)
   IPC_STRUCT_TRAITS_MEMBER(username)
   IPC_STRUCT_TRAITS_MEMBER(password)
@@ -197,9 +204,10 @@
                     autofill::FormData /* form_data */)
 
 // Sent when Autofill manager gets the query response from the Autofill server
-// and there are fields classified as ACCOUNT_CREATION_PASSWORD in the response.
-IPC_MESSAGE_ROUTED1(AutofillMsg_AccountCreationFormsDetected,
-                    std::vector<autofill::FormData> /* forms */)
+// and there are fields classified for password generation in the response.
+IPC_MESSAGE_ROUTED1(
+    AutofillMsg_FoundFormsEligibleForGeneration,
+    std::vector<autofill::PasswordFormGenerationData> /* forms */)
 
 // Sent when Autofill manager gets the query response from the Autofill server
 // which contains information about username and password fields for some forms.
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc
index 6ad50b5..07d19ca 100644
--- a/components/autofill/content/renderer/password_generation_agent.cc
+++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -14,6 +14,7 @@
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_view.h"
@@ -50,34 +51,44 @@
         passwords->push_back(*input_element);
     }
   }
-
-  // This may be too lenient, but we assume that any form with at least three
-  // input elements where at least one of them is a password is an account
-  // creation form.
-  if (!passwords->empty() && num_input_elements >= 3) {
-    // We trim |passwords| because occasionally there are forms where the
-    // security question answers are put in password fields and we don't want
-    // to fill those.
-    if (passwords->size() > 2)
-      passwords->resize(2);
-
-    return true;
-  }
-
-  return false;
+  return !passwords->empty();
 }
 
 bool ContainsURL(const std::vector<GURL>& urls, const GURL& url) {
   return std::find(urls.begin(), urls.end(), url) != urls.end();
 }
 
-bool ContainsForm(const std::vector<FormData>& forms,
-                  const PasswordForm& form) {
+const PasswordFormGenerationData* FindFormGenerationData(
+    const std::vector<PasswordFormGenerationData>& forms,
+    const PasswordForm& form) {
   for (const auto& form_it : forms) {
-    if (form_it.SameFormAs(form.form_data))
-      return true;
+    if (form_it.name == form.form_data.name && form_it.action == form.action)
+      return &form_it;
   }
-  return false;
+  return nullptr;
+}
+
+// This function returns a vector of password fields into which Chrome should
+// fill the generated password. It assumes that |field_data| describes the field
+// where Chrome shows the password generation prompt. It returns no more
+// than 2 elements.
+std::vector<blink::WebInputElement> FindPasswordElementsForGeneration(
+    const std::vector<blink::WebInputElement>& all_password_elements,
+    const FormFieldData& field_data) {
+  auto iter =
+      std::find_if(all_password_elements.begin(), all_password_elements.end(),
+                   [&field_data](const blink::WebInputElement& input) {
+                     return input.nameForAutofill() == field_data.name;
+                   });
+  std::vector<blink::WebInputElement> passwords;
+
+  // We copy not more than 2 fields because occasionally there are forms where
+  // the security question answers are put in password fields and we don't want
+  // to fill those.
+  for (; iter != all_password_elements.end() && passwords.size() < 2; ++iter) {
+    passwords.push_back(*iter);
+  }
+  return passwords;
 }
 
 void CopyElementValueToOtherInputElements(
@@ -240,8 +251,8 @@
                         OnFormNotBlacklisted)
     IPC_MESSAGE_HANDLER(AutofillMsg_GeneratedPasswordAccepted,
                         OnPasswordAccepted)
-    IPC_MESSAGE_HANDLER(AutofillMsg_AccountCreationFormsDetected,
-                        OnAccountCreationFormsDetected)
+    IPC_MESSAGE_HANDLER(AutofillMsg_FoundFormsEligibleForGeneration,
+                        OnFormsEligibleForGenerationFound);
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -271,10 +282,10 @@
   }
 }
 
-void PasswordGenerationAgent::OnAccountCreationFormsDetected(
-    const std::vector<FormData>& forms) {
-  generation_enabled_forms_.insert(
-      generation_enabled_forms_.end(), forms.begin(), forms.end());
+void PasswordGenerationAgent::OnFormsEligibleForGenerationFound(
+    const std::vector<autofill::PasswordFormGenerationData>& forms) {
+  generation_enabled_forms_.insert(generation_enabled_forms_.end(),
+                                   forms.begin(), forms.end());
   DetermineGenerationElement();
 }
 
@@ -296,6 +307,7 @@
   // (e.g. password saving is disabled).
   for (auto& possible_form_data : possible_account_creation_forms_) {
     PasswordForm* possible_password_form = possible_form_data.form.get();
+    const PasswordFormGenerationData* generation_data = nullptr;
     if (base::CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kLocalHeuristicsOnlyForPasswordGeneration)) {
       VLOG(2) << "Bypassing additional checks.";
@@ -304,24 +316,36 @@
       VLOG(2) << "Have not received confirmation that password form isn't "
                << "blacklisted";
       continue;
-    } else if (!ContainsForm(generation_enabled_forms_,
-                             *possible_password_form)) {
-      if (AutocompleteAttributesSetForGeneration(*possible_password_form)) {
-        VLOG(2) << "Ignoring lack of Autofill signal due to Autocomplete "
-                << "attributes";
-        password_generation::LogPasswordGenerationEvent(
-            password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION);
-      } else {
-        VLOG(2) << "Have not received confirmation from Autofill that form is "
-                << "used for account creation";
-        continue;
+    } else {
+      generation_data = FindFormGenerationData(generation_enabled_forms_,
+                                               *possible_password_form);
+      if (!generation_data) {
+        if (AutocompleteAttributesSetForGeneration(*possible_password_form)) {
+          VLOG(2) << "Ignoring lack of Autofill signal due to Autocomplete "
+                  << "attributes";
+          password_generation::LogPasswordGenerationEvent(
+              password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION);
+        } else {
+          VLOG(2)
+              << "Have not received confirmation from Autofill that form is "
+              << "used for account creation";
+          continue;
+        }
       }
     }
 
     VLOG(2) << "Password generation eligible form found";
-    generation_form_data_.reset(
-        new AccountCreationFormData(possible_form_data.form,
-                                    possible_form_data.password_elements));
+    std::vector<blink::WebInputElement> password_elements =
+        generation_data ? FindPasswordElementsForGeneration(
+                              possible_form_data.password_elements,
+                              generation_data->generation_field)
+                        : possible_form_data.password_elements;
+    if (password_elements.empty()) {
+      // It might be if JavaScript changes field names.
+      VLOG(2) << "Fields for generation are not found";
+    }
+    generation_form_data_.reset(new AccountCreationFormData(
+        possible_form_data.form, std::move(password_elements)));
     generation_element_ = generation_form_data_->password_elements[0];
     generation_element_.setAttribute("aria-autocomplete", "list");
     password_generation::LogPasswordGenerationEvent(
diff --git a/components/autofill/content/renderer/password_generation_agent.h b/components/autofill/content/renderer/password_generation_agent.h
index 51844317..959914f 100644
--- a/components/autofill/content/renderer/password_generation_agent.h
+++ b/components/autofill/content/renderer/password_generation_agent.h
@@ -23,6 +23,7 @@
 
 struct FormData;
 struct PasswordForm;
+struct PasswordFormGenerationData;
 class PasswordAutofillAgent;
 
 // This class is responsible for controlling communication for password
@@ -77,8 +78,8 @@
   // Message handlers.
   void OnFormNotBlacklisted(const PasswordForm& form);
   void OnPasswordAccepted(const base::string16& password);
-  void OnAccountCreationFormsDetected(
-      const std::vector<autofill::FormData>& forms);
+  void OnFormsEligibleForGenerationFound(
+      const std::vector<autofill::PasswordFormGenerationData>& forms);
 
   // Helper function that will try and populate |password_elements_| and
   // |possible_account_creation_form_|.
@@ -107,9 +108,9 @@
   std::vector<GURL> not_blacklisted_password_form_origins_;
 
   // Stores each password form for which the Autofill server classifies one of
-  // the form's fields as an ACCOUNT_CREATION_PASSWORD. These forms will
-  // not be sent if the feature is disabled.
-  std::vector<autofill::FormData> generation_enabled_forms_;
+  // the form's fields as an ACCOUNT_CREATION_PASSWORD or NEW_PASSWORD. These
+  // forms will not be sent if the feature is disabled.
+  std::vector<autofill::PasswordFormGenerationData> generation_enabled_forms_;
 
   // Data for form which generation is allowed on.
   scoped_ptr<AccountCreationFormData> generation_form_data_;
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc
index fa292e27..79b79cf 100644
--- a/components/autofill/core/browser/autofill_download_manager.cc
+++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -6,11 +6,14 @@
 
 #include <utility>
 
+#include "base/bind.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/prefs/pref_service.h"
 #include "base/rand_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
+#include "base/thread_task_runner_handle.h"
 #include "components/autofill/core/browser/autofill_driver.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/autofill_xml_parser.h"
@@ -22,6 +25,7 @@
 #include "net/base/load_flags.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
 #include "net/url_request/url_fetcher.h"
 #include "url/gurl.h"
 
@@ -29,10 +33,35 @@
 
 namespace {
 
-const char kAutofillQueryServerNameStartInHeader[] = "GFE/";
 const size_t kMaxFormCacheSize = 16;
 const size_t kMaxFieldsPerQueryRequest = 100;
 
+const net::BackoffEntry::Policy kAutofillBackoffPolicy = {
+    // Number of initial errors (in sequence) to ignore before applying
+    // exponential back-off rules.
+    0,
+
+    // Initial delay for exponential back-off in ms.
+    1000,  // 1 second.
+
+    // Factor by which the waiting time will be multiplied.
+    2,
+
+    // Fuzzing percentage. ex: 10% will spread requests randomly
+    // between 90%-100% of the calculated time.
+    0.33,  // 33%.
+
+    // Maximum amount of time we are willing to delay our request in ms.
+    30 * 1000,  // 30 seconds.
+
+    // Time to keep an entry from being discarded even when it
+    // has no significant state, -1 to never discard.
+    -1,
+
+    // Don't use initial delay unless the last request was an error.
+    false,
+};
+
 #if defined(GOOGLE_CHROME_BUILD)
 const char kClientName[] = "Google Chrome";
 #else
@@ -67,6 +96,7 @@
 struct AutofillDownloadManager::FormRequestData {
   std::vector<std::string> form_signatures;
   RequestType request_type;
+  std::string payload;
 };
 
 AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver,
@@ -76,11 +106,11 @@
       pref_service_(pref_service),
       observer_(observer),
       max_form_cache_size_(kMaxFormCacheSize),
-      next_query_request_(base::Time::Now()),
-      next_upload_request_(base::Time::Now()),
+      fetcher_backoff_(&kAutofillBackoffPolicy),
       positive_upload_rate_(0),
       negative_upload_rate_(0),
-      fetcher_id_for_unittest_(0) {
+      fetcher_id_for_unittest_(0),
+      weak_factory_(this) {
   DCHECK(observer_);
   positive_upload_rate_ =
       pref_service_->GetDouble(prefs::kAutofillPositiveUploadRate);
@@ -95,11 +125,6 @@
 
 bool AutofillDownloadManager::StartQueryRequest(
     const std::vector<FormStructure*>& forms) {
-  if (next_query_request_ > base::Time::Now()) {
-    // We are in back-off mode: do not do the request.
-    return false;
-  }
-
   // Do not send the request if it contains more fields than the server can
   // accept.
   if (CountActiveFieldsInForms(forms) > kMaxFieldsPerQueryRequest)
@@ -113,6 +138,7 @@
   }
 
   request_data.request_type = AutofillDownloadManager::REQUEST_QUERY;
+  request_data.payload = form_xml;
   AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_SENT);
 
   std::string query_data;
@@ -125,7 +151,7 @@
     return true;
   }
 
-  return StartRequest(form_xml, request_data);
+  return StartRequest(request_data);
 }
 
 bool AutofillDownloadManager::StartUploadRequest(
@@ -140,12 +166,6 @@
                                 &form_xml))
     return false;
 
-  if (next_upload_request_ > base::Time::Now()) {
-    // We are in back-off mode: do not do the request.
-    VLOG(1) << "AutofillDownloadManager: Upload request is throttled.";
-    return false;
-  }
-
   // Flip a coin to see if we should upload this form.
   double upload_rate = form_was_autofilled ? GetPositiveUploadRate() :
                                              GetNegativeUploadRate();
@@ -160,8 +180,9 @@
   FormRequestData request_data;
   request_data.form_signatures.push_back(form.FormSignature());
   request_data.request_type = AutofillDownloadManager::REQUEST_UPLOAD;
+  request_data.payload = form_xml;
 
-  return StartRequest(form_xml, request_data);
+  return StartRequest(request_data);
 }
 
 double AutofillDownloadManager::GetPositiveUploadRate() const {
@@ -191,7 +212,6 @@
 }
 
 bool AutofillDownloadManager::StartRequest(
-    const std::string& form_xml,
     const FormRequestData& request_data) {
   net::URLRequestContextGetter* request_context =
       driver_->GetURLRequestContext();
@@ -199,13 +219,13 @@
   GURL request_url = GetRequestUrl(request_data.request_type);
 
   std::string compressed_data;
-  if (!compression::GzipCompress(form_xml, &compressed_data)) {
+  if (!compression::GzipCompress(request_data.payload, &compressed_data)) {
     NOTREACHED();
     return false;
   }
 
-  const int compression_ratio =
-      static_cast<int>(100 * compressed_data.size() / form_xml.size());
+  const int compression_ratio = base::checked_cast<int>(
+      100 * compressed_data.size() / request_data.payload.size());
   AutofillMetrics::LogPayloadCompressionRatio(compression_ratio,
                                               request_data.request_type);
 
@@ -232,7 +252,8 @@
 
   VLOG(1) << "Sending AutofillDownloadManager "
           << RequestTypeToString(request_data.request_type)
-          << " request (compression " << compression_ratio << "): " << form_xml;
+          << " request (compression " << compression_ratio
+          << "): " << request_data.payload;
 
   return true;
 }
@@ -299,39 +320,19 @@
     return;
   }
   std::string request_type(RequestTypeToString(it->second.request_type));
-  const int kHttpResponseOk = 200;
-  const int kHttpInternalServerError = 500;
-  const int kHttpBadGateway = 502;
-  const int kHttpServiceUnavailable = 503;
 
   CHECK(it->second.form_signatures.size());
-  if (source->GetResponseCode() != kHttpResponseOk) {
-    bool back_off = false;
-    std::string server_header;
-    switch (source->GetResponseCode()) {
-      case kHttpBadGateway:
-        if (!source->GetResponseHeaders()->EnumerateHeader(NULL, "server",
-                                                           &server_header) ||
-            base::StartsWith(server_header.c_str(),
-                             kAutofillQueryServerNameStartInHeader,
-                             base::CompareCase::INSENSITIVE_ASCII) != 0)
-          break;
-        // Bad gateway was received from Autofill servers. Fall through to back
-        // off.
-      case kHttpInternalServerError:
-      case kHttpServiceUnavailable:
-        back_off = true;
-        break;
-    }
+  bool success = source->GetResponseCode() == net::HTTP_OK;
+  fetcher_backoff_.InformOfRequest(success);
 
-    if (back_off) {
-      base::Time back_off_time(base::Time::Now() + source->GetBackoffDelay());
-      if (it->second.request_type == AutofillDownloadManager::REQUEST_QUERY) {
-        next_query_request_ = back_off_time;
-      } else {
-        next_upload_request_ = back_off_time;
-      }
-    }
+  if (!success) {
+    // Reschedule with the appropriate delay, ignoring return value because
+    // payload is already well formed.
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(base::IgnoreResult(&AutofillDownloadManager::StartRequest),
+                   weak_factory_.GetWeakPtr(), it->second),
+        fetcher_backoff_.GetTimeUntilRelease());
 
     VLOG(1) << "AutofillDownloadManager: " << request_type
              << " request has failed with response "
diff --git a/components/autofill/core/browser/autofill_download_manager.h b/components/autofill/core/browser/autofill_download_manager.h
index 57530ca0..006e320 100644
--- a/components/autofill/core/browser/autofill_download_manager.h
+++ b/components/autofill/core/browser/autofill_download_manager.h
@@ -14,8 +14,10 @@
 
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
+#include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "net/base/backoff_entry.h"
 #include "net/url_request/url_fetcher_delegate.h"
 
 class PrefService;
@@ -95,21 +97,19 @@
       bool observed_submission);
 
  private:
-  friend class AutofillDownloadTest;
-  FRIEND_TEST_ALL_PREFIXES(AutofillDownloadTest, QueryAndUploadTest);
-  FRIEND_TEST_ALL_PREFIXES(AutofillDownloadTest, UploadRequestIsGzipped);
+  friend class AutofillDownloadManagerTest;
+  FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, QueryAndUploadTest);
+  FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, BackoffLogic_Upload);
+  FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, BackoffLogic_Query);
+  FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, UploadRequestIsGzipped);
 
   struct FormRequestData;
   typedef std::list<std::pair<std::string, std::string> > QueryRequestCache;
 
-  // Initiates request to Autofill servers to download/upload heuristics.
-  // |form_xml| - form structure XML to upload/download.
-  // |request_data| - form signature hash(es) and indicator if it was a query.
-  // |request_data.query| - if true the data is queried and observer notified
-  //   with new data, if available. If false heuristic data is uploaded to our
-  //   servers.
-  bool StartRequest(const std::string& form_xml,
-                    const FormRequestData& request_data);
+  // Initiates request to Autofill servers to download/upload type predictions.
+  // |request_data| - form signature hash(es), request payload data and request
+  //   type (query or upload).
+  bool StartRequest(const FormRequestData& request_data);
 
   // Each request is page visited. We store last |max_form_cache_size|
   // request, to avoid going over the wire. Set to 16 in constructor. Warning:
@@ -162,11 +162,8 @@
   QueryRequestCache cached_forms_;
   size_t max_form_cache_size_;
 
-  // Time when next query/upload requests are allowed. If 50x HTTP received,
-  // exponential back off is initiated, so this times will be in the future
-  // for awhile.
-  base::Time next_query_request_;
-  base::Time next_upload_request_;
+  // Used for exponential backoff of requests.
+  net::BackoffEntry fetcher_backoff_;
 
   // |positive_upload_rate_| is for matched forms,
   // |negative_upload_rate_| for non matched.
@@ -175,6 +172,8 @@
 
   // Needed for unit-test.
   int fetcher_id_for_unittest_;
+
+  base::WeakPtrFactory<AutofillDownloadManager> weak_factory_;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc
index cddcc14..e71048c7 100644
--- a/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -23,6 +23,7 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/compression/compression_utils.h"
 #include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_status.h"
 #include "net/url_request/url_request_test_util.h"
@@ -57,7 +58,7 @@
 
 }  // namespace
 
-// This tests AutofillDownloadManager. AutofillDownloadTest implements
+// This tests AutofillDownloadManager. AutofillDownloadManagerTest implements
 // AutofillDownloadManager::Observer and creates an instance of
 // AutofillDownloadManager. Then it records responses to different initiated
 // requests, which are verified later. To mock network requests
@@ -65,10 +66,10 @@
 // go over the wire, but allow calling back HTTP responses directly.
 // The responses in test are out of order and verify: successful query request,
 // successful upload request, failed upload request.
-class AutofillDownloadTest : public AutofillDownloadManager::Observer,
-                             public testing::Test {
+class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer,
+                                    public testing::Test {
  public:
-  AutofillDownloadTest()
+  AutofillDownloadManagerTest()
       : prefs_(test::PrefServiceForTesting()),
         request_context_(new net::TestURLRequestContextGetter(
             base::ThreadTaskRunnerHandle::Get())),
@@ -132,7 +133,7 @@
   AutofillDownloadManager download_manager_;
 };
 
-TEST_F(AutofillDownloadTest, QueryAndUploadTest) {
+TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
   // Create and register factory.
   net::TestURLFetcherFactory factory;
 
@@ -262,7 +263,7 @@
   // Return them out of sequence.
   net::TestURLFetcher* fetcher = factory.GetFetcherByID(1);
   ASSERT_TRUE(fetcher);
-  FakeOnURLFetchComplete(fetcher, 200, std::string(responses[1]));
+  FakeOnURLFetchComplete(fetcher, net::HTTP_OK, std::string(responses[1]));
 
   // After that upload rates would be adjusted to 0.5/0.3
   EXPECT_DOUBLE_EQ(0.5, download_manager_.GetPositiveUploadRate());
@@ -270,14 +271,15 @@
 
   fetcher = factory.GetFetcherByID(2);
   ASSERT_TRUE(fetcher);
-  FakeOnURLFetchComplete(fetcher, 404, std::string(responses[2]));
+  FakeOnURLFetchComplete(fetcher, net::HTTP_NOT_FOUND,
+                         std::string(responses[2]));
 
   fetcher = factory.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
-  FakeOnURLFetchComplete(fetcher, 200, std::string(responses[0]));
+  FakeOnURLFetchComplete(fetcher, net::HTTP_OK, std::string(responses[0]));
   EXPECT_EQ(3U, responses_.size());
 
-  EXPECT_EQ(AutofillDownloadTest::UPLOAD_SUCCESSFULL,
+  EXPECT_EQ(AutofillDownloadManagerTest::UPLOAD_SUCCESSFULL,
             responses_.front().type_of_response);
   EXPECT_EQ(0, responses_.front().error);
   EXPECT_EQ(std::string(), responses_.front().signature);
@@ -285,9 +287,9 @@
   EXPECT_EQ(std::string(), responses_.front().response);
   responses_.pop_front();
 
-  EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
+  EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_UPLOAD_FAILED,
             responses_.front().type_of_response);
-  EXPECT_EQ(404, responses_.front().error);
+  EXPECT_EQ(net::HTTP_NOT_FOUND, responses_.front().error);
   EXPECT_EQ(form_structures[1]->FormSignature(),
             responses_.front().signature);
   // Expected response on non-query request is an empty string.
@@ -295,7 +297,7 @@
   responses_.pop_front();
 
   EXPECT_EQ(responses_.front().type_of_response,
-            AutofillDownloadTest::QUERY_SUCCESSFULL);
+            AutofillDownloadManagerTest::QUERY_SUCCESSFULL);
   EXPECT_EQ(0, responses_.front().error);
   EXPECT_EQ(std::string(), responses_.front().signature);
   EXPECT_EQ(responses[0], responses_.front().response);
@@ -326,45 +328,141 @@
   ASSERT_TRUE(fetcher);
   histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
                                AutofillMetrics::QUERY_SENT, 2);
-  fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
-  FakeOnURLFetchComplete(fetcher, 500, std::string(responses[0]));
+  FakeOnURLFetchComplete(fetcher, net::HTTP_INTERNAL_SERVER_ERROR,
+                         std::string(responses[0]));
 
-  EXPECT_EQ(AutofillDownloadTest::REQUEST_QUERY_FAILED,
+  EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_QUERY_FAILED,
             responses_.front().type_of_response);
-  EXPECT_EQ(500, responses_.front().error);
+  EXPECT_EQ(net::HTTP_INTERNAL_SERVER_ERROR, responses_.front().error);
   // Expected response on non-query request is an empty string.
   EXPECT_EQ(std::string(), responses_.front().response);
   responses_.pop_front();
-
-  // Query requests should be ignored for the next 10 seconds.
-  EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get()));
-  fetcher = factory.GetFetcherByID(5);
-  EXPECT_EQ(NULL, fetcher);
-  histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
-                               AutofillMetrics::QUERY_SENT, 2);
-
-  // Set upload required to true so requests happen.
-  form_structures[0]->upload_required_ = UPLOAD_REQUIRED;
-  // Request with id 4.
-  EXPECT_TRUE(download_manager_.StartUploadRequest(
-      *(form_structures[0]), true, ServerFieldTypeSet(), std::string(), true));
-  fetcher = factory.GetFetcherByID(5);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_backoff_delay(TestTimeouts::action_max_timeout());
-  FakeOnURLFetchComplete(fetcher, 503, std::string(responses[2]));
-  EXPECT_EQ(AutofillDownloadTest::REQUEST_UPLOAD_FAILED,
-            responses_.front().type_of_response);
-  EXPECT_EQ(503, responses_.front().error);
-  responses_.pop_front();
-
-  // Upload requests should be ignored for the next 10 seconds.
-  EXPECT_FALSE(download_manager_.StartUploadRequest(
-      *(form_structures[0]), true, ServerFieldTypeSet(), std::string(), true));
-  fetcher = factory.GetFetcherByID(6);
-  EXPECT_EQ(NULL, fetcher);
 }
 
-TEST_F(AutofillDownloadTest, QueryTooManyFieldsTest) {
+TEST_F(AutofillDownloadManagerTest, BackoffLogic_Query) {
+  // Create and register factory.
+  net::TestURLFetcherFactory factory;
+
+  FormData form;
+  FormFieldData field;
+  field.label = ASCIIToUTF16("address");
+  field.name = ASCIIToUTF16("address");
+  field.form_control_type = "text";
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("address2");
+  field.name = ASCIIToUTF16("address2");
+  field.form_control_type = "text";
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("city");
+  field.name = ASCIIToUTF16("city");
+  field.form_control_type = "text";
+  form.fields.push_back(field);
+
+  field.label = base::string16();
+  field.name = ASCIIToUTF16("Submit");
+  field.form_control_type = "submit";
+  form.fields.push_back(field);
+
+  FormStructure* form_structure = new FormStructure(form);
+  ScopedVector<FormStructure> form_structures;
+  form_structures.push_back(form_structure);
+
+  // Request with id 0.
+  base::HistogramTester histogram;
+  EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get()));
+  histogram.ExpectUniqueSample("Autofill.ServerQueryResponse",
+                               AutofillMetrics::QUERY_SENT, 1);
+
+  net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
+  ASSERT_TRUE(fetcher);
+
+  // Request error incurs a retry after 1 second.
+  FakeOnURLFetchComplete(fetcher, net::HTTP_NOT_FOUND, "<html></html>");
+  EXPECT_EQ(1U, responses_.size());
+  EXPECT_LT(download_manager_.fetcher_backoff_.GetTimeUntilRelease(),
+            base::TimeDelta::FromMilliseconds(1100));
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+      base::TimeDelta::FromMilliseconds(1100));
+  base::MessageLoop::current()->Run();
+
+  // Get the retried request.
+  fetcher = factory.GetFetcherByID(1);
+  ASSERT_TRUE(fetcher);
+
+  // Next error incurs a retry after 2 seconds.
+  FakeOnURLFetchComplete(fetcher, net::HTTP_INTERNAL_SERVER_ERROR, "");
+  EXPECT_EQ(2U, responses_.size());
+  EXPECT_LT(download_manager_.fetcher_backoff_.GetTimeUntilRelease(),
+            base::TimeDelta::FromMilliseconds(2100));
+}
+
+TEST_F(AutofillDownloadManagerTest, BackoffLogic_Upload) {
+  // Create and register factory.
+  net::TestURLFetcherFactory factory;
+
+  FormData form;
+  FormFieldData field;
+  field.label = ASCIIToUTF16("address");
+  field.name = ASCIIToUTF16("address");
+  field.form_control_type = "text";
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("address2");
+  field.name = ASCIIToUTF16("address2");
+  field.form_control_type = "text";
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("city");
+  field.name = ASCIIToUTF16("city");
+  field.form_control_type = "text";
+  form.fields.push_back(field);
+
+  field.label = base::string16();
+  field.name = ASCIIToUTF16("Submit");
+  field.form_control_type = "submit";
+  form.fields.push_back(field);
+
+  scoped_ptr<FormStructure> form_structure(new FormStructure(form));
+
+  // Set upload to 100% so requests happen.
+  download_manager_.SetPositiveUploadRate(1.0);
+  download_manager_.SetNegativeUploadRate(1.0);
+  // Request with id 0.
+  EXPECT_TRUE(download_manager_.StartUploadRequest(
+      *form_structure, true, ServerFieldTypeSet(), std::string(), true));
+
+  net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
+  ASSERT_TRUE(fetcher);
+
+  // Error incurs a retry after 1 second.
+  FakeOnURLFetchComplete(fetcher, net::HTTP_NOT_FOUND, "<html></html>");
+  EXPECT_EQ(1U, responses_.size());
+  EXPECT_LT(download_manager_.fetcher_backoff_.GetTimeUntilRelease(),
+            base::TimeDelta::FromMilliseconds(1100));
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+      base::TimeDelta::FromMilliseconds(1100));
+  base::MessageLoop::current()->Run();
+
+  // Get the retried request.
+  fetcher = factory.GetFetcherByID(1);
+  ASSERT_TRUE(fetcher);
+
+  // The retried request is a success.
+  FakeOnURLFetchComplete(fetcher, net::HTTP_OK,
+                         "<autofilluploadresponse positiveuploadrate=\"0.5\""
+                         " negativeuploadrate=\"0.3\"/>");
+  EXPECT_EQ(2U, responses_.size());
+
+  // After last success, upload rates are adjusted to 0.5/0.3.
+  EXPECT_DOUBLE_EQ(0.5, download_manager_.GetPositiveUploadRate());
+  EXPECT_DOUBLE_EQ(0.3, download_manager_.GetNegativeUploadRate());
+}
+
+TEST_F(AutofillDownloadManagerTest, QueryTooManyFieldsTest) {
   // Create and register factory.
   net::TestURLFetcherFactory factory;
 
@@ -387,7 +485,7 @@
   EXPECT_FALSE(download_manager_.StartQueryRequest(form_structures.get()));
 }
 
-TEST_F(AutofillDownloadTest, QueryNotTooManyFieldsTest) {
+TEST_F(AutofillDownloadManagerTest, QueryNotTooManyFieldsTest) {
   // Create and register factory.
   net::TestURLFetcherFactory factory;
 
@@ -411,7 +509,7 @@
   EXPECT_TRUE(download_manager_.StartQueryRequest(form_structures.get()));
 }
 
-TEST_F(AutofillDownloadTest, CacheQueryTest) {
+TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
   // Create and register factory.
   net::TestURLFetcherFactory factory;
 
@@ -560,7 +658,7 @@
   EXPECT_EQ(responses[0], responses_.front().response);
 }
 
-TEST_F(AutofillDownloadTest, QueryRequestIsGzipped) {
+TEST_F(AutofillDownloadManagerTest, QueryRequestIsGzipped) {
   // Expected query (uncompressed for visual verification).
   const char* kExpectedQueryXml =
       "<?xml version=\"1.0\"?>\n"
@@ -619,7 +717,7 @@
   histogram.ExpectUniqueSample("Autofill.PayloadCompressionRatio.Query", 72, 1);
 }
 
-TEST_F(AutofillDownloadTest, UploadRequestIsGzipped) {
+TEST_F(AutofillDownloadManagerTest, UploadRequestIsGzipped) {
   // Expected upload (uncompressed for visual verification).
   const char* kExpectedUploadXml =
       "<?xml version=\"1.0\"?>\n"
diff --git a/components/autofill/core/browser/autofill_field_unittest.cc b/components/autofill/core/browser/autofill_field_unittest.cc
index e4dd5dc..f7274c1 100644
--- a/components/autofill/core/browser/autofill_field_unittest.cc
+++ b/components/autofill/core/browser/autofill_field_unittest.cc
@@ -26,13 +26,13 @@
 #endif
 
 const std::vector<const char*> kNotNumericMonthsContentsNoPlaceholder = {
-    "Jan", "Fev", "Mar", "Apr", "May", "Jun",
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 
 const std::vector<const char*> kNotNumericMonthsContentsWithPlaceholder = {
     "Select a Month",
     "Jan",
-    "Fev",
+    "Feb",
     "Mar",
     "Apr",
     "May",
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index a5b5adfc..073d5b7 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -308,6 +308,11 @@
     scoped_ptr<FormStructure> form_structure,
     const TimeTicks& timestamp,
     bool observed_submission) {
+  // It is possible for |personal_data_| to be null, such as when used in the
+  // Android webview.
+  if (!personal_data_)
+    return;
+
   // Only upload server statistics and UMA metrics if at least some local data
   // is available to use as a baseline.
   const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
@@ -953,8 +958,10 @@
 
 void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
   scoped_ptr<CreditCard> imported_credit_card;
-  if (!personal_data_->ImportFormData(submitted_form, &imported_credit_card))
+  if (!personal_data_->ImportFormData(
+          submitted_form, IsCreditCardUploadEnabled(), &imported_credit_card)) {
     return;
+  }
 
 #ifdef ENABLE_FORM_DEBUG_DUMP
   // Debug code for research on what autofill Chrome extracts from the last few
diff --git a/components/autofill/core/browser/autofill_merge_unittest.cc b/components/autofill/core/browser/autofill_merge_unittest.cc
index 31884f6..44d9023 100644
--- a/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -224,7 +224,8 @@
 
       // Import the profile.
       scoped_ptr<CreditCard> imported_credit_card;
-      personal_data_.ImportFormData(form_structure, &imported_credit_card);
+      personal_data_.ImportFormData(form_structure, false,
+                                    &imported_credit_card);
       EXPECT_FALSE(imported_credit_card);
 
       // Clear the |form| to start a new profile.
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h
index e6b2c36e..c2c78a06 100644
--- a/components/autofill/core/browser/form_structure.h
+++ b/components/autofill/core/browser/form_structure.h
@@ -195,6 +195,8 @@
 
   const GURL& source_url() const { return source_url_; }
 
+  const GURL& target_url() const { return target_url_; }
+
   bool has_author_specified_types() { return has_author_specified_types_; }
 
   bool has_author_specified_sections() {
diff --git a/components/autofill/core/browser/password_generator.cc b/components/autofill/core/browser/password_generator.cc
index 3dcd1f2..da4b386 100644
--- a/components/autofill/core/browser/password_generator.cc
+++ b/components/autofill/core/browser/password_generator.cc
@@ -12,12 +12,12 @@
 #include "base/strings/string_util.h"
 #include "third_party/fips181/fips181.h"
 
-const int kMinUpper = 65;  // First upper case letter 'A'
-const int kMaxUpper = 90;  // Last upper case letter 'Z'
-const int kMinLower = 97;  // First lower case letter 'a'
-const int kMaxLower = 122; // Last lower case letter 'z'
-const int kMinDigit = 48;  // First digit '0'
-const int kMaxDigit = 57;  // Last digit '9'
+const int kMinUpper = 65;   // First upper case letter 'A'
+const int kMaxUpper = 90;   // Last upper case letter 'Z'
+const int kMinLower = 97;   // First lower case letter 'a'
+const int kMaxLower = 122;  // Last lower case letter 'z'
+const int kMinDigit = 48;   // First digit '0'
+const int kMaxDigit = 57;   // Last digit '9'
 const int kMinPasswordLength = 4;
 const int kMaxPasswordLength = 15;
 
@@ -50,9 +50,12 @@
   return num_lower_case && num_upper_case && num_digits;
 }
 
-// Make sure that there is at least one upper case and one number in the
-// password. Assume that there already exists a lower case letter as it's the
-// default from gen_pron_pass.
+}  // namespace
+
+namespace autofill {
+
+const int PasswordGenerator::kDefaultPasswordLength = 12;
+
 void ForceFixPassword(std::string* password) {
   for (char& it : *password) {
     if (islower(it)) {
@@ -69,12 +72,6 @@
   }
 }
 
-}  // namespace
-
-namespace autofill {
-
-const int PasswordGenerator::kDefaultPasswordLength = 12;
-
 PasswordGenerator::PasswordGenerator(int max_length)
     : password_length_(GetLengthFromHint(max_length, kDefaultPasswordLength)) {}
 PasswordGenerator::~PasswordGenerator() {}
diff --git a/components/autofill/core/browser/password_generator.h b/components/autofill/core/browser/password_generator.h
index 9177738..4a1f87f 100644
--- a/components/autofill/core/browser/password_generator.h
+++ b/components/autofill/core/browser/password_generator.h
@@ -12,6 +12,11 @@
 
 namespace autofill {
 
+// Make sure that there is at least one upper case and one number in the
+// password. |password| must not be null, and must point to a string containing
+// at least 3 lower-case letters.
+extern void ForceFixPassword(std::string* password);
+
 // Class to generate random passwords. Currently we just use a generic algorithm
 // for all sites, but eventually we can incorporate additional information to
 // determine passwords that are likely to be accepted (i.e. use pattern field,
diff --git a/components/autofill/core/browser/password_generator_unittest.cc b/components/autofill/core/browser/password_generator_unittest.cc
index b312d50..6360f8d 100644
--- a/components/autofill/core/browser/password_generator_unittest.cc
+++ b/components/autofill/core/browser/password_generator_unittest.cc
@@ -7,6 +7,27 @@
 #include "components/autofill/core/browser/password_generator.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+
+void CheckPasswordCorrectness(const std::string& password) {
+  int num_upper_case_letters = 0;
+  int num_lower_case_letters = 0;
+  int num_digits = 0;
+  for (size_t i = 0; i < password.size(); i++) {
+    if (isupper(password[i]))
+      ++num_upper_case_letters;
+    else if (islower(password[i]))
+      ++num_lower_case_letters;
+    else if (isdigit(password[i]))
+      ++num_digits;
+  }
+  EXPECT_GT(num_upper_case_letters, 0) << password;
+  EXPECT_GT(num_lower_case_letters, 0) << password;
+  EXPECT_GT(num_digits, 0) << password;
+}
+
+}  // namespace
+
 namespace autofill {
 
 TEST(PasswordGeneratorTest, PasswordLength) {
@@ -28,20 +49,7 @@
 TEST(PasswordGeneratorTest, PasswordPattern) {
   PasswordGenerator pg(12);
   std::string password = pg.Generate();
-  int num_upper_case_letters = 0;
-  int num_lower_case_letters = 0;
-  int num_digits = 0;
-  for (size_t i = 0; i < password.size(); i++) {
-    if (isupper(password[i]))
-      ++num_upper_case_letters;
-    else if (islower(password[i]))
-      ++num_lower_case_letters;
-    else if (isdigit(password[i]))
-      ++num_digits;
-  }
-  EXPECT_GT(num_upper_case_letters, 0) << password;
-  EXPECT_GT(num_lower_case_letters, 0) << password;
-  EXPECT_GT(num_digits, 0) << password;
+  CheckPasswordCorrectness(password);
 }
 
 TEST(PasswordGeneratorTest, Printable) {
@@ -53,4 +61,14 @@
   }
 }
 
+TEST(PasswordGeneratorTest, ForceFixPasswordTest) {
+  std::string passwords_to_fix[] = {"nonumbersoruppercase",
+                                    "nonumbersWithuppercase",
+                                    "numbers3Anduppercase", "UmpAwgemHoc"};
+  for (auto& password : passwords_to_fix) {
+    ForceFixPassword(&password);
+    CheckPasswordCorrectness(password);
+  }
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index 1b51952..bb6e5d40 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -347,6 +347,7 @@
 
 bool PersonalDataManager::ImportFormData(
     const FormStructure& form,
+    bool should_return_local_card,
     scoped_ptr<CreditCard>* imported_credit_card) {
   scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
   scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
@@ -454,8 +455,11 @@
     local_imported_credit_card.reset();
   }
 
-  // Don't import if we already have this info.
-  // Don't present a prompt if we have already saved this card number.
+  // Don't import if we already have this info. Don't present a prompt if we
+  // have already saved this card number, unless should_return_local_card is
+  // true which indicates that upload is enabled. In this case, it's useful to
+  // present the upload prompt to the user to promote the card from a local card
+  // to a synced server card.
   bool merged_credit_card = false;
   if (local_imported_credit_card) {
     for (CreditCard* card : local_credit_cards_) {
@@ -466,7 +470,8 @@
                                            app_locale_)) {
         merged_credit_card = true;
         UpdateCreditCard(card_copy);
-        local_imported_credit_card.reset();
+        if (!should_return_local_card)
+          local_imported_credit_card.reset();
         break;
       }
     }
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index 713491cc..5fe9c4a 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -89,11 +89,16 @@
   virtual void RemoveObserver(PersonalDataManagerObserver* observer);
 
   // Scans the given |form| for importable Autofill data. If the form includes
-  // sufficient address data, it is immediately imported. If the form includes
-  // sufficient credit card data, it is stored into |credit_card|, so that we
-  // can prompt the user whether to save this data.
+  // sufficient address data for a new profile, it is immediately imported. If
+  // the form includes sufficient credit card data for a new credit card, it is
+  // stored into |credit_card| so that we can prompt the user whether to save
+  // this data. If the form contains credit card data already present in a local
+  // credit card entry *and* |should_return_local_card| is true, the data is
+  // stored into |credit_card| so that we can prompt the user whether to upload
+  // it.
   // Returns |true| if sufficient address or credit card data was found.
   bool ImportFormData(const FormStructure& form,
+                      bool should_return_local_card,
                       scoped_ptr<CreditCard>* credit_card);
 
   // Called to indicate |data_model| was used (to fill in a form). Updates
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 4febae9a..a3fd0834 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -893,7 +893,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -934,7 +934,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure,
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure, false,
                                               &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -967,7 +967,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
   ASSERT_EQ(1U, results.size());
@@ -998,7 +998,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure,
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure, false,
                                               &imported_credit_card));
   const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
   ASSERT_EQ(0U, results.size());
@@ -1019,7 +1019,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure,
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure, false,
                                               &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1050,8 +1050,8 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(
-      personal_data_->ImportFormData(form_structure, &imported_credit_card));
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
+                                             &imported_credit_card));
   const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
   ASSERT_EQ(1U, profiles.size());
 }
@@ -1077,7 +1077,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
   ASSERT_EQ(1U, profiles.size());
@@ -1099,7 +1099,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
   ASSERT_EQ(1U, profiles.size());
@@ -1138,7 +1138,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1185,7 +1185,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1265,7 +1265,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1305,7 +1305,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1354,7 +1354,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1404,7 +1404,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1444,7 +1444,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
@@ -1484,7 +1484,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1531,7 +1531,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1572,7 +1572,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1612,7 +1612,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure1, false,
                                               &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1645,7 +1645,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
   personal_data_->SaveImportedCreditCard(*imported_credit_card);
@@ -1677,7 +1677,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
                                              &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
   personal_data_->SaveImportedCreditCard(*imported_credit_card);
@@ -1727,7 +1727,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
   personal_data_->SaveImportedCreditCard(*imported_credit_card);
@@ -1754,8 +1754,8 @@
   // the masked card.
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure2,
-                                             &imported_credit_card));
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure2, false,
+                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 }
 
@@ -1778,7 +1778,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
   personal_data_->SaveImportedCreditCard(*imported_credit_card);
@@ -1810,7 +1810,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure2, false,
                                               &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -1842,7 +1842,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
   personal_data_->SaveImportedCreditCard(*imported_credit_card);
@@ -1875,7 +1875,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
                                              &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
@@ -1913,7 +1913,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
   personal_data_->SaveImportedCreditCard(*imported_credit_card);
@@ -1942,7 +1942,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure2, false,
                                               &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
@@ -1978,7 +1978,7 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
                                              &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
   personal_data_->SaveImportedCreditCard(*imported_credit_card);
@@ -2009,7 +2009,7 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
                                              &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
@@ -2037,7 +2037,7 @@
 
   FormStructure form_structure3(form3);
   form_structure3.DetermineHeuristicTypes();
-  EXPECT_FALSE(personal_data_->ImportFormData(form_structure3,
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure3, false,
                                               &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -2090,7 +2090,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
@@ -2145,7 +2145,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
@@ -2205,7 +2205,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
@@ -2228,8 +2228,8 @@
 
   FormStructure form_structure2(form);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_TRUE(
-      personal_data_->ImportFormData(form_structure2, &imported_credit_card));
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure2, false,
+                                             &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 
   // Wait for the refresh, which in this case is a no-op.
@@ -2278,7 +2278,7 @@
   FormStructure form_structure(form);
   form_structure.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(personal_data_->ImportFormData(form_structure,
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
                                              &imported_credit_card));
   ASSERT_FALSE(imported_credit_card);
 
@@ -3147,8 +3147,8 @@
   FormStructure form_structure1(form1);
   form_structure1.DetermineHeuristicTypes();
   scoped_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(
-      personal_data_->ImportFormData(form_structure1, &imported_credit_card));
+  EXPECT_TRUE(personal_data_->ImportFormData(form_structure1, false,
+                                             &imported_credit_card));
   EXPECT_TRUE(imported_credit_card);
   imported_credit_card.reset();
 
@@ -3168,8 +3168,8 @@
 
   FormStructure form_structure2(form2);
   form_structure2.DetermineHeuristicTypes();
-  EXPECT_FALSE(
-      personal_data_->ImportFormData(form_structure2, &imported_credit_card));
+  EXPECT_FALSE(personal_data_->ImportFormData(form_structure2, false,
+                                              &imported_credit_card));
   EXPECT_FALSE(imported_credit_card);
 }
 
diff --git a/components/autofill/core/common/password_form_generation_data.h b/components/autofill/core/common/password_form_generation_data.h
new file mode 100644
index 0000000..38910c9
--- /dev/null
+++ b/components/autofill/core/common/password_form_generation_data.h
@@ -0,0 +1,30 @@
+// Copyright 2015 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_AUTOFILL_CORE_COMMON_PASSWORD_FORM_GENERATION_DATA_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_FORM_GENERATION_DATA_H_
+
+#include "base/strings/string16.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "url/gurl.h"
+
+namespace autofill {
+
+// Structure used for sending information from browser to renderer about on
+// which fields password should be generated.
+struct PasswordFormGenerationData {
+  // The name of the form.
+  base::string16 name;
+
+  // The action target of the form; this URL consists of the scheme, host, port
+  // and path; the rest is stripped.
+  GURL action;
+
+  // Field in which password should be generated.
+  FormFieldData generation_field;
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_FORM_GENERATION_DATA_H_
diff --git a/components/cdm/browser/cdm_message_filter_android.cc b/components/cdm/browser/cdm_message_filter_android.cc
index 14043e1..e9399f6 100644
--- a/components/cdm/browser/cdm_message_filter_android.cc
+++ b/components/cdm/browser/cdm_message_filter_android.cc
@@ -9,10 +9,11 @@
 
 #include "components/cdm/common/cdm_messages_android.h"
 #include "ipc/ipc_message_macros.h"
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_drm_bridge.h"
 
 using content::BrowserThread;
+using media::MediaCodecBridge;
 using media::MediaDrmBridge;
 using media::SupportedCodecs;
 
@@ -58,7 +59,7 @@
     if ((request.codecs & info.codec) &&
         MediaDrmBridge::IsKeySystemSupportedWithType(
             key_system, info.container_mime_type) &&
-        media::MediaCodecUtil::CanDecode(info.codec_name, is_secure)) {
+        MediaCodecBridge::CanDecode(info.codec_name, is_secure)) {
       supported_codecs |= info.codec;
     }
   }
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 4ba0143..2ff9375 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -303,6 +303,7 @@
     ],
     'invalidation_unittest_sources': [
       'invalidation/impl/fake_invalidator_unittest.cc',
+      'invalidation/impl/gcm_invalidation_bridge_unittest.cc',
       'invalidation/impl/gcm_network_channel_unittest.cc',
       'invalidation/impl/invalidation_logger_unittest.cc',
       'invalidation/impl/invalidation_notifier_unittest.cc',
@@ -646,6 +647,7 @@
       'search_engines/default_search_pref_migration_unittest.cc',
       'search_engines/desktop_search_win_unittest.cc',
       'search_engines/keyword_table_unittest.cc',
+      'search_engines/search_engine_data_type_controller_unittest.cc',
       'search_engines/search_host_to_urls_map_unittest.cc',
       'search_engines/template_url_prepopulate_data_unittest.cc',
       'search_engines/template_url_service_util_unittest.cc',
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/PkpTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/PkpTest.java
index 1b6107b..c977541 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/PkpTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/PkpTest.java
@@ -302,17 +302,20 @@
      * Asserts that the response from the server contains an PKP error.
      * TODO(kapishnikov): currently QUIC returns ERR_QUIC_PROTOCOL_ERROR instead of expected
      * ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN error code when the pin doesn't match.
-     * This method should be changed when the bug is resolved. See http://crbug.com/548378
+     * This method should be changed when the bug is resolved.
+     * See http://crbug.com/548378
+     * See http://crbug.com/568669
      */
     private void assertErrorResponse() {
         assertNotNull("Expected an error", mListener.mError);
         int errorCode = mListener.mError.netError();
-        boolean correctErrorCode = errorCode == NetError.ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN
-                || errorCode == NetError.ERR_QUIC_PROTOCOL_ERROR;
-        assertTrue(String.format("Incorrect error code. Expected %s or %s but received %s",
-                           NetError.ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN,
-                           NetError.ERR_QUIC_PROTOCOL_ERROR, errorCode),
-                correctErrorCode);
+        Set<Integer> expectedErrors = new HashSet<>();
+        expectedErrors.add(NetError.ERR_QUIC_PROTOCOL_ERROR);
+        expectedErrors.add(NetError.ERR_CONNECTION_REFUSED);
+        expectedErrors.add(NetError.ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN);
+        assertTrue(String.format("Incorrect error code. Expected one of %s but received %s",
+                           expectedErrors, errorCode),
+                expectedErrors.contains(errorCode));
     }
 
     /**
diff --git a/components/error_page/renderer/net_error_helper_core.cc b/components/error_page/renderer/net_error_helper_core.cc
index ecdeece..1061f150 100644
--- a/components/error_page/renderer/net_error_helper_core.cc
+++ b/components/error_page/renderer/net_error_helper_core.cc
@@ -10,8 +10,6 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/i18n/rtl.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_value_converter.h"
@@ -40,8 +38,6 @@
 
 namespace {
 
-#define MAX_DEBUG_HISTORY_EVENTS 50
-
 // |NetErrorNavigationCorrectionTypes| enum id for Web search query.
 // Other correction types uses the |kCorrectionResourceTable| array order.
 const int kWebSearchQueryUMAId = 100;
@@ -530,8 +526,6 @@
 }
 
 void NetErrorHelperCore::CancelPendingFetches() {
-  RecordHistoryDebugEvent(HistoryDebugEvent::CANCEL_PENDING_FETCHES);
-
   // Cancel loading the alternate error page, and prevent any pending error page
   // load from starting a new error page load.  Swapping in the error page when
   // it's finished loading could abort the navigation, otherwise.
@@ -545,8 +539,6 @@
 }
 
 void NetErrorHelperCore::OnStop() {
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_STOP);
-
   if (committed_error_page_info_ &&
       committed_error_page_info_->auto_reload_triggered) {
     ReportAutoReloadFailure(committed_error_page_info_->error,
@@ -559,8 +551,6 @@
 }
 
 void NetErrorHelperCore::OnWasShown() {
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_WAS_SHOWN);
-
   visible_ = true;
   if (!auto_reload_visible_only_)
     return;
@@ -569,8 +559,6 @@
 }
 
 void NetErrorHelperCore::OnWasHidden() {
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_WAS_HIDDEN);
-
   visible_ = false;
   if (!auto_reload_visible_only_)
     return;
@@ -581,8 +569,6 @@
   if (frame_type != MAIN_FRAME)
     return;
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_START_LOAD);
-
   uncommitted_load_started_ = true;
 
   // If there's no pending error page information associated with the page load,
@@ -595,8 +581,6 @@
   if (frame_type != MAIN_FRAME)
     return;
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_COMMIT_LOAD);
-
   // If a page is committing, either it's an error page and autoreload will be
   // started again below, or it's a success page and we need to clear autoreload
   // state.
@@ -635,20 +619,14 @@
   }
 
   committed_error_page_info_.reset(pending_error_page_info_.release());
-
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_COMMIT_LOAD_END);
 }
 
 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) {
   if (frame_type != MAIN_FRAME)
     return;
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_FINISH_LOAD);
-
   if (!committed_error_page_info_) {
     auto_reload_count_ = 0;
-    RecordHistoryDebugEvent(
-        HistoryDebugEvent::ON_FINISH_LOAD_END_NOT_ERROR_PAGE);
     return;
   }
 
@@ -694,12 +672,10 @@
 
   if (!committed_error_page_info_->needs_dns_updates ||
       last_probe_status_ == DNS_PROBE_POSSIBLE) {
-    RecordHistoryDebugEvent(HistoryDebugEvent::ON_FINISH_LOAD_END_DNS_PROBE);
     return;
   }
   DVLOG(1) << "Error page finished loading; sending saved status.";
   UpdateErrorPage();
-  RecordHistoryDebugEvent(HistoryDebugEvent::ON_FINISH_LOAD_END_NO_DNS_PROBE);
 }
 
 void NetErrorHelperCore::GetErrorHTML(FrameType frame_type,
@@ -712,7 +688,6 @@
     // cancelled earlier by starting a new page load (Which has now failed).
     DCHECK(!committed_error_page_info_ ||
            !committed_error_page_info_->needs_load_navigation_corrections);
-    RecordHistoryDebugEvent(HistoryDebugEvent::GET_ERROR_HTML);
 
     pending_error_page_info_.reset(
         new ErrorPageInfo(error, is_failed_post, is_ignoring_cache));
@@ -741,8 +716,6 @@
 void NetErrorHelperCore::OnNetErrorInfo(DnsProbeStatus status) {
   DCHECK_NE(DNS_PROBE_POSSIBLE, status);
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::NET_ERROR_INFO_RECEIVED);
-
   last_probe_status_ = status;
 
   if (!committed_error_page_info_ ||
@@ -821,8 +794,6 @@
   DCHECK(committed_error_page_info_->is_finished_loading);
   DCHECK_NE(DNS_PROBE_POSSIBLE, last_probe_status_);
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::UPDATE_ERROR_PAGE);
-
   UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus",
                             last_probe_status_,
                             DNS_PROBE_MAX);
@@ -853,8 +824,6 @@
   DCHECK(committed_error_page_info_->needs_load_navigation_corrections);
   DCHECK(committed_error_page_info_->navigation_correction_params);
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::NAVIGATION_CORRECTIONS_FETCHED);
-
   pending_error_page_info_.reset(new ErrorPageInfo(
       committed_error_page_info_->error,
       committed_error_page_info_->was_failed_post,
@@ -918,8 +887,6 @@
 }
 
 void NetErrorHelperCore::Reload(bool ignore_cache) {
-  RecordHistoryDebugEvent(HistoryDebugEvent::RELOAD);
-
   if (!committed_error_page_info_) {
     return;
   }
@@ -927,8 +894,6 @@
 }
 
 bool NetErrorHelperCore::MaybeStartAutoReloadTimer() {
-  RecordHistoryDebugEvent(HistoryDebugEvent::MAYBE_RELOAD);
-
   if (!committed_error_page_info_ ||
       !committed_error_page_info_->is_finished_loading ||
       pending_error_page_info_ ||
@@ -944,12 +909,9 @@
   DCHECK(committed_error_page_info_);
   DCHECK(IsReloadableError(*committed_error_page_info_));
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::START_RELOAD_TIMER);
-
   committed_error_page_info_->auto_reload_triggered = true;
 
   if (!online_ || (!visible_ && auto_reload_visible_only_)) {
-    RecordHistoryDebugEvent(HistoryDebugEvent::START_RELOAD_TIMER_PAUSED);
     auto_reload_paused_ = true;
     return;
   }
@@ -970,29 +932,12 @@
   //    auto-reload timer.
   DCHECK(committed_error_page_info_);
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::RELOAD_TIMER_FIRED);
-
   auto_reload_count_++;
   auto_reload_in_flight_ = true;
-
-  if (!committed_error_page_info_) {
-    HistoryDebugEvent history_debug_events[MAX_DEBUG_HISTORY_EVENTS];
-    size_t num_history_debug_events = history_debug_events_.size();
-    for (size_t i = 0; i < num_history_debug_events; ++i) {
-      history_debug_events[i] = history_debug_events_[i];
-    }
-    base::debug::Alias(history_debug_events);
-    base::debug::Alias(&num_history_debug_events);
-    base::debug::DumpWithoutCrashing();
-    return;
-  }
-
   Reload(committed_error_page_info_->was_ignoring_cache);
 }
 
 void NetErrorHelperCore::PauseAutoReloadTimer() {
-  RecordHistoryDebugEvent(HistoryDebugEvent::PAUSE_RELOAD_TIMER);
-
   if (!auto_reload_timer_->IsRunning())
     return;
   DCHECK(committed_error_page_info_);
@@ -1003,8 +948,6 @@
 }
 
 void NetErrorHelperCore::NetworkStateChanged(bool online) {
-  RecordHistoryDebugEvent(HistoryDebugEvent::NETWORK_STATE_CHANGED);
-
   bool was_online = online_;
   online_ = online;
   if (!was_online && online) {
@@ -1025,8 +968,6 @@
   if (frame_type != MAIN_FRAME)
     return false;
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::SHOULD_SUPPRESS_ERROR_PAGE);
-
   // If there's no auto reload attempt in flight, this error page didn't come
   // from auto reload, so don't suppress it.
   if (!auto_reload_in_flight_)
@@ -1045,8 +986,6 @@
   // If there's no committed error page, should not be invoked.
   DCHECK(committed_error_page_info_);
 
-  RecordHistoryDebugEvent(HistoryDebugEvent::EXECUTE_BUTTON_PRESS);
-
   switch (button) {
     case RELOAD_BUTTON:
       RecordEvent(NETWORK_ERROR_PAGE_RELOAD_BUTTON_CLICKED);
@@ -1141,16 +1080,4 @@
 #endif  // defined(OS_ANDROID)
 }
 
-void NetErrorHelperCore::RecordHistoryDebugEvent(
-    HistoryDebugEvent::EventType event_type) {
-  if (history_debug_events_.size() > MAX_DEBUG_HISTORY_EVENTS)
-    history_debug_events_.erase(history_debug_events_.begin());
-  HistoryDebugEvent event;
-  event.event_type = event_type;
-  event.pending_error_page_info_exists = !!pending_error_page_info_;
-  event.committed_error_page_info_exists = !!committed_error_page_info_;
-  event.timer_running = auto_reload_timer_->IsRunning();
-  history_debug_events_.push_back(event);
-}
-
 }  // namespace error_page
diff --git a/components/error_page/renderer/net_error_helper_core.h b/components/error_page/renderer/net_error_helper_core.h
index e95b221..0d955513 100644
--- a/components/error_page/renderer/net_error_helper_core.h
+++ b/components/error_page/renderer/net_error_helper_core.h
@@ -6,7 +6,6 @@
 #define COMPONENTS_ERROR_PAGE_RENDERER_NET_ERROR_HELPER_CORE_H_
 
 #include <string>
-#include <vector>
 
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
@@ -226,43 +225,6 @@
  private:
   struct ErrorPageInfo;
 
-  // Represents an event that has occured, and the initial state of the
-  // NetErrorHelperCore when it occured.
-  // TODO(mmenke): Remove once https://crbug.com/557541 is fixed.
-  struct HistoryDebugEvent {
-    enum EventType {
-      GET_ERROR_HTML = 0,
-      ON_START_LOAD = 1,
-      ON_COMMIT_LOAD = 2,
-      ON_COMMIT_LOAD_END = 3,
-      ON_FINISH_LOAD = 4,
-      ON_FINISH_LOAD_END_NOT_ERROR_PAGE = 5,
-      ON_FINISH_LOAD_END_DNS_PROBE = 6,
-      ON_FINISH_LOAD_END_NO_DNS_PROBE = 7,
-      ON_STOP = 8,
-      ON_WAS_SHOWN = 9,
-      ON_WAS_HIDDEN = 10,
-      CANCEL_PENDING_FETCHES = 11,
-      NAVIGATION_CORRECTIONS_FETCHED = 12,
-      NET_ERROR_INFO_RECEIVED = 13,
-      NETWORK_STATE_CHANGED = 14,
-      SHOULD_SUPPRESS_ERROR_PAGE = 15,
-      EXECUTE_BUTTON_PRESS = 16,
-      MAYBE_RELOAD = 17,
-      RELOAD = 18,
-      START_RELOAD_TIMER = 19,
-      RELOAD_TIMER_FIRED = 20,
-      PAUSE_RELOAD_TIMER = 21,
-      UPDATE_ERROR_PAGE = 22,
-      START_RELOAD_TIMER_PAUSED = 23,
-    };
-
-    EventType event_type;
-    bool pending_error_page_info_exists;
-    bool committed_error_page_info_exists;
-    bool timer_running;
-  };
-
   // Gets HTML for a main frame error page.  Depending on
   // |pending_error_page_info|, may use the navigation correction service, or
   // show a DNS probe error page.  May modify |pending_error_page_info|.
@@ -286,11 +248,6 @@
 
   static bool IsReloadableError(const ErrorPageInfo& info);
 
-  // Adds the specified event, along with information about the current state of
-  // |this|, to |history_|.
-  // TODO(mmenke): Remove once https://crbug.com/557541 is fixed.
-  void RecordHistoryDebugEvent(HistoryDebugEvent::EventType event_type);
-
   Delegate* delegate_;
 
   // The last DnsProbeStatus received from the browser.
@@ -351,10 +308,6 @@
   // the error page.  It is used to detect when such navigations result
   // in errors.
   Button navigation_from_button_;
-
-  // Record of the most recent events that have occurred.
-  // TODO(mmenke): Remove once https://crbug.com/557541 is fixed.
-  std::vector<HistoryDebugEvent> history_debug_events_;
 };
 
 }  // namespace error_page
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer.cc b/components/gcm_driver/crypto/gcm_message_cryptographer.cc
index 574a2576..076b9f96 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer.cc
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer.cc
@@ -87,7 +87,7 @@
 GCMMessageCryptographer::~GCMMessageCryptographer() {}
 
 bool GCMMessageCryptographer::Encrypt(const base::StringPiece& plaintext,
-                                      const base::StringPiece& key,
+                                      const base::StringPiece& ikm,
                                       const base::StringPiece& salt,
                                       size_t* record_size,
                                       std::string* ciphertext) const {
@@ -97,10 +97,10 @@
   if (salt.size() != kSaltSize)
     return false;
 
-  std::string ikm = DeriveInputKeyingMaterial(key);
+  std::string prk = DerivePseudoRandomKey(ikm);
 
-  std::string content_encryption_key = DeriveContentEncryptionKey(ikm, salt);
-  std::string nonce = DeriveNonce(ikm, salt);
+  std::string content_encryption_key = DeriveContentEncryptionKey(prk, salt);
+  std::string nonce = DeriveNonce(prk, salt);
 
   // draft-thomson-http-encryption allows between 0 and 255 octets of padding to
   // be inserted before the enciphered content, with the length of the padding
@@ -126,7 +126,7 @@
 }
 
 bool GCMMessageCryptographer::Decrypt(const base::StringPiece& ciphertext,
-                                      const base::StringPiece& key,
+                                      const base::StringPiece& ikm,
                                       const base::StringPiece& salt,
                                       size_t record_size,
                                       std::string* plaintext) const {
@@ -144,10 +144,10 @@
     return false;
   }
 
-  std::string ikm = DeriveInputKeyingMaterial(key);
+  std::string prk = DerivePseudoRandomKey(ikm);
 
-  std::string content_encryption_key = DeriveContentEncryptionKey(ikm, salt);
-  std::string nonce = DeriveNonce(ikm, salt);
+  std::string content_encryption_key = DeriveContentEncryptionKey(prk, salt);
+  std::string nonce = DeriveNonce(prk, salt);
 
   std::string decrypted_record;
   if (!EncryptDecryptRecordInternal(DECRYPT, ciphertext, content_encryption_key,
@@ -178,15 +178,18 @@
   return true;
 }
 
-std::string GCMMessageCryptographer::DeriveInputKeyingMaterial(
-    const base::StringPiece& key) const {
+std::string GCMMessageCryptographer::DerivePseudoRandomKey(
+    const base::StringPiece& ikm) const {
   if (allow_empty_auth_secret_for_tests_ && auth_secret_.empty())
-    return key.as_string();
+    return ikm.as_string();
 
   CHECK(!auth_secret_.empty());
 
-  crypto::HKDF hkdf(key, auth_secret_,
-                    "Content-Encoding: auth",
+  std::stringstream info_stream;
+  info_stream << "Content-Encoding: auth" << '\x00';
+
+  crypto::HKDF hkdf(ikm, auth_secret_,
+                    info_stream.str(),
                     32, /* key_bytes_to_generate */
                     0,  /* iv_bytes_to_generate */
                     0   /* subkey_secret_bytes_to_generate */);
@@ -195,9 +198,9 @@
 }
 
 std::string GCMMessageCryptographer::DeriveContentEncryptionKey(
-    const base::StringPiece& key,
+    const base::StringPiece& prk,
     const base::StringPiece& salt) const {
-  crypto::HKDF hkdf(key, salt,
+  crypto::HKDF hkdf(prk, salt,
                     content_encryption_key_info_,
                     kContentEncryptionKeySize,
                     0,  /* iv_bytes_to_generate */
@@ -207,9 +210,9 @@
 }
 
 std::string GCMMessageCryptographer::DeriveNonce(
-    const base::StringPiece& key,
+    const base::StringPiece& prk,
     const base::StringPiece& salt) const {
-  crypto::HKDF hkdf(key, salt,
+  crypto::HKDF hkdf(prk, salt,
                     nonce_info_,
                     kNonceSize,
                     0,  /* iv_bytes_to_generate */
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer.h b/components/gcm_driver/crypto/gcm_message_cryptographer.h
index de74cd3a..821c2af 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer.h
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer.h
@@ -50,22 +50,22 @@
 
   ~GCMMessageCryptographer();
 
-  // Encrypts |plaintext| using the |key| and the |salt|, both of which must be
+  // Encrypts |plaintext| using the |ikm| and the |salt|, both of which must be
   // 16 octets in length. The |plaintext| will be written to a single record,
   // and will include a 16 octet authentication tag. The encrypted result will
   // be written to |ciphertext|, the record size to |record_size|. This
   // implementation does not support prepending padding to the |plaintext|.
   bool Encrypt(const base::StringPiece& plaintext,
-               const base::StringPiece& key,
+               const base::StringPiece& ikm,
                const base::StringPiece& salt,
                size_t* record_size,
                std::string* ciphertext) const WARN_UNUSED_RESULT;
 
-  // Decrypts |ciphertext| using the |key| and the |salt|, both of which must be
+  // Decrypts |ciphertext| using the |ikm| and the |salt|, both of which must be
   // 16 octets in length. The result will be stored in |plaintext|. Note that
   // there must only be a single record, per draft-thomson-http-encryption-01.
   bool Decrypt(const base::StringPiece& ciphertext,
-               const base::StringPiece& key,
+               const base::StringPiece& ikm,
                const base::StringPiece& salt,
                size_t record_size,
                std::string* plaintext) const WARN_UNUSED_RESULT;
@@ -89,17 +89,17 @@
                                     const base::StringPiece& nonce,
                                     std::string* output) const;
 
-  // Derives the input keying material (IKM) to use for deriving the content
+  // Derives the pseuro random key (PRK) to use for deriving the content
   // encryption key and the nonce. If |auth_secret_| is not the empty string,
   // another HKDF will be invoked between the |key| and the |auth_secret_|.
-  std::string DeriveInputKeyingMaterial(const base::StringPiece& key) const;
+  std::string DerivePseudoRandomKey(const base::StringPiece& ikm) const;
 
-  // Derives the content encryption key from |key| and |salt|.
-  std::string DeriveContentEncryptionKey(const base::StringPiece& key,
+  // Derives the content encryption key from |prk| and |salt|.
+  std::string DeriveContentEncryptionKey(const base::StringPiece& prk,
                                          const base::StringPiece& salt) const;
 
-  // Derives the nonce from |key| and |salt|.
-  std::string DeriveNonce(const base::StringPiece& key,
+  // Derives the nonce from |prk| and |salt|.
+  std::string DeriveNonce(const base::StringPiece& prk,
                           const base::StringPiece& salt) const;
 
   // The info parameters to the HKDFs used for deriving the content encryption
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc b/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc
index 878f5dc3..e7975ef 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc
@@ -50,14 +50,14 @@
     "AhA6n2oFYPWIh-cXwyv1m2C0JvmjHB4ZkXj8QylESXU",
     "tsJYqAGvFDk6lDEv7daecw",
     4096,
-    "NFivl-fJJkKHJPvHlDM3P6SHyBdmr5Caqxm1m-Is"
+    "x9jT8FN0cy3GX906plTF_K52znY5ZMo0lqMEN90c"
    },
    // Empty message.
    { "",
     "lMyvTong4VR053jfCpWmMDGW5dEDAqiTZUIU-inhTjU",
     "wH3uvZqcN6oey9whiGpn1A",
     4096,
-    "Pnoyj0pZJ0daULfQFPWUlBA"
+    "KNXWPR0Sx1jc3NW4JDPQKlw"
    },
    // Message with an invalid salt size.
    { "Hello, world!",
@@ -70,21 +70,21 @@
 
 const TestVector kDecryptionTestVectors[] = {
   // Simple message.
-  { "o7t04QCaL2YHs_UQWqJo_4RZ8rnLCJsoQeAGbvVv",
+  { "lqMcX_o8HrRu3v9F9w4Cwk_fCiYmmTRCcatQdpQk",
     "47ZytAw9qHlm-Q8g-7rH81rUPzaCgGcoFvlS1qxQtQk",
     "EuR7EVetcaWpndXd_dKeyA",
     4096,
     "Hello, world!"
    },
    // Simple message with 16 bytes of padding.
-   { "mCKryg4tyVSkEM5B5fmV8FzTcMvzB3a8PRii3SY3uM8nXOc4yLpB0XgXjnDKbw",
+   { "2sdvDvwlda33AMQEjtTdPqfb0RINM710Pabe_zQ3H8DO4ca5P7iy6Xh_9ZOqXQ",
      "MYSsNybwrTzRIzQYUq_yFPc6ugcTrJdEZJDM4NswvUg",
      "8sEAMQYnufo2UkKl80cUGQ",
      4096,
      "Hello, world!"
    },
    // Empty message.
-   { "k27iDM90-Jmc6q5Eb9Nx2IM",
+   { "Px1lQsFDdDrTomks7GYRvts",
      "S3-Ki_-XtzR66gUp_zR75CC5JXO62pyr5fWfneTYwFE",
      "4RM6s19jJHdmqiVEJDp9jg",
      4096,
@@ -223,10 +223,10 @@
 
   const std::string salt = GenerateRandomSalt();
 
-  const std::string ikm = cryptographer()->DeriveInputKeyingMaterial(key());
-  const std::string nonce = cryptographer()->DeriveNonce(ikm, salt);
+  const std::string prk = cryptographer()->DerivePseudoRandomKey(key());
+  const std::string nonce = cryptographer()->DeriveNonce(prk, salt);
   const std::string content_encryption_key =
-      cryptographer()->DeriveContentEncryptionKey(ikm, salt);
+      cryptographer()->DeriveContentEncryptionKey(prk, salt);
 
   ASSERT_GT(message.size(), 1u);
   const size_t record_size = message.size() + 1;
@@ -334,7 +334,7 @@
       kLocalPublicKeyCommon, base::Base64UrlDecodePolicy::IGNORE_PADDING,
       &public_key));
 
-  // Fake IKM to use in the DeriveInputKeyingMaterial calls.
+  // Fake IKM to use in the DerivePseudoRandomKey calls.
   const char kFakeIKM[] = "HelloWorld";
 
   GCMMessageCryptographer hello_cryptographer(
@@ -343,11 +343,11 @@
   GCMMessageCryptographer world_cryptographer(
       GCMMessageCryptographer::Label::P256, public_key, public_key, "World");
 
-  ASSERT_NE(hello_cryptographer.DeriveInputKeyingMaterial(kFakeIKM), kFakeIKM);
-  ASSERT_NE(world_cryptographer.DeriveInputKeyingMaterial(kFakeIKM), kFakeIKM);
+  ASSERT_NE(hello_cryptographer.DerivePseudoRandomKey(kFakeIKM), kFakeIKM);
+  ASSERT_NE(world_cryptographer.DerivePseudoRandomKey(kFakeIKM), kFakeIKM);
 
-  ASSERT_NE(hello_cryptographer.DeriveInputKeyingMaterial(kFakeIKM),
-            world_cryptographer.DeriveInputKeyingMaterial(kFakeIKM));
+  ASSERT_NE(hello_cryptographer.DerivePseudoRandomKey(kFakeIKM),
+            world_cryptographer.DerivePseudoRandomKey(kFakeIKM));
 
   std::string salt = GenerateRandomSalt();
 
diff --git a/components/html_viewer/media_factory.cc b/components/html_viewer/media_factory.cc
index 64426c1..cec7ae879 100644
--- a/components/html_viewer/media_factory.cc
+++ b/components/html_viewer/media_factory.cc
@@ -29,6 +29,7 @@
 #include "mojo/application/public/cpp/connect.h"
 #include "mojo/application/public/interfaces/shell.mojom.h"
 #include "third_party/WebKit/public/web/WebKit.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "v8/include/v8.h"
 
 namespace html_viewer {
@@ -105,9 +106,13 @@
       GetMediaPermission(), initial_cdm);
   base::WeakPtr<media::WebMediaPlayerDelegate> delegate;
 
+  if (!url_index_.get() || url_index_->frame() != frame) {
+    url_index_.reset(new media::UrlIndex(frame));
+  }
+
   return new media::WebMediaPlayerImpl(frame, client, encrypted_client,
                                        delegate, media_renderer_factory.Pass(),
-                                       GetCdmFactory(), params);
+                                       GetCdmFactory(), url_index_, params);
 #endif  // defined(OS_ANDROID)
 }
 
diff --git a/components/html_viewer/media_factory.h b/components/html_viewer/media_factory.h
index edae380..804eddf 100644
--- a/components/html_viewer/media_factory.h
+++ b/components/html_viewer/media_factory.h
@@ -6,11 +6,13 @@
 #define COMPONENTS_HTML_VIEWER_MEDIA_FACTORY_H_
 
 #include "base/macros.h"
+#include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/thread.h"
 #include "media/audio/fake_audio_log_factory.h"
 #include "media/base/audio_hardware_config.h"
+#include "media/blink/url_index.h"
 #include "media/mojo/interfaces/service_factory.mojom.h"
 #include "mojo/application/public/interfaces/service_provider.mojom.h"
 
@@ -33,6 +35,7 @@
 class RestartableAudioRendererSink;
 class CdmFactory;
 class MediaPermission;
+class UrlIndex;
 class WebEncryptedMediaClientImpl;
 }
 
@@ -89,6 +92,9 @@
   scoped_ptr<media::MediaPermission> media_permission_;
   scoped_ptr<media::CdmFactory> cdm_factory_;
 
+  // Media resource cache, lazily initialized.
+  linked_ptr<media::UrlIndex> url_index_;
+
   DISALLOW_COPY_AND_ASSIGN(MediaFactory);
 };
 
diff --git a/components/invalidation/impl/BUILD.gn b/components/invalidation/impl/BUILD.gn
index 23cde27..00416a7 100644
--- a/components/invalidation/impl/BUILD.gn
+++ b/components/invalidation/impl/BUILD.gn
@@ -119,6 +119,7 @@
     # Non-Android tests.
     sources += [
       "fake_invalidator_unittest.cc",
+      "gcm_invalidation_bridge_unittest.cc",
       "gcm_network_channel_unittest.cc",
       "invalidation_notifier_unittest.cc",
       "invalidator_registrar_unittest.cc",
@@ -138,7 +139,9 @@
     deps += [
       "//components/gcm_driver:test_support",
       "//components/pref_registry:test_support",
+      "//components/signin/core/browser:test_support",
       "//google_apis:test_support",
+      "//net",
     ]
   }
 }
diff --git a/components/invalidation/impl/DEPS b/components/invalidation/impl/DEPS
index 5fb7f26..c8f5ee18 100644
--- a/components/invalidation/impl/DEPS
+++ b/components/invalidation/impl/DEPS
@@ -12,6 +12,7 @@
   "+jni",
   "+jingle/notifier",
   "+net/base/backoff_entry.h",
+  "+net/base/ip_endpoint.h",
   "+net/base/network_change_notifier.h",
   "+net/http/http_status_code.h",
   "+net/url_request",
diff --git a/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc b/components/invalidation/impl/gcm_invalidation_bridge_unittest.cc
similarity index 77%
rename from chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc
rename to components/invalidation/impl/gcm_invalidation_bridge_unittest.cc
index 6f608ab..2d434bf0 100644
--- a/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc
+++ b/components/invalidation/impl/gcm_invalidation_bridge_unittest.cc
@@ -2,23 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/invalidation/impl/gcm_invalidation_bridge.h"
+
+#include "base/bind.h"
 #include "base/location.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
-#include "chrome/browser/signin/account_fetcher_service_factory.h"
-#include "chrome/browser/signin/chrome_signin_client_factory.h"
-#include "chrome/browser/signin/fake_account_fetcher_service_builder.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/test_signin_client_builder.h"
-#include "chrome/test/base/testing_profile.h"
 #include "components/gcm_driver/fake_gcm_driver.h"
 #include "components/gcm_driver/gcm_driver.h"
-#include "components/invalidation/impl/gcm_invalidation_bridge.h"
-#include "components/signin/core/browser/fake_account_fetcher_service.h"
 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/fake_identity_provider.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/base/ip_endpoint.h"
@@ -57,22 +50,12 @@
   ~GCMInvalidationBridgeTest() override {}
 
   void SetUp() override {
-    TestingProfile::Builder builder;
-    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                              &BuildAutoIssuingFakeProfileOAuth2TokenService);
-    builder.AddTestingFactory(AccountFetcherServiceFactory::GetInstance(),
-                              FakeAccountFetcherServiceBuilder::BuildForTests);
-    builder.AddTestingFactory(ChromeSigninClientFactory::GetInstance(),
-                              signin::BuildTestSigninClient);
-    profile_ = builder.Build();
-
-    FakeProfileOAuth2TokenService* token_service =
-        (FakeProfileOAuth2TokenService*)
-        ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
-    token_service->UpdateCredentials("", "fake_refresh_token");
+    token_service_.reset(new FakeProfileOAuth2TokenService());
+    token_service_->set_auto_post_fetch_response_on_message_loop(true);
+    token_service_->UpdateCredentials("", "fake_refresh_token");
     gcm_driver_.reset(new CustomFakeGCMDriver());
 
-    identity_provider_.reset(new FakeIdentityProvider(token_service));
+    identity_provider_.reset(new FakeIdentityProvider(token_service_.get()));
     bridge_.reset(new GCMInvalidationBridge(gcm_driver_.get(),
                                             identity_provider_.get()));
 
@@ -104,8 +87,8 @@
     connection_online_ = online;
   }
 
-  content::TestBrowserThreadBundle thread_bundle_;
-  scoped_ptr<Profile> profile_;
+  base::MessageLoop message_loop_;
+  scoped_ptr<FakeProfileOAuth2TokenService> token_service_;
   scoped_ptr<gcm::GCMDriver> gcm_driver_;
   scoped_ptr<FakeIdentityProvider> identity_provider_;
 
diff --git a/components/nacl.gyp b/components/nacl.gyp
index e90fa16..a9ed69c 100644
--- a/components/nacl.gyp
+++ b/components/nacl.gyp
@@ -63,6 +63,7 @@
     ['disable_nacl!=1', {
       'targets': [
         {
+          # GN version: //components/nacl/loader
           'target_name': 'nacl',
           'type': 'static_library',
           'variables': {
@@ -87,6 +88,7 @@
           ],
         },
         {
+          # GN version: //components/nacl/browser
           'target_name': 'nacl_browser',
           'type': 'static_library',
           'sources': [
@@ -140,6 +142,7 @@
           ],
         },
         {
+          # GN version: //components/nacl/renderer
           'target_name': 'nacl_renderer',
           'type': 'static_library',
           'sources': [
@@ -179,6 +182,7 @@
           ],
         },
         {
+          # GN version: //components/nacl/loader:nacl_loader_unittests
           'target_name': 'nacl_loader_unittests',
           'type': '<(gtest_target_type)',
           'sources': [
@@ -198,6 +202,7 @@
         ['OS=="linux"', {
           'targets': [
             {
+              # GN version: //components/nacl/loader:nacl_helper
               'target_name': 'nacl_helper',
               'type': 'executable',
               'include_dirs': [
@@ -221,6 +226,7 @@
                 'ldflags': ['-pie'],
               },
             }, {
+              # GN version: //components/nacl/loader/sandbox_linux
               'target_name': 'nacl_linux',
               'type': 'static_library',
               'include_dirs': [
@@ -308,6 +314,7 @@
               },
             },
             {
+              # GN version: //components/nacl/common:switches
               'target_name': 'nacl_switches_win64',
               'type': 'static_library',
               'sources': [
@@ -324,6 +331,7 @@
               },
             },
             {
+              # GN version: //components/nacl/common
               'target_name': 'nacl_common_win64',
               'type': 'static_library',
               'defines': [
@@ -416,6 +424,7 @@
   ],
   'targets': [
     {
+      # GN version: //components/nacl/common:switches
       'target_name': 'nacl_switches',
       'type': 'static_library',
       'sources': [
@@ -427,6 +436,7 @@
       ],
     },
     {
+      # GN version: //components/nacl/common
       'target_name': 'nacl_common',
       'type': 'static_library',
       'sources': [
diff --git a/components/nacl/BUILD.gn b/components/nacl/BUILD.gn
deleted file mode 100644
index 7e20ecc0..0000000
--- a/components/nacl/BUILD.gn
+++ /dev/null
@@ -1,374 +0,0 @@
-# Copyright (c) 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/features.gni")
-import("//build/config/nacl/config.gni")
-import("//build/config/ui.gni")
-import("//testing/test.gni")
-
-if (enable_nacl) {
-  source_set("nacl") {
-    sources = [
-      "loader/nacl_ipc_adapter.cc",
-      "loader/nacl_ipc_adapter.h",
-      "loader/nacl_listener.cc",
-      "loader/nacl_listener.h",
-      "loader/nacl_main.cc",
-      "loader/nacl_main_platform_delegate.h",
-      "loader/nacl_main_platform_delegate_linux.cc",
-      "loader/nacl_main_platform_delegate_mac.mm",
-      "loader/nacl_main_platform_delegate_win.cc",
-      "loader/nacl_trusted_listener.cc",
-      "loader/nacl_trusted_listener.h",
-      "loader/nacl_validation_db.h",
-      "loader/nacl_validation_query.cc",
-      "loader/nacl_validation_query.h",
-    ]
-
-    deps = [
-      ":nacl_common",
-      ":nacl_switches",
-      "//base",
-      "//base:base_static",
-      "//content/public/common",
-      "//crypto",
-      "//ipc",
-      "//native_client/src/trusted/service_runtime:sel_main_chrome",
-      "//ppapi/c",
-      "//ppapi/proxy:ipc",
-      "//ppapi/shared_impl",
-      "//sandbox",
-      "//third_party/mojo/src/mojo/edk/system",
-    ]
-
-    if (enable_nacl_untrusted) {
-      data_deps = [
-        "//ppapi/native_client:irt",
-      ]
-    }
-    if (enable_pnacl) {
-      data_deps +=
-          [ "//ppapi/native_client/src/untrusted/pnacl_support_extension" ]
-    }
-  }
-
-  source_set("nacl_browser") {
-    sources = [
-      "browser/bad_message.cc",
-      "browser/bad_message.h",
-      "browser/nacl_broker_host_win.cc",
-      "browser/nacl_broker_host_win.h",
-      "browser/nacl_broker_service_win.cc",
-      "browser/nacl_broker_service_win.h",
-      "browser/nacl_browser.cc",
-      "browser/nacl_browser.h",
-      "browser/nacl_file_host.cc",
-      "browser/nacl_file_host.h",
-      "browser/nacl_host_message_filter.cc",
-      "browser/nacl_host_message_filter.h",
-      "browser/nacl_process_host.cc",
-      "browser/nacl_process_host.h",
-      "browser/nacl_validation_cache.cc",
-      "browser/nacl_validation_cache.h",
-      "browser/pnacl_host.cc",
-      "browser/pnacl_host.h",
-      "browser/pnacl_translation_cache.cc",
-      "browser/pnacl_translation_cache.h",
-      "common/nacl_debug_exception_handler_win.cc",
-      "common/nacl_debug_exception_handler_win.h",
-    ]
-
-    deps = [
-      ":nacl_common",
-      ":nacl_switches",
-      "//base",
-      "//base/third_party/dynamic_annotations",
-      "//components/url_formatter",
-      "//content/public/browser",
-      "//content/public/common",
-      "//ipc",
-      "//native_client/src/trusted/service_runtime:sel_main_chrome",
-      "//net",
-      "//ppapi/host",
-      "//ppapi/proxy:ipc",
-      "//ppapi/shared_impl",
-    ]
-
-    data_deps = []
-
-    if (is_linux) {
-      sources += [
-        "zygote/nacl_fork_delegate_linux.cc",
-        "zygote/nacl_fork_delegate_linux.h",
-      ]
-
-      deps += [
-        ":nacl_helper_integration",
-        "//sandbox/linux:sandbox_services",
-        "//sandbox/linux:suid_sandbox_client",
-      ]
-
-      data_deps += [ ":helper_nonsfi" ]
-    }
-  }
-
-  source_set("nacl_renderer") {
-    sources = [
-      "renderer/file_downloader.cc",
-      "renderer/file_downloader.h",
-      "renderer/histogram.cc",
-      "renderer/histogram.h",
-      "renderer/json_manifest.cc",
-      "renderer/json_manifest.h",
-      "renderer/manifest_downloader.cc",
-      "renderer/manifest_downloader.h",
-      "renderer/manifest_service_channel.cc",
-      "renderer/manifest_service_channel.h",
-      "renderer/nacl_helper.cc",
-      "renderer/nacl_helper.h",
-      "renderer/nexe_load_manager.cc",
-      "renderer/nexe_load_manager.h",
-      "renderer/platform_info.cc",
-      "renderer/platform_info.h",
-      "renderer/pnacl_translation_resource_host.cc",
-      "renderer/pnacl_translation_resource_host.h",
-      "renderer/ppb_nacl_private_impl.cc",
-      "renderer/ppb_nacl_private_impl.h",
-      "renderer/progress_event.cc",
-      "renderer/progress_event.h",
-      "renderer/trusted_plugin_channel.cc",
-      "renderer/trusted_plugin_channel.h",
-    ]
-
-    deps = [
-      ":nacl_common",
-      ":nacl_switches",
-      "renderer/plugin:nacl_trusted_plugin",
-      "//base",
-      "//content/public/common",
-      "//content/public/renderer",
-      "//ipc",
-      "//net",
-      "//ppapi/c",
-      "//ppapi/proxy:ipc",
-      "//ppapi/shared_impl",
-      "//third_party/WebKit/public:blink",
-    ]
-  }
-
-  # TODO(GYP): Delete this after we've converted everything to GN.
-  # The _run targets exist only for compatibility w/ GYP.
-  group("nacl_loader_unittests_run") {
-    testonly = true
-    deps = [
-      ":nacl_loader_unittests",
-    ]
-  }
-
-  test("nacl_loader_unittests") {
-    sources = [
-      "loader/nacl_ipc_adapter_unittest.cc",
-      "loader/nacl_validation_query_unittest.cc",
-      "loader/run_all_unittests.cc",
-    ]
-
-    deps = [
-      ":nacl",
-      "//base/test:test_support",
-      "//ipc:test_support",
-      "//ppapi/c",
-      "//testing/gtest",
-    ]
-  }
-
-  if (is_linux) {
-    executable("nacl_helper") {
-      sources = [
-        "loader/nacl_helper_linux.cc",
-        "loader/nacl_helper_linux.h",
-      ]
-
-      deps = [
-        ":nacl",
-        ":nacl_linux",
-        ":nacl_switches",
-        "//base",
-        "//build/config/sanitizers:deps",
-        "//content/public/common",
-        "//crypto",
-        "//ipc",
-        "//sandbox/linux:sandbox_services",
-      ]
-
-      cflags = [ "-fPIE" ]
-
-      ldflags = [ "-pie" ]
-
-      data_deps = [
-        "//native_client/src/trusted/service_runtime/linux:bootstrap",
-      ]
-    }
-
-    # For setting up nacl_helper.
-    source_set("nacl_helper_integration") {
-      public = [
-        "loader/nacl_helper_linux.h",
-      ]
-      data_deps = [
-        ":nacl_helper",
-      ]
-    }
-
-    source_set("nacl_linux") {
-      sources = [
-        "loader/sandbox_linux/nacl_bpf_sandbox_linux.cc",
-        "loader/sandbox_linux/nacl_sandbox_linux.cc",
-      ]
-
-      defines = [ "IN_NACL_HELPER=1" ]
-
-      deps = [
-        ":nacl",
-        ":nacl_common",
-        ":nacl_switches",
-        "//base",
-        "//content/public/common",
-        "//crypto",
-        "//ipc",
-        "//sandbox",
-        "//sandbox/linux:sandbox_services_headers",
-      ]
-
-      if (use_glib) {
-        configs += [ "//build/config/linux:glib" ]
-      }
-
-      if (use_seccomp_bpf) {
-        defines += [ "USE_SECCOMP_BPF" ]
-      }
-    }
-  }
-
-  if (is_nacl_nonsfi) {
-    executable("nacl_helper_nonsfi_nexe") {
-      output_name = "nacl_helper_nonsfi"
-      set_sources_assignment_filter([])
-      sources = [
-        "common/nacl_messages.cc",
-        "common/nacl_messages.h",
-        "common/nacl_types.cc",
-        "common/nacl_types.h",
-        "common/nacl_types_param_traits.cc",
-        "common/nacl_types_param_traits.h",
-        "loader/nacl_helper_linux.cc",
-        "loader/nacl_helper_linux.h",
-        "loader/nacl_trusted_listener.cc",
-        "loader/nacl_trusted_listener.h",
-        "loader/nonsfi/nonsfi_listener.cc",
-        "loader/nonsfi/nonsfi_listener.h",
-        "loader/nonsfi/nonsfi_main.cc",
-        "loader/nonsfi/nonsfi_main.h",
-      ]
-      deps = [
-        ":nacl_helper_nonsfi_sandbox",
-        ":nacl_switches",
-        "//base",
-        "//components/tracing",
-        "//content",
-        "//ipc",
-        "//native_client/src/nonsfi/irt:nacl_sys_private",
-        "//native_client/src/nonsfi/loader:elf_loader",
-        "//native_client/src/untrusted/nacl:nacl",
-        "//ppapi/proxy",
-        "//sandbox/linux:sandbox",
-      ]
-    }
-
-    source_set("nacl_helper_nonsfi_sandbox") {
-      set_sources_assignment_filter([])
-      sources = [
-        "loader/nonsfi/nonsfi_sandbox.cc",
-        "loader/nonsfi/nonsfi_sandbox.h",
-        "loader/sandbox_linux/nacl_sandbox_linux.cc",
-        "loader/sandbox_linux/nacl_sandbox_linux.h",
-      ]
-      deps = [
-        ":nacl_switches",
-        "//base",
-        "//content",
-        "//sandbox/linux:sandbox",
-        "//sandbox/linux:sandbox_services_headers",
-      ]
-    }
-
-    copy("nacl_helper_nonsfi_copy") {
-      sources = [
-        "${root_out_dir}/nacl_helper_nonsfi",
-      ]
-      outputs = [
-        "${root_build_dir}/{{source_file_part}}",
-      ]
-      deps = [
-        ":nacl_helper_nonsfi_nexe",
-      ]
-    }
-  }
-
-  group("helper_nonsfi") {
-    deps = [
-      ":nacl_helper_nonsfi_copy(//build/toolchain/nacl:newlib_pnacl_nonsfi)",
-    ]
-  }
-}
-
-# TODO(brettw) move to //components/nacl/common:switches
-source_set("nacl_switches") {
-  sources = [
-    "common/nacl_switches.cc",
-    "common/nacl_switches.h",
-  ]
-}
-
-# TODO(brettw) move to //components/nacl/common
-source_set("nacl_common") {
-  sources = [
-    "common/nacl_cmd_line.cc",
-    "common/nacl_cmd_line.h",
-    "common/nacl_constants.cc",
-    "common/nacl_constants.h",
-    "common/nacl_host_messages.cc",
-    "common/nacl_host_messages.h",
-    "common/nacl_messages.cc",
-    "common/nacl_messages.h",
-    "common/nacl_nonsfi_util.cc",
-    "common/nacl_nonsfi_util.h",
-    "common/nacl_process_type.h",
-    "common/nacl_renderer_messages.cc",
-    "common/nacl_renderer_messages.h",
-    "common/nacl_sandbox_type.h",
-    "common/nacl_types.cc",
-    "common/nacl_types.h",
-    "common/nacl_types_param_traits.cc",
-    "common/nacl_types_param_traits.h",
-    "common/pnacl_types.cc",
-    "common/pnacl_types.h",
-  ]
-
-  deps = [
-    ":nacl_switches",
-    "//base",
-    "//content/public/common",
-    "//ipc",
-    "//url",
-  ]
-
-  if (is_linux) {
-    sources += [
-      "common/nacl_paths.cc",
-      "common/nacl_paths.h",
-    ]
-
-    defines = [ "__STDC_LIMIT_MACROS=1" ]
-  }
-}
diff --git a/components/nacl/browser/BUILD.gn b/components/nacl/browser/BUILD.gn
new file mode 100644
index 0000000..b55fab1
--- /dev/null
+++ b/components/nacl/browser/BUILD.gn
@@ -0,0 +1,65 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+
+assert(enable_nacl)
+
+source_set("browser") {
+  sources = [
+    "bad_message.cc",
+    "bad_message.h",
+    "nacl_broker_host_win.cc",
+    "nacl_broker_host_win.h",
+    "nacl_broker_service_win.cc",
+    "nacl_broker_service_win.h",
+    "nacl_browser.cc",
+    "nacl_browser.h",
+    "nacl_file_host.cc",
+    "nacl_file_host.h",
+    "nacl_host_message_filter.cc",
+    "nacl_host_message_filter.h",
+    "nacl_process_host.cc",
+    "nacl_process_host.h",
+    "nacl_validation_cache.cc",
+    "nacl_validation_cache.h",
+    "pnacl_host.cc",
+    "pnacl_host.h",
+    "pnacl_translation_cache.cc",
+    "pnacl_translation_cache.h",
+  ]
+
+  deps = [
+    "//base",
+    "//base/third_party/dynamic_annotations",
+    "//components/nacl/common",
+    "//components/nacl/common:debug_exception_handler",
+    "//components/url_formatter",
+    "//content/public/browser",
+    "//content/public/common",
+    "//ipc",
+    "//native_client/src/trusted/service_runtime:sel_main_chrome",
+    "//net",
+    "//ppapi/host",
+    "//ppapi/proxy:ipc",
+    "//ppapi/shared_impl",
+  ]
+
+  data_deps = []
+
+  if (is_linux) {
+    sources += [
+      "../zygote/nacl_fork_delegate_linux.cc",
+      "../zygote/nacl_fork_delegate_linux.h",
+    ]
+
+    deps += [
+      "//components/nacl/loader:nacl_helper_integration",
+      "//sandbox/linux:sandbox_services",
+      "//sandbox/linux:suid_sandbox_client",
+    ]
+
+    data_deps += [ "//components/nacl/loader:helper_nonsfi" ]
+  }
+}
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index 5b6cb44..06c3c78 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -493,13 +493,6 @@
       delete this;
       return;
     }
-
-    if (!enable_ppapi_proxy()) {
-      SendErrorToRenderer(
-          "PPAPI proxy must be enabled on NaCl in Non-SFI mode.");
-      delete this;
-      return;
-    }
   } else {
     // Rather than creating a socket pair in the renderer, and passing
     // one side through the browser to sel_ldr, socket pairs are created
@@ -900,8 +893,6 @@
 
   NaClStartParams params;
 
-  // Enable PPAPI proxy channel creation only for renderer processes.
-  params.enable_ipc_proxy = enable_ppapi_proxy();
   params.process_type = process_type_;
   bool enable_nacl_debug = enable_debug_stub_ &&
       NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(manifest_url_);
@@ -1061,9 +1052,6 @@
     // process will exit properly.
     bool has_error = false;
 
-    // Note: this check is redundant. We check this earlier.
-    DCHECK(params.enable_ipc_proxy);
-
     ScopedChannelHandle ppapi_browser_server_channel_handle;
     ScopedChannelHandle ppapi_browser_client_channel_handle;
     ScopedChannelHandle ppapi_renderer_server_channel_handle;
@@ -1207,18 +1195,9 @@
   ScopedChannelHandle manifest_service_channel_handle(
       raw_manifest_service_channel_handle);
 
-  if (enable_ppapi_proxy()) {
-    if (!StartPPAPIProxy(ppapi_browser_channel_handle.Pass())) {
-      SendErrorToRenderer("Browser PPAPI proxy could not start.");
-      return;
-    }
-  } else {
-    // If PPAPI proxy is disabled, channel handles should be invalid.
-    DCHECK(ppapi_browser_channel_handle.get().name.empty());
-    DCHECK(ppapi_renderer_channel_handle.get().name.empty());
-    // Invalidate, just in case.
-    ppapi_browser_channel_handle.reset();
-    ppapi_renderer_channel_handle.reset();
+  if (!StartPPAPIProxy(ppapi_browser_channel_handle.Pass())) {
+    SendErrorToRenderer("Browser PPAPI proxy could not start.");
+    return;
   }
 
   // Let the renderer know that the IPC channels are established.
diff --git a/components/nacl/browser/nacl_process_host.h b/components/nacl/browser/nacl_process_host.h
index 80e2a0a..7580f21 100644
--- a/components/nacl/browser/nacl_process_host.h
+++ b/components/nacl/browser/nacl_process_host.h
@@ -139,9 +139,6 @@
 
   void OnResourcesReady();
 
-  // Enable the PPAPI proxy only for NaCl processes corresponding to a renderer.
-  bool enable_ppapi_proxy() { return render_view_id_ != 0; }
-
   // Sends the reply message to the renderer who is waiting for the plugin
   // to load. Returns true on success.
   void ReplyToRenderer(
diff --git a/components/nacl/common/BUILD.gn b/components/nacl/common/BUILD.gn
index ab7fc75..5af9cbe 100644
--- a/components/nacl/common/BUILD.gn
+++ b/components/nacl/common/BUILD.gn
@@ -2,6 +2,66 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/features.gni")
+
+if (enable_nacl) {
+  source_set("common") {
+    sources = [
+      "nacl_cmd_line.cc",
+      "nacl_cmd_line.h",
+      "nacl_constants.cc",
+      "nacl_constants.h",
+      "nacl_host_messages.cc",
+      "nacl_host_messages.h",
+      "nacl_messages.cc",
+      "nacl_messages.h",
+      "nacl_nonsfi_util.cc",
+      "nacl_nonsfi_util.h",
+      "nacl_process_type.h",
+      "nacl_renderer_messages.cc",
+      "nacl_renderer_messages.h",
+      "nacl_sandbox_type.h",
+      "nacl_types.cc",
+      "nacl_types.h",
+      "nacl_types_param_traits.cc",
+      "nacl_types_param_traits.h",
+      "pnacl_types.cc",
+      "pnacl_types.h",
+    ]
+
+    public_deps = [
+      ":switches",
+    ]
+
+    deps = [
+      "//base",
+      "//content/public/common",
+      "//ipc",
+      "//url",
+    ]
+
+    if (is_linux) {
+      sources += [
+        "nacl_paths.cc",
+        "nacl_paths.h",
+      ]
+
+      defines = [ "__STDC_LIMIT_MACROS=1" ]
+    }
+  }
+
+  source_set("debug_exception_handler") {
+    sources = [
+      "nacl_debug_exception_handler_win.cc",
+      "nacl_debug_exception_handler_win.h",
+    ]
+
+    deps = [
+      "//base",
+    ]
+  }
+}
+
 # Depending on this allows targets to unconditionally include
 # nacl_process_type.h without testing whether nacl is enabled.
 source_set("process_type") {
@@ -13,3 +73,10 @@
     "//content/public/common",
   ]
 }
+
+source_set("switches") {
+  sources = [
+    "nacl_switches.cc",
+    "nacl_switches.h",
+  ]
+}
diff --git a/components/nacl/common/nacl_messages.h b/components/nacl/common/nacl_messages.h
index aed918d..2e3ce628 100644
--- a/components/nacl/common/nacl_messages.h
+++ b/components/nacl/common/nacl_messages.h
@@ -35,7 +35,6 @@
   IPC_STRUCT_TRAITS_MEMBER(validation_cache_key)
   IPC_STRUCT_TRAITS_MEMBER(version)
   IPC_STRUCT_TRAITS_MEMBER(enable_debug_stub)
-  IPC_STRUCT_TRAITS_MEMBER(enable_ipc_proxy)
   IPC_STRUCT_TRAITS_MEMBER(process_type)
   IPC_STRUCT_TRAITS_MEMBER(crash_info_shmem_handle)
 IPC_STRUCT_TRAITS_END()
diff --git a/components/nacl/common/nacl_types.cc b/components/nacl/common/nacl_types.cc
index 1273ec63..9667af6 100644
--- a/components/nacl/common/nacl_types.cc
+++ b/components/nacl/common/nacl_types.cc
@@ -19,7 +19,6 @@
 #endif
       validation_cache_enabled(false),
       enable_debug_stub(false),
-      enable_ipc_proxy(false),
       process_type(kUnknownNaClProcessType),
       crash_info_shmem_handle(base::SharedMemory::NULLHandle()) {
 }
diff --git a/components/nacl/common/nacl_types.h b/components/nacl/common/nacl_types.h
index 32d4c0cc..8e4fe87 100644
--- a/components/nacl/common/nacl_types.h
+++ b/components/nacl/common/nacl_types.h
@@ -101,7 +101,6 @@
   std::string version;
 
   bool enable_debug_stub;
-  bool enable_ipc_proxy;
 
   NaClAppProcessType process_type;
 
diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn
new file mode 100644
index 0000000..ed8f335
--- /dev/null
+++ b/components/nacl/loader/BUILD.gn
@@ -0,0 +1,189 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+import("//build/config/nacl/config.gni")
+import("//testing/test.gni")
+
+assert(enable_nacl)
+
+source_set("loader") {
+  sources = [
+    "nacl_ipc_adapter.cc",
+    "nacl_ipc_adapter.h",
+    "nacl_listener.cc",
+    "nacl_listener.h",
+    "nacl_main.cc",
+    "nacl_main_platform_delegate.h",
+    "nacl_main_platform_delegate_linux.cc",
+    "nacl_main_platform_delegate_mac.mm",
+    "nacl_main_platform_delegate_win.cc",
+    "nacl_trusted_listener.cc",
+    "nacl_trusted_listener.h",
+    "nacl_validation_db.h",
+    "nacl_validation_query.cc",
+    "nacl_validation_query.h",
+  ]
+
+  deps = [
+    "//base",
+    "//base:base_static",
+    "//components/nacl/common",
+    "//content/public/common",
+    "//crypto",
+    "//ipc",
+    "//native_client/src/trusted/service_runtime:sel_main_chrome",
+    "//ppapi/c",
+    "//ppapi/proxy:ipc",
+    "//ppapi/shared_impl",
+    "//sandbox",
+    "//third_party/mojo/src/mojo/edk/system",
+  ]
+
+  if (enable_nacl_untrusted) {
+    data_deps = [
+      "//ppapi/native_client:irt",
+    ]
+  }
+  if (enable_pnacl) {
+    data_deps +=
+        [ "//ppapi/native_client/src/untrusted/pnacl_support_extension" ]
+  }
+}
+
+# TODO(GYP): Delete this after we've converted everything to GN.
+# The _run targets exist only for compatibility w/ GYP.
+group("nacl_loader_unittests_run") {
+  testonly = true
+  deps = [
+    ":nacl_loader_unittests",
+  ]
+}
+
+test("nacl_loader_unittests") {
+  sources = [
+    "nacl_ipc_adapter_unittest.cc",
+    "nacl_validation_query_unittest.cc",
+    "run_all_unittests.cc",
+  ]
+
+  deps = [
+    ":loader",
+    "//base/test:test_support",
+    "//ipc:test_support",
+    "//ppapi/c",
+    "//testing/gtest",
+  ]
+}
+
+if (is_linux) {
+  executable("nacl_helper") {
+    sources = [
+      "nacl_helper_linux.cc",
+      "nacl_helper_linux.h",
+    ]
+
+    deps = [
+      ":loader",
+      "//base",
+      "//build/config/sanitizers:deps",
+      "//components/nacl/common:switches",
+      "//components/nacl/loader/sandbox_linux",
+      "//content/public/common",
+      "//crypto",
+      "//ipc",
+      "//sandbox/linux:sandbox_services",
+    ]
+
+    cflags = [ "-fPIE" ]
+
+    ldflags = [ "-pie" ]
+
+    data_deps = [
+      "//native_client/src/trusted/service_runtime/linux:bootstrap",
+    ]
+  }
+
+  # For setting up nacl_helper.
+  source_set("nacl_helper_integration") {
+    public = [
+      "nacl_helper_linux.h",
+    ]
+    data_deps = [
+      ":nacl_helper",
+    ]
+  }
+}
+
+if (is_nacl_nonsfi) {
+  executable("nacl_helper_nonsfi_nexe") {
+    output_name = "nacl_helper_nonsfi"
+    set_sources_assignment_filter([])
+    sources = [
+      # TODO(brettw) can this just depend on //components/nacl/common?
+      "../common/nacl_messages.cc",
+      "../common/nacl_messages.h",
+      "../common/nacl_types.cc",
+      "../common/nacl_types.h",
+      "../common/nacl_types_param_traits.cc",
+      "../common/nacl_types_param_traits.h",
+      "nacl_helper_linux.cc",
+      "nacl_helper_linux.h",
+      "nacl_trusted_listener.cc",
+      "nacl_trusted_listener.h",
+      "nonsfi/nonsfi_listener.cc",
+      "nonsfi/nonsfi_listener.h",
+      "nonsfi/nonsfi_main.cc",
+      "nonsfi/nonsfi_main.h",
+    ]
+    deps = [
+      ":nacl_helper_nonsfi_sandbox",
+      "//base",
+      "//components/nacl/common:switches",
+      "//components/tracing",
+      "//content",
+      "//ipc",
+      "//native_client/src/nonsfi/irt:nacl_sys_private",
+      "//native_client/src/nonsfi/loader:elf_loader",
+      "//native_client/src/untrusted/nacl:nacl",
+      "//ppapi/proxy",
+      "//sandbox/linux:sandbox",
+    ]
+  }
+
+  source_set("nacl_helper_nonsfi_sandbox") {
+    set_sources_assignment_filter([])
+    sources = [
+      "nonsfi/nonsfi_sandbox.cc",
+      "nonsfi/nonsfi_sandbox.h",
+      "sandbox_linux/nacl_sandbox_linux.cc",
+      "sandbox_linux/nacl_sandbox_linux.h",
+    ]
+    deps = [
+      "//base",
+      "//components/nacl/common:switches",
+      "//content",
+      "//sandbox/linux:sandbox",
+      "//sandbox/linux:sandbox_services_headers",
+    ]
+  }
+
+  copy("nacl_helper_nonsfi_copy") {
+    sources = [
+      "${root_out_dir}/nacl_helper_nonsfi",
+    ]
+    outputs = [
+      "${root_build_dir}/{{source_file_part}}",
+    ]
+    deps = [
+      ":nacl_helper_nonsfi_nexe",
+    ]
+  }
+}
+
+group("helper_nonsfi") {
+  deps = [
+    ":nacl_helper_nonsfi_copy(//build/toolchain/nacl:newlib_pnacl_nonsfi)",
+  ]
+}
diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc
index d6f8849b..329dc9c2 100644
--- a/components/nacl/loader/nacl_listener.cc
+++ b/components/nacl/loader/nacl_listener.cc
@@ -350,32 +350,29 @@
     LOG(FATAL) << "NaClAppCreate() failed";
   }
 
-  IPC::ChannelHandle browser_handle;
-  IPC::ChannelHandle ppapi_renderer_handle;
-  IPC::ChannelHandle manifest_service_handle;
+  IPC::ChannelHandle browser_handle =
+      IPC::Channel::GenerateVerifiedChannelID("nacl");
+  IPC::ChannelHandle ppapi_renderer_handle =
+      IPC::Channel::GenerateVerifiedChannelID("nacl");
+  IPC::ChannelHandle manifest_service_handle =
+      IPC::Channel::GenerateVerifiedChannelID("nacl");
 
-  if (params.enable_ipc_proxy) {
-    browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
-    ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
-    manifest_service_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
-
-    // Create the PPAPI IPC channels between the NaCl IRT and the host
-    // (browser/renderer) processes. The IRT uses these channels to
-    // communicate with the host and to initialize the IPC dispatchers.
-    SetUpIPCAdapter(&browser_handle, io_thread_.task_runner(), nap,
-                    NACL_CHROME_DESC_BASE,
-                    NaClIPCAdapter::ResolveFileTokenCallback(),
-                    NaClIPCAdapter::OpenResourceCallback());
-    SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.task_runner(), nap,
-                    NACL_CHROME_DESC_BASE + 1,
-                    NaClIPCAdapter::ResolveFileTokenCallback(),
-                    NaClIPCAdapter::OpenResourceCallback());
-    SetUpIPCAdapter(
-        &manifest_service_handle, io_thread_.task_runner(), nap,
-        NACL_CHROME_DESC_BASE + 2,
-        base::Bind(&NaClListener::ResolveFileToken, base::Unretained(this)),
-        base::Bind(&NaClListener::OnOpenResource, base::Unretained(this)));
-  }
+  // Create the PPAPI IPC channels between the NaCl IRT and the host
+  // (browser/renderer) processes. The IRT uses these channels to
+  // communicate with the host and to initialize the IPC dispatchers.
+  SetUpIPCAdapter(&browser_handle, io_thread_.task_runner(), nap,
+                  NACL_CHROME_DESC_BASE,
+                  NaClIPCAdapter::ResolveFileTokenCallback(),
+                  NaClIPCAdapter::OpenResourceCallback());
+  SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.task_runner(), nap,
+                  NACL_CHROME_DESC_BASE + 1,
+                  NaClIPCAdapter::ResolveFileTokenCallback(),
+                  NaClIPCAdapter::OpenResourceCallback());
+  SetUpIPCAdapter(
+      &manifest_service_handle, io_thread_.task_runner(), nap,
+      NACL_CHROME_DESC_BASE + 2,
+      base::Bind(&NaClListener::ResolveFileToken, base::Unretained(this)),
+      base::Bind(&NaClListener::OnOpenResource, base::Unretained(this)));
 
   trusted_listener_ =
       new NaClTrustedListener(IPC::Channel::GenerateVerifiedChannelID("nacl"),
diff --git a/components/nacl/loader/nonsfi/nonsfi_listener.cc b/components/nacl/loader/nonsfi/nonsfi_listener.cc
index 5d2ed0c..feb84a9 100644
--- a/components/nacl/loader/nonsfi/nonsfi_listener.cc
+++ b/components/nacl/loader/nonsfi/nonsfi_listener.cc
@@ -77,9 +77,6 @@
   // Random number source initialization.
   nonsfi_set_urandom_fd(base::GetUrandomFD());
 
-  // In Non-SFI mode, PPAPI proxy must be enabled.
-  CHECK(params.enable_ipc_proxy);
-
   // In Non-SFI mode, we neither intercept nor rewrite the message using
   // NaClIPCAdapter, and the channels are connected between the plugin and
   // the hosts directly. So, the IPC::Channel instances will be created in
diff --git a/components/nacl/loader/sandbox_linux/BUILD.gn b/components/nacl/loader/sandbox_linux/BUILD.gn
new file mode 100644
index 0000000..ce1d404
--- /dev/null
+++ b/components/nacl/loader/sandbox_linux/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+import("//build/config/ui.gni")
+
+assert(is_linux)
+assert(enable_nacl)
+
+source_set("sandbox_linux") {
+  sources = [
+    "nacl_bpf_sandbox_linux.cc",
+    "nacl_sandbox_linux.cc",
+  ]
+
+  defines = [ "IN_NACL_HELPER=1" ]
+
+  deps = [
+    "//base",
+    "//components/nacl/common",
+    "//components/nacl/loader",
+    "//content/public/common",
+    "//crypto",
+    "//ipc",
+    "//sandbox",
+    "//sandbox/linux:sandbox_services_headers",
+  ]
+
+  if (use_glib) {
+    configs += [ "//build/config/linux:glib" ]
+  }
+
+  if (use_seccomp_bpf) {
+    defines += [ "USE_SECCOMP_BPF" ]
+  }
+}
diff --git a/components/nacl/renderer/BUILD.gn b/components/nacl/renderer/BUILD.gn
new file mode 100644
index 0000000..f6f5992
--- /dev/null
+++ b/components/nacl/renderer/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+
+assert(enable_nacl)
+
+source_set("renderer") {
+  sources = [
+    "file_downloader.cc",
+    "file_downloader.h",
+    "histogram.cc",
+    "histogram.h",
+    "json_manifest.cc",
+    "json_manifest.h",
+    "manifest_downloader.cc",
+    "manifest_downloader.h",
+    "manifest_service_channel.cc",
+    "manifest_service_channel.h",
+    "nacl_helper.cc",
+    "nacl_helper.h",
+    "nexe_load_manager.cc",
+    "nexe_load_manager.h",
+    "platform_info.cc",
+    "platform_info.h",
+    "pnacl_translation_resource_host.cc",
+    "pnacl_translation_resource_host.h",
+    "ppb_nacl_private_impl.cc",
+    "ppb_nacl_private_impl.h",
+    "progress_event.cc",
+    "progress_event.h",
+    "trusted_plugin_channel.cc",
+    "trusted_plugin_channel.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/nacl/common",
+    "//components/nacl/renderer/plugin:nacl_trusted_plugin",
+    "//content/public/common",
+    "//content/public/renderer",
+    "//ipc",
+    "//net",
+    "//ppapi/c",
+    "//ppapi/proxy:ipc",
+    "//ppapi/shared_impl",
+    "//third_party/WebKit/public:blink",
+  ]
+}
diff --git a/components/nacl/renderer/plugin/temporary_file.cc b/components/nacl/renderer/plugin/temporary_file.cc
index 9fc1a68..6a79e77 100644
--- a/components/nacl/renderer/plugin/temporary_file.cc
+++ b/components/nacl/renderer/plugin/temporary_file.cc
@@ -18,65 +18,50 @@
 
 TempFile::TempFile(Plugin* plugin, PP_FileHandle handle)
     : plugin_(plugin),
-      internal_handle_(handle) { }
+      file_handle_(handle) { }
 
 TempFile::~TempFile() { }
 
-int32_t TempFile::Open(bool writeable) {
-  if (internal_handle_ == PP_kInvalidFileHandle)
-    return PP_ERROR_FAILED;
-
-#if NACL_WINDOWS
-  HANDLE handle = internal_handle_;
-
-  //////// Now try the posix view.
-  int rdwr_flag = writeable ? _O_RDWR : _O_RDONLY;
-  int32_t posix_desc = _open_osfhandle(reinterpret_cast<intptr_t>(handle),
-                                       rdwr_flag | _O_BINARY
-                                       | _O_TEMPORARY | _O_SHORT_LIVED );
-
-  // Close the Windows HANDLE if it can't be converted.
-  if (posix_desc == -1) {
-    PLUGIN_PRINTF(("TempFile::Open failed to convert HANDLE to posix\n"));
-    CloseHandle(handle);
-  }
-  int32_t fd = posix_desc;
-#else
-  int32_t fd = internal_handle_;
-#endif
-
+nacl::DescWrapper* TempFile::MakeDescWrapper(int nacl_file_flags) {
+  base::File file_dup = file_handle_.Duplicate();
+  if (!file_dup.IsValid())
+    return NULL;
+#if defined(OS_WIN)
+  int fd = _open_osfhandle(
+      reinterpret_cast<intptr_t>(file_dup.TakePlatformFile()),
+      _O_RDWR | _O_BINARY | _O_TEMPORARY | _O_SHORT_LIVED);
   if (fd < 0)
-    return PP_ERROR_FAILED;
+    return NULL;
+#else
+  int fd = file_dup.TakePlatformFile();
+#endif
+  return plugin_->wrapper_factory()->MakeFileDesc(fd, nacl_file_flags);
+}
 
-  // dup the fd to make allow making separate read and write wrappers.
-  int32_t read_fd = DUP(fd);
-  if (read_fd == NACL_NO_FILE_DESC)
+int32_t TempFile::Open(bool writeable) {
+  read_wrapper_.reset(MakeDescWrapper(O_RDONLY));
+  if (!read_wrapper_)
     return PP_ERROR_FAILED;
 
   if (writeable) {
-    write_wrapper_.reset(
-        plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDWR));
+    write_wrapper_.reset(MakeDescWrapper(O_RDWR));
+    if (!write_wrapper_)
+      return PP_ERROR_FAILED;
   }
 
-  read_wrapper_.reset(
-      plugin_->wrapper_factory()->MakeFileDesc(read_fd, O_RDONLY));
   return PP_OK;
 }
 
 bool TempFile::Reset() {
   // Use the read_wrapper_ to reset the file pos.  The write_wrapper_ is also
   // backed by the same file, so it should also reset.
-  CHECK(read_wrapper_.get() != NULL);
+  CHECK(read_wrapper_);
   nacl_off64_t newpos = read_wrapper_->Seek(0, SEEK_SET);
   return newpos == 0;
 }
 
 PP_FileHandle TempFile::TakeFileHandle() {
-  PP_FileHandle to_return = internal_handle_;
-  internal_handle_ = PP_kInvalidFileHandle;
-  read_wrapper_.release();
-  write_wrapper_.release();
-  return to_return;
+  return file_handle_.TakePlatformFile();
 }
 
 }  // namespace plugin
diff --git a/components/nacl/renderer/plugin/temporary_file.h b/components/nacl/renderer/plugin/temporary_file.h
index 5237b46..d87f42cf 100644
--- a/components/nacl/renderer/plugin/temporary_file.h
+++ b/components/nacl/renderer/plugin/temporary_file.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_NACL_RENDERER_PLUGIN_TEMPORARY_FILE_H_
 #define COMPONENTS_NACL_RENDERER_PLUGIN_TEMPORARY_FILE_H_
 
+#include "base/files/file.h"
+#include "base/memory/scoped_ptr.h"
 #include "native_client/src/include/nacl_macros.h"
 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
 
@@ -51,17 +53,20 @@
   nacl::DescWrapper* write_wrapper() { return write_wrapper_.get(); }
   nacl::DescWrapper* read_wrapper() { return read_wrapper_.get(); }
 
-  // Returns the handle to the file repesented and resets the internal handle
-  // and all wrappers.
+  // Returns a handle to the file, transferring ownership of it.  Note that
+  // the objects returned by write_wrapper() and read_wrapper() remain
+  // valid after TakeFileHandle() is called.
   PP_FileHandle TakeFileHandle();
 
  private:
   NACL_DISALLOW_COPY_AND_ASSIGN(TempFile);
 
+  nacl::DescWrapper* MakeDescWrapper(int nacl_file_flags);
+
   Plugin* plugin_;
-  nacl::scoped_ptr<nacl::DescWrapper> read_wrapper_;
-  nacl::scoped_ptr<nacl::DescWrapper> write_wrapper_;
-  PP_FileHandle internal_handle_;
+  scoped_ptr<nacl::DescWrapper> read_wrapper_;
+  scoped_ptr<nacl::DescWrapper> write_wrapper_;
+  base::File file_handle_;
 };
 
 }  // namespace plugin
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc
index 533d7f4..404fed85 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -66,11 +66,11 @@
   host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), form));
 }
 
-void ContentPasswordManagerDriver::AccountCreationFormsFound(
-    const std::vector<autofill::FormData>& forms) {
+void ContentPasswordManagerDriver::FormsEligibleForGenerationFound(
+    const std::vector<autofill::PasswordFormGenerationData>& forms) {
   content::RenderFrameHost* host = render_frame_host_;
-  host->Send(new AutofillMsg_AccountCreationFormsDetected(host->GetRoutingID(),
-                                                          forms));
+  host->Send(new AutofillMsg_FoundFormsEligibleForGeneration(
+      host->GetRoutingID(), forms));
 }
 
 void ContentPasswordManagerDriver::AutofillDataReceived(
diff --git a/components/password_manager/content/browser/content_password_manager_driver.h b/components/password_manager/content/browser/content_password_manager_driver.h
index 42618e98..91393771 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.h
+++ b/components/password_manager/content/browser/content_password_manager_driver.h
@@ -11,6 +11,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "components/autofill/core/common/password_form_field_prediction_map.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/password_manager/core/browser/password_autofill_manager.h"
 #include "components/password_manager/core/browser/password_generation_manager.h"
 #include "components/password_manager/core/browser/password_manager.h"
@@ -53,8 +54,8 @@
       const autofill::PasswordFormFillData& form_data) override;
   void AllowPasswordGenerationForForm(
       const autofill::PasswordForm& form) override;
-  void AccountCreationFormsFound(
-      const std::vector<autofill::FormData>& forms) override;
+  void FormsEligibleForGenerationFound(
+      const std::vector<autofill::PasswordFormGenerationData>& forms) override;
   void AutofillDataReceived(
       const std::map<autofill::FormData,
                      autofill::PasswordFormFieldPredictionMap>& predictions)
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 7254beb3..e55627aa 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -1069,36 +1069,21 @@
         provisionally_saved_form_->username_element.empty() &&
         provisionally_saved_form_->new_password_element.empty();
 
+    is_new_login_ = false;
     if (best_update_match)
       pending_credentials_ = *best_update_match;
-    else
+    else if (has_generated_password_) {
+      // If a password was generated and we didn't find match we have to save it
+      // in separate entry since we have to store it but we don't know where.
+      CreatePendingCredentialsForNewCredentials();
+      is_new_login_ = true;
+    } else {
+      // We don't care about |pending_credentials_| if we didn't find the best
+      // match, since the user will select the correct one.
       pending_credentials_.origin = provisionally_saved_form_->origin;
-    is_new_login_ = false;
-    // We don't care about |pending_credentials_| if we didn't find the best
-    // match, since the user will select the correct one.
-  } else {
-    // User typed in a new, unknown username.
-    user_action_ = kUserActionOverrideUsernameAndPassword;
-    pending_credentials_ = observed_form_;
-    if (provisionally_saved_form_->was_parsed_using_autofill_predictions)
-      pending_credentials_.username_element =
-          provisionally_saved_form_->username_element;
-    pending_credentials_.username_value =
-        provisionally_saved_form_->username_value;
-    pending_credentials_.other_possible_usernames =
-        provisionally_saved_form_->other_possible_usernames;
-
-    // The password value will be filled in later, remove any garbage for now.
-    pending_credentials_.password_value.clear();
-    pending_credentials_.new_password_value.clear();
-
-    // If this was a sign-up or change password form, the names of the elements
-    // are likely different than those on a login form, so do not bother saving
-    // them. We will fill them with meaningful values in UpdateLogin() when the
-    // user goes onto a real login form for the first time.
-    if (!provisionally_saved_form_->new_password_element.empty()) {
-      pending_credentials_.password_element.clear();
     }
+  } else {
+    CreatePendingCredentialsForNewCredentials();
   }
 
   pending_credentials_.action = provisionally_saved_form_->action;
@@ -1235,27 +1220,19 @@
 
 PasswordForm* PasswordFormManager::FindBestMatchForUpdatePassword(
     const base::string16& password) const {
-  if (best_matches_.size() == 1) {
-    // In case when the user has only one credential, consider it the same as
-    // is being saved.
+  if (best_matches_.size() == 1 && !has_generated_password_) {
+    // In case when the user has only one credential and the current password is
+    // not generated, consider it the same as is being saved.
     return best_matches_.begin()->second.get();
   }
   if (password.empty())
     return nullptr;
 
-  PasswordFormMap::const_iterator best_password_match_it = best_matches_.end();
   for (auto it = best_matches_.begin(); it != best_matches_.end(); ++it) {
-    if (it->second->password_value == password) {
-      if (best_password_match_it != best_matches_.end()) {
-        // Found a second credential with the same password, do nothing.
-        return nullptr;
-      }
-      best_password_match_it = it;
-    }
+    if (it->second->password_value == password)
+      return it->second.get();
   }
-  return best_password_match_it == best_matches_.end()
-             ? nullptr
-             : best_password_match_it->second.get();
+  return nullptr;
 }
 
 PasswordForm* PasswordFormManager::FindBestSavedMatch(
@@ -1264,7 +1241,7 @@
       best_matches_.find(provisionally_saved_form_->username_value);
   if (it != best_matches_.end())
     return it->second.get();
-  if (!form->username_value.empty())
+  if (!form->username_element.empty() || !form->new_password_element.empty())
     return nullptr;
   for (const auto& stored_match : best_matches_) {
     if (stored_match.second->password_value == form->password_value)
@@ -1273,6 +1250,31 @@
   return nullptr;
 }
 
+void PasswordFormManager::CreatePendingCredentialsForNewCredentials() {
+  // User typed in a new, unknown username.
+  user_action_ = kUserActionOverrideUsernameAndPassword;
+  pending_credentials_ = observed_form_;
+  if (provisionally_saved_form_->was_parsed_using_autofill_predictions)
+    pending_credentials_.username_element =
+        provisionally_saved_form_->username_element;
+  pending_credentials_.username_value =
+      provisionally_saved_form_->username_value;
+  pending_credentials_.other_possible_usernames =
+      provisionally_saved_form_->other_possible_usernames;
+
+  // The password value will be filled in later, remove any garbage for now.
+  pending_credentials_.password_value.clear();
+  pending_credentials_.new_password_value.clear();
+
+  // If this was a sign-up or change password form, the names of the elements
+  // are likely different than those on a login form, so do not bother saving
+  // them. We will fill them with meaningful values in UpdateLogin() when the
+  // user goes onto a real login form for the first time.
+  if (!provisionally_saved_form_->new_password_element.empty()) {
+    pending_credentials_.password_element.clear();
+  }
+}
+
 void PasswordFormManager::OnNopeUpdateClicked() {
   UploadChangePasswordForm(autofill::NOT_NEW_PASSWORD, std::string());
 }
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index a82ea6d..376b390 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -402,6 +402,10 @@
   // from password store.
   void CreatePendingCredentials();
 
+  // Create pending credentials from provisionally saved form when this form
+  // represents credentials that were not previosly saved.
+  void CreatePendingCredentialsForNewCredentials();
+
   // If |pending_credentials_.username_value| is not empty, iterates over all
   // forms from |best_matches_| and deletes from the password store all which
   // are not PSL-matched, have an empty username, and a password equal to
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index 3a4f97f..fe469f12 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -2546,4 +2546,115 @@
 }
 #endif
 
+TEST_F(PasswordFormManagerTest,
+       TestSavingOnChangePasswordFormGenerationNoStoredForms) {
+  client()->set_is_update_password_ui_enabled(true);
+  SimulateMatchingPhase(form_manager(), RESULT_NO_MATCH);
+  form_manager()->set_has_generated_password(true);
+
+  // User submits change password form and there is no stored credentials.
+  PasswordForm credentials = *observed_form();
+  credentials.username_element.clear();
+  credentials.password_value = saved_match()->password_value;
+  credentials.new_password_element = ASCIIToUTF16("NewPasswd");
+  credentials.new_password_value = ASCIIToUTF16("new_password");
+  credentials.preferred = true;
+  form_manager()->ProvisionallySave(
+      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  // Successful login. The PasswordManager would instruct PasswordFormManager
+  // to save, which should know this is a new login.
+  EXPECT_TRUE(form_manager()->IsNewLogin());
+  // Make sure the credentials that would be submitted on successful login
+  // are going to match submitted form.
+  EXPECT_EQ(observed_form()->origin.spec(),
+            form_manager()->pending_credentials().origin.spec());
+  EXPECT_EQ(observed_form()->signon_realm,
+            form_manager()->pending_credentials().signon_realm);
+  EXPECT_EQ(observed_form()->action,
+            form_manager()->pending_credentials().action);
+  EXPECT_TRUE(form_manager()->pending_credentials().preferred);
+  EXPECT_EQ(ASCIIToUTF16("new_password"),
+            form_manager()->pending_credentials().password_value);
+  EXPECT_EQ(base::string16(),
+            form_manager()->pending_credentials().username_value);
+  EXPECT_TRUE(
+      form_manager()->pending_credentials().new_password_element.empty());
+  EXPECT_TRUE(form_manager()->pending_credentials().new_password_value.empty());
+}
+
+TEST_F(PasswordFormManagerTest, TestUpdatingOnChangePasswordFormGeneration) {
+  client()->set_is_update_password_ui_enabled(true);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
+  form_manager()->set_has_generated_password(true);
+
+  // User submits credentials for the change password form, and old password is
+  // coincide with password from an existing credentials, so stored credentials
+  // should be updated.
+  PasswordForm credentials = *observed_form();
+  credentials.username_element.clear();
+  credentials.password_value = saved_match()->password_value;
+  credentials.new_password_element = ASCIIToUTF16("NewPasswd");
+  credentials.new_password_value = ASCIIToUTF16("new_password");
+  credentials.preferred = true;
+  form_manager()->ProvisionallySave(
+      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  EXPECT_FALSE(form_manager()->IsNewLogin());
+  // Make sure the credentials that would be submitted on successful login
+  // are going to match the stored entry in the db.
+  EXPECT_EQ(saved_match()->origin.spec(),
+            form_manager()->pending_credentials().origin.spec());
+  EXPECT_EQ(saved_match()->signon_realm,
+            form_manager()->pending_credentials().signon_realm);
+  EXPECT_EQ(observed_form()->action,
+            form_manager()->pending_credentials().action);
+  EXPECT_TRUE(form_manager()->pending_credentials().preferred);
+  EXPECT_EQ(ASCIIToUTF16("new_password"),
+            form_manager()->pending_credentials().password_value);
+  EXPECT_EQ(saved_match()->username_value,
+            form_manager()->pending_credentials().username_value);
+  EXPECT_TRUE(
+      form_manager()->pending_credentials().new_password_element.empty());
+  EXPECT_TRUE(form_manager()->pending_credentials().new_password_value.empty());
+}
+
+TEST_F(PasswordFormManagerTest,
+       TestSavingOnChangePasswordFormGenerationNoMatchedForms) {
+  client()->set_is_update_password_ui_enabled(true);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
+  form_manager()->set_has_generated_password(true);
+
+  // User submits credentials for the change password form, and old password is
+  // not coincide with password from existing credentials, so new credentials
+  // should be saved.
+  PasswordForm credentials = *observed_form();
+  credentials.username_element.clear();
+  credentials.password_value =
+      saved_match()->password_value + ASCIIToUTF16("1");
+  credentials.new_password_element = ASCIIToUTF16("NewPasswd");
+  credentials.new_password_value = ASCIIToUTF16("new_password");
+  credentials.preferred = true;
+  form_manager()->ProvisionallySave(
+      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  EXPECT_TRUE(form_manager()->IsNewLogin());
+  // Make sure the credentials that would be submitted on successful login
+  // are going to match submitted form.
+  EXPECT_EQ(observed_form()->origin.spec(),
+            form_manager()->pending_credentials().origin.spec());
+  EXPECT_EQ(observed_form()->signon_realm,
+            form_manager()->pending_credentials().signon_realm);
+  EXPECT_EQ(observed_form()->action,
+            form_manager()->pending_credentials().action);
+  EXPECT_TRUE(form_manager()->pending_credentials().preferred);
+  EXPECT_EQ(ASCIIToUTF16("new_password"),
+            form_manager()->pending_credentials().password_value);
+  EXPECT_EQ(base::string16(),
+            form_manager()->pending_credentials().username_value);
+  EXPECT_TRUE(
+      form_manager()->pending_credentials().new_password_element.empty());
+  EXPECT_TRUE(form_manager()->pending_credentials().new_password_value.empty());
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_generation_manager.cc b/components/password_manager/core/browser/password_generation_manager.cc
index 40e170c1..637abde 100644
--- a/components/password_manager/core/browser/password_generation_manager.cc
+++ b/components/password_manager/core/browser/password_generation_manager.cc
@@ -7,7 +7,7 @@
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
@@ -23,12 +23,13 @@
 PasswordGenerationManager::~PasswordGenerationManager() {
 }
 
-void PasswordGenerationManager::DetectAccountCreationForms(
+void PasswordGenerationManager::DetectFormsEligibleForGeneration(
     const std::vector<autofill::FormStructure*>& forms) {
   if (!IsGenerationEnabled())
     return;
 
-  std::vector<autofill::FormData> account_creation_forms;
+  std::vector<autofill::PasswordFormGenerationData>
+      forms_eligible_for_generation;
   for (std::vector<autofill::FormStructure*>::const_iterator form_it =
            forms.begin();
        form_it != forms.end(); ++form_it) {
@@ -37,14 +38,17 @@
              form->begin();
          field_it != form->end(); ++field_it) {
       autofill::AutofillField* field = *field_it;
-      if (field->server_type() == autofill::ACCOUNT_CREATION_PASSWORD) {
-        account_creation_forms.push_back(form->ToFormData());
+      if (field->server_type() == autofill::ACCOUNT_CREATION_PASSWORD ||
+          field->server_type() == autofill::NEW_PASSWORD) {
+        forms_eligible_for_generation.push_back(
+            autofill::PasswordFormGenerationData{form->form_name(),
+                                                 form->target_url(), *field});
         break;
       }
     }
   }
-  if (!account_creation_forms.empty())
-    driver_->AccountCreationFormsFound(account_creation_forms);
+  if (!forms_eligible_for_generation.empty())
+    driver_->FormsEligibleForGenerationFound(forms_eligible_for_generation);
 }
 
 // In order for password generation to be enabled, we need to make sure:
diff --git a/components/password_manager/core/browser/password_generation_manager.h b/components/password_manager/core/browser/password_generation_manager.h
index 36cf18b0..7b31c705 100644
--- a/components/password_manager/core/browser/password_generation_manager.h
+++ b/components/password_manager/core/browser/password_generation_manager.h
@@ -40,7 +40,7 @@
   // Detect account creation forms from forms with autofill type annotated.
   // Will send a message to the renderer if we find a correctly annotated form
   // and the feature is enabled.
-  void DetectAccountCreationForms(
+  void DetectFormsEligibleForGeneration(
       const std::vector<autofill::FormStructure*>& forms);
 
   // Determines current state of password generation
diff --git a/components/password_manager/core/browser/password_generation_manager_unittest.cc b/components/password_manager/core/browser/password_generation_manager_unittest.cc
index fcc2683..2aa6780 100644
--- a/components/password_manager/core/browser/password_generation_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_generation_manager_unittest.cc
@@ -14,6 +14,7 @@
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/password_manager/core/browser/password_autofill_manager.h"
 #include "components/password_manager/core/browser/password_generation_manager.h"
 #include "components/password_manager/core/browser/password_manager.h"
@@ -48,21 +49,24 @@
   PasswordAutofillManager* GetPasswordAutofillManager() override {
     return &password_autofill_manager_;
   }
-  void AccountCreationFormsFound(
-      const std::vector<autofill::FormData>& forms) override {
-    found_account_creation_forms_.insert(
-        found_account_creation_forms_.begin(), forms.begin(), forms.end());
+  void FormsEligibleForGenerationFound(
+      const std::vector<autofill::PasswordFormGenerationData>& forms) override {
+    found_forms_eligible_for_generation_.insert(
+        found_forms_eligible_for_generation_.begin(), forms.begin(),
+        forms.end());
   }
 
-  const std::vector<autofill::FormData>& GetFoundAccountCreationForms() {
-    return found_account_creation_forms_;
+  const std::vector<autofill::PasswordFormGenerationData>&
+  GetFoundEligibleForGenerationForms() {
+    return found_forms_eligible_for_generation_;
   }
 
  private:
   PasswordManager password_manager_;
   PasswordGenerationManager password_generation_manager_;
   PasswordAutofillManager password_autofill_manager_;
-  std::vector<autofill::FormData> found_account_creation_forms_;
+  std::vector<autofill::PasswordFormGenerationData>
+      found_forms_eligible_for_generation_;
 };
 
 class MockPasswordManagerClient : public StubPasswordManagerClient {
@@ -113,9 +117,9 @@
     return GetGenerationManager()->IsGenerationEnabled();
   }
 
-  void DetectAccountCreationForms(
+  void DetectFormsEligibleForGeneration(
       const std::vector<autofill::FormStructure*>& forms) {
-    GetGenerationManager()->DetectAccountCreationForms(forms);
+    GetGenerationManager()->DetectFormsEligibleForGeneration(forms);
   }
 
   base::MessageLoop message_loop_;
@@ -153,7 +157,7 @@
   EXPECT_FALSE(IsGenerationEnabled());
 }
 
-TEST_F(PasswordGenerationManagerTest, DetectAccountCreationForms) {
+TEST_F(PasswordGenerationManagerTest, DetectFormsEligibleForGeneration) {
   // Setup so that IsGenerationEnabled() returns true.
   EXPECT_CALL(*client_, IsSavingAndFillingEnabledForCurrentPage())
       .WillRepeatedly(testing::Return(true));
@@ -177,6 +181,8 @@
   forms.push_back(&form1);
   autofill::FormData account_creation_form;
   account_creation_form.origin = GURL("http://accounts.yahoo.com/");
+  account_creation_form.action = GURL("http://accounts.yahoo.com/signup");
+  account_creation_form.name = ASCIIToUTF16("account_creation_form");
   account_creation_form.fields.push_back(username);
   account_creation_form.fields.push_back(password);
   autofill::FormFieldData confirm_password;
@@ -186,8 +192,22 @@
   account_creation_form.fields.push_back(confirm_password);
   autofill::FormStructure form2(account_creation_form);
   forms.push_back(&form2);
+  autofill::FormData change_password_form;
+  change_password_form.origin = GURL("http://accounts.yahoo.com/");
+  change_password_form.action = GURL("http://accounts.yahoo.com/change");
+  change_password_form.name = ASCIIToUTF16("change_password_form");
+  change_password_form.fields.push_back(password);
+  change_password_form.fields[0].name = ASCIIToUTF16("new_password");
+  change_password_form.fields.push_back(confirm_password);
+  autofill::FormStructure form3(change_password_form);
+  forms.push_back(&form3);
 
   // Simulate the server response to set the field types.
+  // The server response numbers mean:
+  // EMAIL_ADDRESS = 9
+  // PASSWORD = 75
+  // ACCOUNT_CREATION_PASSWORD = 76
+  // NEW_PASSWORD = 88
   const char* const kServerResponse =
       "<autofillqueryresponse>"
       "<field autofilltype=\"9\" />"
@@ -195,13 +215,28 @@
       "<field autofilltype=\"9\" />"
       "<field autofilltype=\"76\" />"
       "<field autofilltype=\"75\" />"
+      "<field autofilltype=\"88\" />"
+      "<field autofilltype=\"88\" />"
       "</autofillqueryresponse>";
   autofill::FormStructure::ParseQueryResponse(kServerResponse, forms, NULL);
 
-  DetectAccountCreationForms(forms);
-  EXPECT_EQ(1u, GetTestDriver()->GetFoundAccountCreationForms().size());
-  EXPECT_EQ(GURL("http://accounts.yahoo.com/"),
-            GetTestDriver()->GetFoundAccountCreationForms()[0].origin);
+  DetectFormsEligibleForGeneration(forms);
+  EXPECT_EQ(2u, GetTestDriver()->GetFoundEligibleForGenerationForms().size());
+  EXPECT_EQ(GURL("http://accounts.yahoo.com/signup"),
+            GetTestDriver()->GetFoundEligibleForGenerationForms()[0].action);
+  EXPECT_EQ(account_creation_form.name,
+            GetTestDriver()->GetFoundEligibleForGenerationForms()[0].name);
+  EXPECT_EQ(password.name, GetTestDriver()
+                               ->GetFoundEligibleForGenerationForms()[0]
+                               .generation_field.name);
+  EXPECT_EQ(GURL("http://accounts.yahoo.com/change"),
+            GetTestDriver()->GetFoundEligibleForGenerationForms()[1].action);
+  EXPECT_EQ(ASCIIToUTF16("new_password"),
+            GetTestDriver()
+                ->GetFoundEligibleForGenerationForms()[1]
+                .generation_field.name);
+  EXPECT_EQ(change_password_form.name,
+            GetTestDriver()->GetFoundEligibleForGenerationForms()[1].name);
 }
 
 TEST_F(PasswordGenerationManagerTest, UpdatePasswordSyncStateIncognito) {
diff --git a/components/password_manager/core/browser/password_manager_driver.h b/components/password_manager/core/browser/password_manager_driver.h
index 10d7558c..4f397c8 100644
--- a/components/password_manager/core/browser/password_manager_driver.h
+++ b/components/password_manager/core/browser/password_manager_driver.h
@@ -18,6 +18,7 @@
 struct FormData;
 struct FormFieldData;
 struct PasswordForm;
+struct PasswordFormGenerationData;
 struct PasswordFormFillData;
 }  // namespace autofill
 
@@ -43,9 +44,10 @@
   virtual void AllowPasswordGenerationForForm(
       const autofill::PasswordForm& form) = 0;
 
-  // Notifies the driver that account creation |forms| were found.
-  virtual void AccountCreationFormsFound(
-      const std::vector<autofill::FormData>& forms) = 0;
+  // Notifies the driver that |forms| were found on which password can be
+  // generated.
+  virtual void FormsEligibleForGenerationFound(
+      const std::vector<autofill::PasswordFormGenerationData>& forms) = 0;
 
   // Notifies the driver that username and password predictions from autofill
   // have been received.
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.cc b/components/password_manager/core/browser/stub_password_manager_driver.cc
index a3173e4..4e6749d 100644
--- a/components/password_manager/core/browser/stub_password_manager_driver.cc
+++ b/components/password_manager/core/browser/stub_password_manager_driver.cc
@@ -20,9 +20,8 @@
     const autofill::PasswordForm& form) {
 }
 
-void StubPasswordManagerDriver::AccountCreationFormsFound(
-    const std::vector<autofill::FormData>& forms) {
-}
+void StubPasswordManagerDriver::FormsEligibleForGenerationFound(
+    const std::vector<autofill::PasswordFormGenerationData>& forms) {}
 
 void StubPasswordManagerDriver::GeneratedPasswordAccepted(
     const base::string16& password) {
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.h b/components/password_manager/core/browser/stub_password_manager_driver.h
index 3ee02b59..d0d3761 100644
--- a/components/password_manager/core/browser/stub_password_manager_driver.h
+++ b/components/password_manager/core/browser/stub_password_manager_driver.h
@@ -22,8 +22,8 @@
       const autofill::PasswordFormFillData& form_data) override;
   void AllowPasswordGenerationForForm(
       const autofill::PasswordForm& form) override;
-  void AccountCreationFormsFound(
-      const std::vector<autofill::FormData>& forms) override;
+  void FormsEligibleForGenerationFound(
+      const std::vector<autofill::PasswordFormGenerationData>& forms) override;
   void GeneratedPasswordAccepted(const base::string16& password) override;
   void FillSuggestion(const base::string16& username,
                       const base::string16& password) override;
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.cc b/components/plugins/renderer/loadable_plugin_placeholder.cc
index ff30f4a..a47d9108 100644
--- a/components/plugins/renderer/loadable_plugin_placeholder.cc
+++ b/components/plugins/renderer/loadable_plugin_placeholder.cc
@@ -270,10 +270,6 @@
   // This is necessary to prevent a flicker.
   if (premade_throttler_ && power_saver_enabled_)
     premade_throttler_->SetHiddenForPlaceholder(true /* hidden */);
-
-  // In case our initial geometry was reported before the placeholder finished
-  // loading, request another one. Needed for correct large poster unthrottling.
-  plugin()->container()->reportGeometry();
 }
 
 void LoadablePluginPlaceholder::DidFinishIconRepositionForTestingCallback() {
@@ -351,20 +347,17 @@
 
     // On a size update check if we now qualify as a essential plugin.
     url::Origin content_origin = url::Origin(GetPluginParams().url);
-    auto status = render_frame()->GetPeripheralContentStatus(
-        render_frame()->GetWebFrame()->top()->securityOrigin(), content_origin,
-        gfx::Size(width, height));
-    if (status != content::RenderFrame::CONTENT_STATUS_PERIPHERAL) {
+    bool cross_origin_main_content = false;
+    if (!render_frame()->ShouldThrottleContent(
+            render_frame()->GetWebFrame()->top()->securityOrigin(),
+            content_origin, width, height, &cross_origin_main_content)) {
       MarkPluginEssential(
           heuristic_run_before_
               ? PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_SIZE_CHANGE
               : PluginInstanceThrottler::UNTHROTTLE_METHOD_DO_NOT_RECORD);
 
-      if (!heuristic_run_before_ &&
-          status ==
-              content::RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG) {
+      if (cross_origin_main_content && !heuristic_run_before_)
         render_frame()->WhitelistContentOrigin(content_origin);
-      }
     }
 
     heuristic_run_before_ = true;
diff --git a/components/policy/core/browser/android/android_combined_policy_provider.cc b/components/policy/core/browser/android/android_combined_policy_provider.cc
index c66f5ac..1673204 100644
--- a/components/policy/core/browser/android/android_combined_policy_provider.cc
+++ b/components/policy/core/browser/android/android_combined_policy_provider.cc
@@ -42,7 +42,9 @@
       env, java_combined_policy_provider_.obj());
 }
 
-void AndroidCombinedPolicyProvider::FlushPolicies(JNIEnv* env, jobject obj) {
+void AndroidCombinedPolicyProvider::FlushPolicies(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   initialized_ = true;
   UpdatePolicy(policy_converter_->GetPolicyBundle().Pass());
 }
diff --git a/components/policy/core/browser/android/android_combined_policy_provider.h b/components/policy/core/browser/android/android_combined_policy_provider.h
index 985d5420..7c4706c 100644
--- a/components/policy/core/browser/android/android_combined_policy_provider.h
+++ b/components/policy/core/browser/android/android_combined_policy_provider.h
@@ -31,7 +31,8 @@
 
   // Push the polices updated by the Java policy providers to the core policy
   // system
-  void FlushPolicies(JNIEnv* env, jobject obj);
+  void FlushPolicies(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj);
 
   // Call this method to tell the policy system whether it should wait for
   // policies to be loaded by this provider. If this method is called,
diff --git a/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc b/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc
index b860f2b3..56f91cd 100644
--- a/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc
+++ b/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc
@@ -70,9 +70,8 @@
       ConvertUTF8ToJavaString(env, "TestPolicy");
   ScopedJavaLocalRef<jstring> jvalue =
       ConvertUTF8ToJavaString(env, "TestValue");
-  manager.GetPolicyConverterForTesting()->SetPolicyString(env, nullptr,
-                                                          jpolicy.obj(),
-                                                          jvalue.obj());
+  manager.GetPolicyConverterForTesting()->SetPolicyString(env, nullptr, jpolicy,
+                                                          jvalue);
   manager.FlushPolicies(env, nullptr);
   const PolicyBundle& bundle = manager.policies();
   const PolicyMap& map = bundle.Get(ns);
diff --git a/components/policy/core/browser/android/policy_converter.cc b/components/policy/core/browser/android/policy_converter.cc
index 21cd0f64..0d199c4 100644
--- a/components/policy/core/browser/android/policy_converter.cc
+++ b/components/policy/core/browser/android/policy_converter.cc
@@ -22,6 +22,7 @@
 #include "jni/PolicyConverter_jni.h"
 
 using base::android::ConvertJavaStringToUTF8;
+using base::android::JavaRef;
 
 namespace policy {
 namespace android {
@@ -50,8 +51,8 @@
 }
 
 void PolicyConverter::SetPolicyBoolean(JNIEnv* env,
-                                       jobject obj,
-                                       jstring policyKey,
+                                       const JavaRef<jobject>& obj,
+                                       const JavaRef<jstring>& policyKey,
                                        jboolean value) {
   SetPolicyValue(
       ConvertJavaStringToUTF8(env, policyKey),
@@ -59,8 +60,8 @@
 }
 
 void PolicyConverter::SetPolicyInteger(JNIEnv* env,
-                                       jobject obj,
-                                       jstring policyKey,
+                                       const JavaRef<jobject>& obj,
+                                       const JavaRef<jstring>& policyKey,
                                        jint value) {
   SetPolicyValue(
       ConvertJavaStringToUTF8(env, policyKey),
@@ -68,18 +69,18 @@
 }
 
 void PolicyConverter::SetPolicyString(JNIEnv* env,
-                                      jobject obj,
-                                      jstring policyKey,
-                                      jstring value) {
+                                      const JavaRef<jobject>& obj,
+                                      const JavaRef<jstring>& policyKey,
+                                      const JavaRef<jstring>& value) {
   SetPolicyValue(ConvertJavaStringToUTF8(env, policyKey),
                  make_scoped_ptr(new base::StringValue(
                      ConvertJavaStringToUTF8(env, value))));
 }
 
 void PolicyConverter::SetPolicyStringArray(JNIEnv* env,
-                                           jobject obj,
-                                           jstring policyKey,
-                                           jobjectArray array) {
+                                           const JavaRef<jobject>& obj,
+                                           const JavaRef<jstring>& policyKey,
+                                           const JavaRef<jobjectArray>& array) {
   SetPolicyValue(ConvertJavaStringToUTF8(env, policyKey),
                  ConvertJavaStringArrayToListValue(env, array).Pass());
 }
@@ -87,14 +88,15 @@
 // static
 scoped_ptr<base::ListValue> PolicyConverter::ConvertJavaStringArrayToListValue(
     JNIEnv* env,
-    jobjectArray array) {
-  DCHECK(array);
-  int length = static_cast<int>(env->GetArrayLength(array));
+    const JavaRef<jobjectArray>& array) {
+  DCHECK(!array.is_null());
+  int length = static_cast<int>(env->GetArrayLength(array.obj()));
   DCHECK_GE(length, 0) << "Invalid array length: " << length;
 
   scoped_ptr<base::ListValue> list_value(new base::ListValue());
   for (int i = 0; i < length; ++i) {
-    jstring str = static_cast<jstring>(env->GetObjectArrayElement(array, i));
+    jstring str =
+        static_cast<jstring>(env->GetObjectArrayElement(array.obj(), i));
     list_value->AppendString(ConvertJavaStringToUTF8(env, str));
   }
 
diff --git a/components/policy/core/browser/android/policy_converter.h b/components/policy/core/browser/android/policy_converter.h
index a8d2d70..b1fd336 100644
--- a/components/policy/core/browser/android/policy_converter.h
+++ b/components/policy/core/browser/android/policy_converter.h
@@ -42,21 +42,21 @@
 
   // To be called from Java:
   void SetPolicyBoolean(JNIEnv* env,
-                        jobject obj,
-                        jstring policyKey,
+                        const base::android::JavaRef<jobject>& obj,
+                        const base::android::JavaRef<jstring>& policyKey,
                         jboolean value);
   void SetPolicyInteger(JNIEnv* env,
-                        jobject obj,
-                        jstring policyKey,
+                        const base::android::JavaRef<jobject>& obj,
+                        const base::android::JavaRef<jstring>& policyKey,
                         jint value);
   void SetPolicyString(JNIEnv* env,
-                       jobject obj,
-                       jstring policyKey,
-                       jstring value);
+                       const base::android::JavaRef<jobject>& obj,
+                       const base::android::JavaRef<jstring>& policyKey,
+                       const base::android::JavaRef<jstring>& value);
   void SetPolicyStringArray(JNIEnv* env,
-                            jobject obj,
-                            jstring policyKey,
-                            jobjectArray value);
+                            const base::android::JavaRef<jobject>& obj,
+                            const base::android::JavaRef<jstring>& policyKey,
+                            const base::android::JavaRef<jobjectArray>& value);
 
   // Converts the passed in value to the type desired by the schema. If the
   // value is not convertible, it is returned unchanged, so the policy system
@@ -72,7 +72,7 @@
   // Public for testing.
   static scoped_ptr<base::ListValue> ConvertJavaStringArrayToListValue(
       JNIEnv* env,
-      jobjectArray array);
+      const base::android::JavaRef<jobjectArray>& array);
 
   // Register native methods
   static bool Register(JNIEnv* env);
diff --git a/components/policy/core/browser/android/policy_converter_unittest.cc b/components/policy/core/browser/android/policy_converter_unittest.cc
index 748eb5fe..ad78eef 100644
--- a/components/policy/core/browser/android/policy_converter_unittest.cc
+++ b/components/policy/core/browser/android/policy_converter_unittest.cc
@@ -16,6 +16,8 @@
 using base::ListValue;
 using base::StringValue;
 using base::Value;
+using base::android::JavaRef;
+using base::android::ScopedJavaLocalRef;
 
 namespace policy {
 namespace android {
@@ -61,8 +63,9 @@
   // Uses|PolicyConverter::ConvertJavaStringArrayToListValue| to convert the
   // passed in java array and serializes the result to JSON, to make it easier
   // to compare with EXPECT_EQ.
-  std::string ConvertJavaStringArrayToListValue(JNIEnv* env,
-                                                jobjectArray java_array) {
+  std::string ConvertJavaStringArrayToListValue(
+      JNIEnv* env,
+      const JavaRef<jobjectArray>& java_array) {
     scoped_ptr<ListValue> list =
         PolicyConverter::ConvertJavaStringArrayToListValue(env, java_array);
 
@@ -73,8 +76,9 @@
   }
 
   // Converts the passed in values to a java string array
-  jobjectArray MakeJavaStringArray(JNIEnv* env,
-                                   std::vector<std::string> values) {
+  ScopedJavaLocalRef<jobjectArray> MakeJavaStringArray(
+      JNIEnv* env,
+      std::vector<std::string> values) {
     jobjectArray java_array = (jobjectArray)env->NewObjectArray(
         values.size(), env->FindClass("java/lang/String"), nullptr);
     for (size_t i = 0; i < values.size(); i++) {
@@ -83,7 +87,7 @@
           base::android::ConvertUTF8ToJavaString(env, values[i]).obj());
     }
 
-    return java_array;
+    return ScopedJavaLocalRef<jobjectArray>(env, java_array);
   }
 
   Schema schema_;
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn
index e2fa0e4..682042d7 100644
--- a/components/search_engines/BUILD.gn
+++ b/components/search_engines/BUILD.gn
@@ -116,6 +116,7 @@
     "default_search_pref_migration_unittest.cc",
     "desktop_search_win_unittest.cc",
     "keyword_table_unittest.cc",
+    "search_engine_data_type_controller_unittest.cc",
     "search_host_to_urls_map_unittest.cc",
     "template_url_prepopulate_data_unittest.cc",
     "template_url_service_util_unittest.cc",
@@ -133,8 +134,10 @@
     "//components/policy",
     "//components/policy:policy_component_test_support",
     "//components/pref_registry:test_support",
+    "//components/sync_driver:test_support",
     "//components/webdata/common",
     "//sql",
+    "//sync:test_support_sync_api",
     "//testing/gmock",
     "//testing/gtest",
     "//url",
diff --git a/components/search_engines/prepopulated_engines.json b/components/search_engines/prepopulated_engines.json
index 64c3b877..4a40b4f 100644
--- a/components/search_engines/prepopulated_engines.json
+++ b/components/search_engines/prepopulated_engines.json
@@ -30,7 +30,7 @@
 
     // Increment this if you change the data in ways that mean users with
     // existing data should get a new version.
-    "kCurrentDataVersion": 85
+    "kCurrentDataVersion": 86
   },
 
   // The following engines are included in country lists and are added to the
@@ -580,6 +580,7 @@
       "suggest_url": "https://api.browser.yandex.by/suggest/get?part={searchTerms}",
       "image_url": "http://yandex.by/images/search/?rpt=imageview",
       "image_url_post_params": "upfile={google:imageThumbnail},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight},prg=1",
+      "new_tab_url": "https://www.yandex.by/chrome/newtab",
       "type": "SEARCH_ENGINE_YANDEX",
       "id": 15
     },
@@ -592,6 +593,7 @@
       "suggest_url": "https://api.browser.yandex.kz/suggest/get?part={searchTerms}",
       "image_url": "http://yandex.kz/images/search/?rpt=imageview",
       "image_url_post_params": "upfile={google:imageThumbnail},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight},prg=1",
+      "new_tab_url": "https://www.yandex.kz/chrome/newtab",
       "type": "SEARCH_ENGINE_YANDEX",
       "id": 15
     },
@@ -604,6 +606,7 @@
       "suggest_url": "https://api.browser.yandex.ru/suggest/get?part={searchTerms}",
       "image_url": "http://yandex.ru/images/search/?rpt=imageview",
       "image_url_post_params": "upfile={google:imageThumbnail},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight},prg=1",
+      "new_tab_url": "https://www.yandex.ru/chrome/newtab",
       "type": "SEARCH_ENGINE_YANDEX",
       "id": 15
     },
@@ -616,6 +619,7 @@
       "suggest_url": "https://api.browser.yandex.com.tr/suggest/get?part={searchTerms}",
       "image_url": "http://yandex.com.tr/gorsel/search?rpt=imageview",
       "image_url_post_params": "upfile={google:imageThumbnail},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight},prg=1",
+      "new_tab_url": "https://www.yandex.com.tr/chrome/newtab",
       "type": "SEARCH_ENGINE_YANDEX",
       "id": 15
     },
@@ -628,6 +632,7 @@
       "suggest_url": "https://api.browser.yandex.ua/suggest/get?part={searchTerms}",
       "image_url": "http://yandex.ua/images/search/?rpt=imageview",
       "image_url_post_params": "upfile={google:imageThumbnail},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight},prg=1",
+      "new_tab_url": "https://www.yandex.ua/chrome/newtab",
       "type": "SEARCH_ENGINE_YANDEX",
       "id": 15
     },
diff --git a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc b/components/search_engines/search_engine_data_type_controller_unittest.cc
similarity index 88%
rename from chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
rename to components/search_engines/search_engine_data_type_controller_unittest.cc
index 42c7b272..a569e5e3 100644
--- a/chrome/browser/sync/glue/search_engine_data_type_controller_unittest.cc
+++ b/components/search_engines/search_engine_data_type_controller_unittest.cc
@@ -8,21 +8,17 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
 #include "base/tracked_objects.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/search_engines/template_url_service_factory_test_util.h"
-#include "chrome/test/base/testing_profile.h"
 #include "components/search_engines/search_engine_data_type_controller.h"
+#include "components/search_engines/template_url_service.h"
 #include "components/sync_driver/data_type_controller_mock.h"
 #include "components/sync_driver/fake_generic_change_processor.h"
 #include "components/sync_driver/fake_sync_client.h"
 #include "components/sync_driver/sync_api_component_factory_mock.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "sync/api/fake_syncable_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using content::BrowserThread;
 using testing::_;
 using testing::DoAll;
 using testing::InvokeWithoutArgs;
@@ -38,7 +34,11 @@
  public:
   SyncSearchEngineDataTypeControllerTest()
       : sync_driver::FakeSyncClient(&profile_sync_factory_),
-        test_util_(&profile_) {}
+        template_url_service_(new TemplateURLService(nullptr, 0)) {
+    // Disallow the TemplateURLService from loading until
+    // PreloadTemplateURLService() is called .
+    template_url_service_->set_disable_load(true);
+  }
 
   // FakeSyncClient overrides.
   base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType(
@@ -47,12 +47,10 @@
   }
 
   void SetUp() override {
-    // Feed the DTC the profile so it is reused later.
-    // This allows us to control the associated TemplateURLService.
     search_engine_dtc_ = new SearchEngineDataTypeController(
-        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::ThreadTaskRunnerHandle::Get(),
         base::Bind(&base::DoNothing), this,
-        TemplateURLServiceFactory::GetForProfile(&profile_));
+        template_url_service_.get());
   }
 
   void TearDown() override {
@@ -62,9 +60,9 @@
   }
 
  protected:
-  // Pre-emptively get the TURL Service and make sure it is loaded.
   void PreloadTemplateURLService() {
-    test_util_.VerifyLoad();
+    template_url_service_->set_disable_load(false);
+    template_url_service_->Load();
   }
 
   void SetStartExpectations() {
@@ -86,9 +84,8 @@
     base::MessageLoop::current()->RunUntilIdle();
   }
 
-  content::TestBrowserThreadBundle thread_bundle_;
-  TestingProfile profile_;
-  TemplateURLServiceFactoryTestUtil test_util_;
+  base::MessageLoop message_loop_;
+  scoped_ptr<TemplateURLService> template_url_service_;
   scoped_refptr<SearchEngineDataTypeController> search_engine_dtc_;
   SyncApiComponentFactoryMock profile_sync_factory_;
   syncer::FakeSyncableService syncable_service_;
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
index 908f7d9..fac64b69 100644
--- a/components/search_engines/template_url_service.cc
+++ b/components/search_engines/template_url_service.cc
@@ -233,6 +233,7 @@
       provider_map_(new SearchHostToURLsMap),
       loaded_(false),
       load_failed_(false),
+      disable_load_(false),
       load_handle_(0),
       default_search_provider_(NULL),
       next_id_(kInvalidTemplateURLID + 1),
@@ -258,6 +259,7 @@
       provider_map_(new SearchHostToURLsMap),
       loaded_(false),
       load_failed_(false),
+      disable_load_(false),
       load_handle_(0),
       default_search_provider_(NULL),
       next_id_(kInvalidTemplateURLID + 1),
@@ -705,7 +707,7 @@
 }
 
 void TemplateURLService::Load() {
-  if (loaded_ || load_handle_)
+  if (loaded_ || load_handle_ || disable_load_)
     return;
 
   if (web_data_service_.get())
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h
index 2bac422..3797657 100644
--- a/components/search_engines/template_url_service.h
+++ b/components/search_engines/template_url_service.h
@@ -294,6 +294,9 @@
 
 #if defined(UNIT_TEST)
   void set_loaded(bool value) { loaded_ = value; }
+
+  // Turns Load() into a no-op.
+  void set_disable_load(bool value) { disable_load_ = value; }
 #endif
 
   // Whether or not the keywords have been loaded.
@@ -746,6 +749,9 @@
   // inconsistent state data anywhere.
   bool load_failed_;
 
+  // Whether Load() is disabled. True only in testing contexts.
+  bool disable_load_;
+
   // If non-zero, we're waiting on a load.
   KeywordWebDataService::Handle load_handle_;
 
diff --git a/components/sessions/core/in_memory_tab_restore_service.cc b/components/sessions/core/in_memory_tab_restore_service.cc
index b06b42d..27b6892 100644
--- a/components/sessions/core/in_memory_tab_restore_service.cc
+++ b/components/sessions/core/in_memory_tab_restore_service.cc
@@ -60,11 +60,6 @@
   return helper_.RemoveTabEntryById(id);
 }
 
-bool InMemoryTabRestoreService::RemoveTabByLastVisit(
-    const GURL& url, const base::Time& time) {
-  return helper_.RemoveTabByLastVisit(url, time);
-}
-
 std::vector<LiveTab*> InMemoryTabRestoreService::RestoreEntryById(
     LiveTabContext* context,
     SessionID::id_type id,
diff --git a/components/sessions/core/in_memory_tab_restore_service.h b/components/sessions/core/in_memory_tab_restore_service.h
index d5344d23..3e69f1b7 100644
--- a/components/sessions/core/in_memory_tab_restore_service.h
+++ b/components/sessions/core/in_memory_tab_restore_service.h
@@ -42,7 +42,6 @@
   std::vector<LiveTab*> RestoreMostRecentEntry(LiveTabContext* context,
                                                int host_desktop_type) override;
   Tab* RemoveTabEntryById(SessionID::id_type id) override;
-  bool RemoveTabByLastVisit(const GURL& url, const base::Time& time) override;
   std::vector<LiveTab*> RestoreEntryById(
       LiveTabContext* context,
       SessionID::id_type id,
diff --git a/components/sessions/core/persistent_tab_restore_service.cc b/components/sessions/core/persistent_tab_restore_service.cc
index 03d940e..3231b04 100644
--- a/components/sessions/core/persistent_tab_restore_service.cc
+++ b/components/sessions/core/persistent_tab_restore_service.cc
@@ -965,11 +965,6 @@
   return helper_.RemoveTabEntryById(id);
 }
 
-bool PersistentTabRestoreService::RemoveTabByLastVisit(
-    const GURL& url, const base::Time& time) {
-  return helper_.RemoveTabByLastVisit(url, time);
-}
-
 std::vector<LiveTab*> PersistentTabRestoreService::RestoreEntryById(
     LiveTabContext* context,
     SessionID::id_type id,
diff --git a/components/sessions/core/persistent_tab_restore_service.h b/components/sessions/core/persistent_tab_restore_service.h
index c84c417..587d5af 100644
--- a/components/sessions/core/persistent_tab_restore_service.h
+++ b/components/sessions/core/persistent_tab_restore_service.h
@@ -39,7 +39,6 @@
   std::vector<LiveTab*> RestoreMostRecentEntry(LiveTabContext* context,
                                                int host_desktop_type) override;
   Tab* RemoveTabEntryById(SessionID::id_type id) override;
-  bool RemoveTabByLastVisit(const GURL& url, const base::Time& time) override;
   std::vector<LiveTab*> RestoreEntryById(
       LiveTabContext* context,
       SessionID::id_type id,
diff --git a/components/sessions/core/tab_restore_service.h b/components/sessions/core/tab_restore_service.h
index c90ee02..c96ece31 100644
--- a/components/sessions/core/tab_restore_service.h
+++ b/components/sessions/core/tab_restore_service.h
@@ -168,14 +168,6 @@
   // passed to the caller.
   virtual Tab* RemoveTabEntryById(SessionID::id_type id) = 0;
 
-  // Removes the Tab whose navigation ended at a visit identified by the given
-  // |url| and |time|. If this Tab is not a separate Entry, but a part of
-  // a Window, it will be removed from that Window instead. If this leaves
-  // the Window with a single Tab, it will be converted to a Tab Entry.
-  // Returns true if a Tab with the given last visit |url| and |time| existed.
-  virtual bool RemoveTabByLastVisit(const GURL& url,
-                                    const base::Time& time) = 0;
-
   // Restores an entry by id. If there is no entry with an id matching |id|,
   // this does nothing. If |context| is NULL, this creates a new window for the
   // entry. |disposition| is respected, but the attributes (tabstrip index,
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc
index e75e142d..07651f9 100644
--- a/components/sessions/core/tab_restore_service_helper.cc
+++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -157,58 +157,6 @@
   return tab;
 }
 
-bool TabRestoreServiceHelper::RemoveTabByLastVisit(
-    const GURL& url, const base::Time& time) {
-  for (Entries::iterator entries_iterator = entries_.begin();
-       entries_iterator != entries_.end(); ++entries_iterator) {
-    Entry* entry = *entries_iterator;
-
-    if (entry->type == TabRestoreService::TAB) {
-      Tab* tab = static_cast<Tab*>(entry);
-      const sessions::SerializedNavigationEntry& last_navigation =
-          tab->navigations[tab->current_navigation_index];
-      if (last_navigation.virtual_url() == url &&
-          last_navigation.timestamp() == time) {
-        scoped_ptr<Entry> deleter(*entries_iterator);
-        entries_.erase(entries_iterator);
-        NotifyTabsChanged();
-        return true;
-      }
-    } else if (entry->type == TabRestoreService::WINDOW) {
-      TabRestoreService::Window* window =
-          static_cast<TabRestoreService::Window*>(entry);
-
-      for (std::vector<Tab>::iterator tabs_iterator = window->tabs.begin();
-           tabs_iterator != window->tabs.end(); ++tabs_iterator) {
-        const sessions::SerializedNavigationEntry& last_navigation =
-            tabs_iterator->navigations[tabs_iterator->current_navigation_index];
-        if (last_navigation.virtual_url() == url &&
-            last_navigation.timestamp() == time) {
-          int index = tabs_iterator - window->tabs.begin();
-          window->tabs.erase(tabs_iterator);
-
-          if (window->selected_tab_index > index)
-            --window->selected_tab_index;
-          else if (window->selected_tab_index == index)
-            window->selected_tab_index = 0;
-
-          if (window->tabs.size() == 1 && window->app_name.empty()) {
-            scoped_ptr<Entry> deleter(*entries_iterator);
-            *entries_iterator = new Tab(window->tabs[0]);
-          }
-
-          NotifyTabsChanged();
-          return true;
-        }
-      }
-    } else {
-      NOTREACHED();
-    }
-  }
-
-  return false;
-}
-
 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById(
     LiveTabContext* context,
     SessionID::id_type id,
diff --git a/components/sessions/core/tab_restore_service_helper.h b/components/sessions/core/tab_restore_service_helper.h
index 143d749..8fa5c827 100644
--- a/components/sessions/core/tab_restore_service_helper.h
+++ b/components/sessions/core/tab_restore_service_helper.h
@@ -80,7 +80,6 @@
   std::vector<LiveTab*> RestoreMostRecentEntry(LiveTabContext* context,
                                                int host_desktop_type);
   Tab* RemoveTabEntryById(SessionID::id_type id);
-  bool RemoveTabByLastVisit(const GURL& url, const base::Time& time);
   std::vector<LiveTab*> RestoreEntryById(LiveTabContext* context,
                                          SessionID::id_type id,
                                          int host_desktop_type,
diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm
index 22a09265..2278ffb 100644
--- a/components/signin/ios/browser/account_consistency_service.mm
+++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -207,6 +207,11 @@
   signin_manager_->AddObserver(this);
   web::BrowserState::GetActiveStateManager(browser_state_)->AddObserver(this);
   LoadFromPrefs();
+  if (signin_manager_->IsAuthenticated()) {
+    AddXChromeConnectedCookies();
+  } else {
+    RemoveXChromeConnectedCookies();
+  }
 }
 
 AccountConsistencyService::~AccountConsistencyService() {
diff --git a/components/startup_metric_utils/browser/pre_read_field_trial_utils_win.cc b/components/startup_metric_utils/browser/pre_read_field_trial_utils_win.cc
index b343535..d3de8c1 100644
--- a/components/startup_metric_utils/browser/pre_read_field_trial_utils_win.cc
+++ b/components/startup_metric_utils/browser/pre_read_field_trial_utils_win.cc
@@ -93,12 +93,16 @@
   base::win::RegKey(HKEY_CURRENT_USER, registry_path.c_str(), KEY_SET_VALUE)
       .DeleteKey(L"");
 
-  // Read variation params for the new group.
-  std::map<std::string, std::string> variation_params;
-  if (!variations::GetVariationParams(kPreReadFieldTrialName,
-                                      &variation_params))
+  // Get the new group name.
+  const base::string16 group = base::UTF8ToUTF16(
+      base::FieldTrialList::FindFullName(kPreReadFieldTrialName));
+  if (group.empty())
     return;
 
+  // Get variation params for the new group.
+  std::map<std::string, std::string> variation_params;
+  variations::GetVariationParams(kPreReadFieldTrialName, &variation_params);
+
   // Open the registry key.
   base::win::RegKey key(HKEY_CURRENT_USER, registry_path.c_str(),
                         KEY_SET_VALUE);
@@ -118,9 +122,7 @@
   }
 
   // Write the new group name in the registry.
-  key.WriteValue(L"", base::UTF8ToUTF16(base::FieldTrialList::FindFullName(
-                                            kPreReadFieldTrialName))
-                          .c_str());
+  key.WriteValue(L"", group.c_str());
 }
 
 void RegisterPreReadSyntheticFieldTrial(
diff --git a/components/test_runner/event_sender.cc b/components/test_runner/event_sender.cc
index 84a7955..fbe0e43 100644
--- a/components/test_runner/event_sender.cc
+++ b/components/test_runner/event_sender.cc
@@ -67,21 +67,6 @@
   return WebMouseEvent::ButtonNone;
 }
 
-int GetWebMouseEventModifierForButton(WebMouseEvent::Button button) {
-  switch (button) {
-    case WebMouseEvent::ButtonNone:
-      return 0;
-    case WebMouseEvent::ButtonLeft:
-      return WebMouseEvent::LeftButtonDown;
-    case WebMouseEvent::ButtonMiddle:
-      return WebMouseEvent::MiddleButtonDown;
-    case WebMouseEvent::ButtonRight:
-      return WebMouseEvent::RightButtonDown;
-  }
-  NOTREACHED();
-  return 0;
-}
-
 void InitMouseEvent(WebInputEvent::Type t,
                     WebMouseEvent::Button b,
                     const WebPoint& pos,
@@ -91,7 +76,7 @@
                     WebMouseEvent* e) {
   e->type = t;
   e->button = b;
-  e->modifiers = modifiers | GetWebMouseEventModifierForButton(b);
+  e->modifiers = modifiers;
   e->x = pos.x;
   e->y = pos.y;
   e->globalX = pos.x;
@@ -1159,6 +1144,7 @@
   if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
     view_->mouseCaptureLost();
   pressed_button_ = WebMouseEvent::ButtonNone;
+  modifiers_ = 0;
   is_drag_mode_ = true;
   force_layout_on_events_ = true;
 
diff --git a/content/browser/accessibility/accessibility_event_recorder_mac.mm b/content/browser/accessibility/accessibility_event_recorder_mac.mm
index 95967f43..cf30701 100644
--- a/content/browser/accessibility/accessibility_event_recorder_mac.mm
+++ b/content/browser/accessibility/accessibility_event_recorder_mac.mm
@@ -9,11 +9,9 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/mac/foundation_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
+#include "base/mac/scoped_cftyperef.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 
 namespace content {
@@ -39,10 +37,11 @@
       AXUIElementRef element, NSString* attribute_name);
 
   // The AXUIElement for the Chrome application.
-  AXUIElementRef application_;
+  base::ScopedCFTypeRef<AXUIElementRef> application_;
 
   // The AXObserver we use to monitor AX notifications.
-  AXObserverRef observer_ref_;
+  base::ScopedCFTypeRef<AXObserverRef> observer_ref_;
+  CFRunLoopSourceRef observer_run_loop_source_;
 };
 
 // Callback function registered using AXObserverCreate.
@@ -64,18 +63,17 @@
 
 AccessibilityEventRecorderMac::AccessibilityEventRecorderMac(
     BrowserAccessibilityManager* manager)
-    : AccessibilityEventRecorder(manager),
-      observer_ref_(0) {
+    : AccessibilityEventRecorder(manager), observer_run_loop_source_(NULL) {
   // Get Chrome's process id.
   int pid = [[NSProcessInfo processInfo] processIdentifier];
-  if (kAXErrorSuccess != AXObserverCreate(
-      pid, EventReceivedThunk, &observer_ref_)) {
+  if (kAXErrorSuccess != AXObserverCreate(pid, EventReceivedThunk,
+                                          observer_ref_.InitializeInto())) {
     LOG(FATAL) << "Failed to create AXObserverRef";
   }
 
   // Get an AXUIElement for the Chrome application.
-  application_ = AXUIElementCreateApplication(pid);
-  if (!application_)
+  application_.reset(AXUIElementCreateApplication(pid));
+  if (!application_.get())
     LOG(FATAL) << "Failed to create AXUIElement for application.";
 
   // Add the notifications we care about to the observer.
@@ -92,58 +90,59 @@
   AddNotification(@"AXRowExpanded");
 
   // Add the observer to the current message loop.
-  CFRunLoopAddSource(
-      [[NSRunLoop currentRunLoop] getCFRunLoop],
-      AXObserverGetRunLoopSource(observer_ref_),
-      kCFRunLoopDefaultMode);
+  observer_run_loop_source_ = AXObserverGetRunLoopSource(observer_ref_.get());
+  CFRunLoopAddSource(CFRunLoopGetCurrent(), observer_run_loop_source_,
+                     kCFRunLoopDefaultMode);
 }
 
 AccessibilityEventRecorderMac::~AccessibilityEventRecorderMac() {
-  CFRelease(application_);
-  CFRelease(observer_ref_);
+  CFRunLoopRemoveSource(CFRunLoopGetCurrent(), observer_run_loop_source_,
+                        kCFRunLoopDefaultMode);
 }
 
 void AccessibilityEventRecorderMac::AddNotification(NSString* notification) {
-  AXObserverAddNotification(observer_ref_,
-                            application_,
-                            static_cast<CFStringRef>(notification),
-                            this);
+  AXObserverAddNotification(observer_ref_, application_,
+                            base::mac::NSToCFCast(notification), this);
 }
 
 std::string AccessibilityEventRecorderMac::GetAXAttributeValue(
-    AXUIElementRef element, NSString* attribute_name) {
-  CFTypeRef value;
+    AXUIElementRef element,
+    NSString* attribute_name) {
+  base::ScopedCFTypeRef<CFTypeRef> value;
   AXError err = AXUIElementCopyAttributeValue(
-      element, static_cast<CFStringRef>(attribute_name), &value);
+      element, base::mac::NSToCFCast(attribute_name), value.InitializeInto());
   if (err != kAXErrorSuccess)
     return std::string();
-  return base::SysNSStringToUTF8(
-      base::mac::CFToNSCast(static_cast<CFStringRef>(value)));
+
+  CFStringRef value_string = base::mac::CFCast<CFStringRef>(value.get());
+  if (value_string)
+    return base::SysCFStringRefToUTF8(value_string);
+
+  // TODO(dmazzoni): And if it's not a string, can we return something better?
+  return std::string();
 }
 
-void AccessibilityEventRecorderMac::EventReceived(
-    AXUIElementRef element,
-    CFStringRef notification) {
-  std::string notification_str = base::SysNSStringToUTF8(
-      base::mac::CFToNSCast(notification));
+void AccessibilityEventRecorderMac::EventReceived(AXUIElementRef element,
+                                                  CFStringRef notification) {
+  std::string notification_str = base::SysCFStringRefToUTF8(notification);
   std::string role = GetAXAttributeValue(element, NSAccessibilityRoleAttribute);
   if (role.empty())
     return;
-  std::string log = base::StringPrintf("%s on %s",
-      notification_str.c_str(), role.c_str());
+  std::string log =
+      base::StringPrintf("%s on %s", notification_str.c_str(), role.c_str());
 
-  std::string title = GetAXAttributeValue(element,
-                                          NSAccessibilityTitleAttribute);
+  std::string title =
+      GetAXAttributeValue(element, NSAccessibilityTitleAttribute);
   if (!title.empty())
     log += base::StringPrintf(" AXTitle=\"%s\"", title.c_str());
 
-  std::string description = GetAXAttributeValue(element,
-                                          NSAccessibilityDescriptionAttribute);
+  std::string description =
+      GetAXAttributeValue(element, NSAccessibilityDescriptionAttribute);
   if (!description.empty())
     log += base::StringPrintf(" AXDescription=\"%s\"", description.c_str());
 
-  std::string value = GetAXAttributeValue(element,
-                                          NSAccessibilityValueAttribute);
+  std::string value =
+      GetAXAttributeValue(element, NSAccessibilityValueAttribute);
   if (!value.empty())
     log += base::StringPrintf(" AXValue=\"%s\"", value.c_str());
 
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 16aee5d..21b33438 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -948,7 +948,9 @@
   RunHtmlTest(FILE_PATH_LITERAL("input-tel.html"));
 }
 
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputText) {
+// Fails on Android GN bot, see crbug.com/569542.
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+                       MAYBE(AccessibilityInputText)) {
   RunHtmlTest(FILE_PATH_LITERAL("input-text.html"));
 }
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index b2e4eea9..b574596 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -103,10 +103,6 @@
 #include "ui/gl/gl_surface.h"
 #endif
 
-#if defined(OS_MACOSX)
-#include "media/base/mac/avfoundation_glue.h"
-#endif
-
 #if defined(OS_MACOSX) && !defined(OS_IOS)
 #include "base/memory/memory_pressure_monitor_mac.h"
 #include "content/browser/bootstrap_sandbox_manager_mac.h"
@@ -747,15 +743,6 @@
   }
 #endif
 
-#if defined(OS_MACOSX)
-  {
-    // Initialize AVFoundation if supported, for audio and video.
-    TRACE_EVENT0("startup",
-                 "BrowserMainLoop::CreateThreads:InitializeAVFoundation");
-    AVFoundationGlue::InitializeAVFoundation();
-  }
-#endif
-
 #if defined(OS_MACOSX) && !defined(OS_IOS)
   // The WindowResizeHelper allows the UI thread to wait on specific renderer
   // and GPU messages from the IO thread. Initializing it before the IO thread
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 61dbe6c3..7d2ee45 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -802,6 +802,9 @@
   SendQueuedMessages();
 
   delegate_->DidAttach(GetGuestProxyRoutingID());
+  RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
+      web_contents()->GetRenderWidgetHostView());
+  rwhv->RegisterSurfaceNamespaceId();
 
   if (!use_cross_process_frames)
     has_render_view_ = true;
@@ -827,6 +830,12 @@
   // it's attached again.
   attached_ = false;
 
+  RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
+       web_contents()->GetRenderWidgetHostView());
+  // If the guest is terminated, our host may already be gone.
+  if (rwhv)
+    rwhv->UnregisterSurfaceNamespaceId();
+
   delegate_->DidDetach();
 }
 
diff --git a/content/browser/device_monitor_mac.mm b/content/browser/device_monitor_mac.mm
index 36e9a571..c135011e 100644
--- a/content/browser/device_monitor_mac.mm
+++ b/content/browser/device_monitor_mac.mm
@@ -531,6 +531,12 @@
 void DeviceMonitorMac::StartMonitoring(
     const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
+  // We're on the UI thread so let's try to initialize AVFoundation and then
+  // see if it's supported.  IsAVFoundationSupported can't implicitly initialize
+  // the library since it can be called on different threads.
+  AVFoundationGlue::InitializeAVFoundation();
+
   if (AVFoundationGlue::IsAVFoundationSupported()) {
     // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458404
     // is fixed.
diff --git a/content/browser/download/mhtml_generation_manager.cc b/content/browser/download/mhtml_generation_manager.cc
index bd432ee..c63405e 100644
--- a/content/browser/download/mhtml_generation_manager.cc
+++ b/content/browser/download/mhtml_generation_manager.cc
@@ -4,17 +4,24 @@
 
 #include "content/browser/download/mhtml_generation_manager.h"
 
+#include <map>
+#include <queue>
+
 #include "base/bind.h"
 #include "base/files/file.h"
+#include "base/guid.h"
+#include "base/rand_util.h"
 #include "base/scoped_observer.h"
 #include "base/stl_util.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/common/frame_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "content/public/browser/web_contents.h"
-#include "content/common/view_messages.h"
 
 namespace content {
 
@@ -29,9 +36,15 @@
 
   GenerateMHTMLCallback callback() const { return callback_; }
 
-  // Sends IPC to the renderer, asking for MHTML generation.
+  // Sends IPC to the renderer, asking for MHTML generation of the next frame.
+  //
   // Returns true if the message was sent successfully; false otherwise.
-  bool SendToRenderView();
+  bool SendToNextRenderFrame();
+
+  // Indicates if more calls to SendToNextRenderFrame are needed.
+  bool HasMoreFramesToProcess() const {
+    return !pending_frame_tree_node_ids_.empty();
+  }
 
   // Close the file on the file thread and respond back on the UI thread with
   // file size.
@@ -44,7 +57,15 @@
   void RenderProcessHostDestroyed(RenderProcessHost* host) override;
 
  private:
+  static std::string GenerateMHTMLBoundaryMarker();
   static int64 CloseFileOnFileThread(base::File file);
+  void AddFrame(RenderFrameHost* render_frame_host);
+
+  // Creates a new map with values (content ids) the same as in
+  // |frame_tree_node_to_content_id_| map, but with the keys translated from
+  // frame_tree_node_id into a |site_instance|-specific routing_id.
+  std::map<int, std::string> CreateFrameRoutingIdToContentId(
+      SiteInstance* site_instance);
 
   // Id used to map renderer responses to jobs.
   // See also MHTMLGenerationManager::id_to_job_ map.
@@ -53,9 +74,15 @@
   // The handle to the file the MHTML is saved to for the browser process.
   base::File browser_file_;
 
-  // The IDs mapping to a specific contents.
-  int process_id_;
-  int routing_id_;
+  // The IDs of frames we still need to process.
+  std::queue<int> pending_frame_tree_node_ids_;
+
+  // Map from frames into content ids (see WebPageSerializer::generateMHTMLParts
+  // for more details about what "content ids" are and how they are used).
+  std::map<int, std::string> frame_tree_node_to_content_id_;
+
+  // MIME multipart boundary to use in the MHTML doc.
+  std::string mhtml_boundary_marker_;
 
   // The callback to call once generation is complete.
   GenerateMHTMLCallback callback_;
@@ -71,33 +98,69 @@
                                  WebContents* web_contents,
                                  GenerateMHTMLCallback callback)
     : job_id_(job_id),
-      process_id_(web_contents->GetRenderProcessHost()->GetID()),
-      routing_id_(web_contents->GetRenderViewHost()->GetRoutingID()),
+      mhtml_boundary_marker_(GenerateMHTMLBoundaryMarker()),
       callback_(callback),
       observed_renderer_process_host_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  web_contents->ForEachFrame(base::Bind(
+      &MHTMLGenerationManager::Job::AddFrame,
+      base::Unretained(this)));  // Safe because ForEachFrame is synchronous.
+
+  // Main frame needs to be processed first.
+  DCHECK(!pending_frame_tree_node_ids_.empty());
+  DCHECK(FrameTreeNode::GloballyFindByID(pending_frame_tree_node_ids_.front())
+             ->parent() == nullptr);
 }
 
 MHTMLGenerationManager::Job::~Job() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
-bool MHTMLGenerationManager::Job::SendToRenderView() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(browser_file_.IsValid());
+std::map<int, std::string>
+MHTMLGenerationManager::Job::CreateFrameRoutingIdToContentId(
+    SiteInstance* site_instance) {
+  std::map<int, std::string> result;
+  for (const auto& it : frame_tree_node_to_content_id_) {
+    int ftn_id = it.first;
+    const std::string& content_id = it.second;
 
-  RenderViewHost* rvh = RenderViewHost::FromID(process_id_, routing_id_);
-  if (!rvh) {  // The contents went away.
-    return false;
+    FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(ftn_id);
+    if (!ftn)
+      continue;
+
+    int routing_id =
+        ftn->render_manager()->GetRoutingIdForSiteInstance(site_instance);
+    if (routing_id == MSG_ROUTING_NONE)
+      continue;
+
+    result[routing_id] = content_id;
   }
+  return result;
+}
 
-  observed_renderer_process_host_.Add(rvh->GetMainFrame()->GetProcess());
+bool MHTMLGenerationManager::Job::SendToNextRenderFrame() {
+  DCHECK(browser_file_.IsValid());
+  DCHECK_LT(0u, pending_frame_tree_node_ids_.size());
+
+  int frame_tree_node_id = pending_frame_tree_node_ids_.front();
+  pending_frame_tree_node_ids_.pop();
+  bool is_last_frame = pending_frame_tree_node_ids_.empty();
+
+  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+  if (!ftn)  // The contents went away.
+    return false;
+  RenderFrameHost* rfh = ftn->current_frame_host();
+
+  // Get notified if the target of the IPC message dies between responding.
+  observed_renderer_process_host_.RemoveAll();
+  observed_renderer_process_host_.Add(rfh->GetProcess());
 
   IPC::PlatformFileForTransit renderer_file = IPC::GetFileHandleForProcess(
-      browser_file_.GetPlatformFile(), rvh->GetProcess()->GetHandle(),
+      browser_file_.GetPlatformFile(), rfh->GetProcess()->GetHandle(),
       false);  // |close_source_handle|.
-  rvh->Send(
-      new ViewMsg_SavePageAsMHTML(rvh->GetRoutingID(), job_id_, renderer_file));
+  rfh->Send(new FrameMsg_SerializeAsMHTML(
+      rfh->GetRoutingID(), job_id_, renderer_file, mhtml_boundary_marker_,
+      CreateFrameRoutingIdToContentId(rfh->GetSiteInstance()), is_last_frame));
   return true;
 }
 
@@ -109,6 +172,17 @@
   MHTMLGenerationManager::GetInstance()->RenderProcessExited(this);
 }
 
+void MHTMLGenerationManager::Job::AddFrame(RenderFrameHost* render_frame_host) {
+  auto* rfhi = static_cast<RenderFrameHostImpl*>(render_frame_host);
+  int frame_tree_node_id = rfhi->frame_tree_node()->frame_tree_node_id();
+  pending_frame_tree_node_ids_.push(frame_tree_node_id);
+
+  std::string guid = base::GenerateGUID();
+  std::string content_id = base::StringPrintf("<frame-%d-%s@mhtml.blink>",
+                                              frame_tree_node_id, guid.c_str());
+  frame_tree_node_to_content_id_[frame_tree_node_id] = content_id;
+}
+
 void MHTMLGenerationManager::Job::RenderProcessHostDestroyed(
     RenderProcessHost* host) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -140,6 +214,25 @@
   return file_size;
 }
 
+// static
+std::string MHTMLGenerationManager::Job::GenerateMHTMLBoundaryMarker() {
+  // TODO(lukasza): Introduce and use a shared helper function in
+  // net/base/mime_util.h instead of having the ad-hoc code below.
+
+  // Trying to generate random boundaries similar to IE/UnMHT
+  // (ex: ----=_NextPart_000_001B_01CC157B.96F808A0).
+  uint8_t random_values[10];
+  base::RandBytes(&random_values, sizeof(random_values));
+
+  std::string result("----=_NextPart_000_");
+  result += base::HexEncode(random_values + 0, 2);
+  result += '_';
+  result += base::HexEncode(random_values + 2, 4);
+  result += '.';
+  result += base::HexEncode(random_values + 6, 4);
+  return result;
+}
+
 MHTMLGenerationManager* MHTMLGenerationManager::GetInstance() {
   return base::Singleton<MHTMLGenerationManager>::get();
 }
@@ -165,21 +258,43 @@
                  job_id));
 }
 
-void MHTMLGenerationManager::OnSavedPageAsMHTML(
+void MHTMLGenerationManager::OnSavedFrameAsMHTML(
     int job_id,
     bool mhtml_generation_in_renderer_succeeded) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  JobStatus job_status = mhtml_generation_in_renderer_succeeded
-                             ? JobStatus::SUCCESS
-                             : JobStatus::FAILURE;
-  JobFinished(job_id, job_status);
+
+  if (!mhtml_generation_in_renderer_succeeded) {
+    JobFinished(job_id, JobStatus::FAILURE);
+    return;
+  }
+
+  Job* job = FindJob(job_id);
+  if (!job)
+    return;
+
+  if (job->HasMoreFramesToProcess()) {
+    if (!job->SendToNextRenderFrame()) {
+      JobFinished(job_id, JobStatus::FAILURE);
+    }
+    return;
+  }
+
+  JobFinished(job_id, JobStatus::SUCCESS);
 }
 
 // static
 base::File MHTMLGenerationManager::CreateFile(const base::FilePath& file_path) {
   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
-  base::File browser_file(
-      file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+
+  // SECURITY NOTE: A file descriptor to the file created below will be passed
+  // to multiple renderer processes which (in out-of-process iframes mode) can
+  // act on behalf of separate web principals.  Therefore it is important to
+  // only allow writing to the file and forbid reading from the file (as this
+  // would allow reading content generated by other renderers / other web
+  // principals).
+  uint32 file_flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE;
+
+  base::File browser_file(file_path, file_flags);
   if (!browser_file.IsValid()) {
     LOG(ERROR) << "Failed to create file to save MHTML at: " <<
         file_path.value();
@@ -203,7 +318,7 @@
 
   job->set_browser_file(browser_file.Pass());
 
-  if (!job->SendToRenderView()) {
+  if (!job->SendToNextRenderFrame()) {
     JobFinished(job_id, JobStatus::FAILURE);
   }
 }
diff --git a/content/browser/download/mhtml_generation_manager.h b/content/browser/download/mhtml_generation_manager.h
index e13ca600..1c0a51eb 100644
--- a/content/browser/download/mhtml_generation_manager.h
+++ b/content/browser/download/mhtml_generation_manager.h
@@ -37,10 +37,10 @@
                  const base::FilePath& file_path,
                  const GenerateMHTMLCallback& callback);
 
-  // Handler for ViewHostMsg_SavedPageAsMHTML (a notification from the renderer
-  // that the MHTML generation finished).
-  void OnSavedPageAsMHTML(int job_id,
-                          bool mhtml_generation_in_renderer_succeeded);
+  // Handler for FrameHostMsg_SerializeAsMHTMLResponse (a notification from the
+  // renderer that the MHTML generation finished for a single frame).
+  void OnSavedFrameAsMHTML(int job_id,
+                           bool mhtml_generation_in_renderer_succeeded);
 
  private:
   friend struct base::DefaultSingletonTraits<MHTMLGenerationManager>;
diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc
index 01874d0..26884297 100644
--- a/content/browser/download/save_file_manager.cc
+++ b/content/browser/download/save_file_manager.cc
@@ -47,6 +47,7 @@
 }
 
 SaveFile* SaveFileManager::LookupSaveFile(int save_item_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   SaveFileMap::iterator it = save_file_map_.find(save_item_id);
   return it == save_file_map_.end() ? NULL : it->second;
 }
@@ -165,7 +166,7 @@
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&SaveFileManager::OnStartSave, this, info));
+      base::Bind(&SaveFileManager::OnStartSave, this, *info));
 }
 
 // We do forward an update to the UI thread here, since we do not use timer to
@@ -219,23 +220,23 @@
 
 // Notifications sent from the file thread and run on the UI thread.
 
-void SaveFileManager::OnStartSave(const SaveFileCreateInfo* info) {
+void SaveFileManager::OnStartSave(const SaveFileCreateInfo& info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   SavePackage* save_package = GetSavePackageFromRenderIds(
-      info->render_process_id, info->render_frame_routing_id);
+      info.render_process_id, info.render_frame_routing_id);
   if (!save_package) {
     // Cancel this request.
-    SendCancelRequest(info->save_item_id);
+    SendCancelRequest(info.save_item_id);
     return;
   }
 
   // Insert started saving job to tracking list.
-  SavePackageMap::iterator sit = packages_.find(info->save_item_id);
+  SavePackageMap::iterator sit = packages_.find(info.save_item_id);
   DCHECK(sit == packages_.end());
-  packages_[info->save_item_id] = save_package;
+  packages_[info.save_item_id] = save_package;
 
   // Forward this message to SavePackage.
-  save_package->StartSave(info);
+  save_package->StartSave(&info);
 }
 
 void SaveFileManager::OnUpdateSaveProgress(int save_item_id,
diff --git a/content/browser/download/save_file_manager.h b/content/browser/download/save_file_manager.h
index 9b0abe5..906acf4 100644
--- a/content/browser/download/save_file_manager.h
+++ b/content/browser/download/save_file_manager.h
@@ -161,7 +161,7 @@
 
   // Lookup the SaveManager for this WebContents' saving browser context and
   // inform it the saving job has been started.
-  void OnStartSave(const SaveFileCreateInfo* info);
+  void OnStartSave(const SaveFileCreateInfo& info);
   // Update the SavePackage with the current state of a started saving job.
   // If the SavePackage for this saving job is gone, cancel the request.
   void OnUpdateSaveProgress(int save_item_id,
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
index 4682969..ae742bc 100644
--- a/content/browser/download/save_package.cc
+++ b/content/browser/download/save_package.cc
@@ -547,7 +547,7 @@
 }
 
 // We have received a message from SaveFileManager about a new saving job. We
-// create a SaveItem and store it in our in_progress list.
+// find a SaveItem and store it in our in_progress list.
 void SavePackage::StartSave(const SaveFileCreateInfo* info) {
   DCHECK(info && !info->url.is_empty());
 
diff --git a/content/browser/frame_host/debug_urls.cc b/content/browser/frame_host/debug_urls.cc
index 8459559..f095f8e 100644
--- a/content/browser/frame_host/debug_urls.cc
+++ b/content/browser/frame_host/debug_urls.cc
@@ -77,11 +77,26 @@
 
 void HandleKaskoDebugURL() {
 #if defined(KASKO)
+  // Signature of the exported crash key setting function.
+  using SetCrashKeyValueImplPtr = void(__cdecl *)(const wchar_t*,
+                                                  const wchar_t*);
   // Signature of an enhanced crash reporting function.
-  typedef void(__cdecl * ReportCrashWithProtobufPtr)(EXCEPTION_POINTERS*,
+  using ReportCrashWithProtobufPtr = void(__cdecl *)(EXCEPTION_POINTERS*,
                                                      const char*);
 
   HMODULE exe_hmodule = ::GetModuleHandle(NULL);
+
+  // First, set a crash key using the exported function reserved for Kasko
+  // clients (SyzyASAN for now).
+  SetCrashKeyValueImplPtr set_crash_key_value_impl =
+      reinterpret_cast<SetCrashKeyValueImplPtr>(
+          ::GetProcAddress(exe_hmodule, "SetCrashKeyValueImpl"));
+  if (set_crash_key_value_impl)
+    set_crash_key_value_impl(L"kasko-set-crash-key-value-impl", L"true");
+  else
+    NOTREACHED();
+
+  // Next, invoke a crash report via Kasko.
   ReportCrashWithProtobufPtr report_crash_with_protobuf =
       reinterpret_cast<ReportCrashWithProtobufPtr>(
           ::GetProcAddress(exe_hmodule, "ReportCrashWithProtobuf"));
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 18a88eb4..64cd0966 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -20,6 +20,7 @@
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/download/mhtml_generation_manager.h"
 #include "content/browser/frame_host/cross_process_frame_connector.h"
 #include "content/browser/frame_host/cross_site_transferring_request.h"
 #include "content/browser/frame_host/frame_mojo_shell.h"
@@ -541,6 +542,8 @@
     IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
     IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress,
                         OnDidChangeLoadProgress)
+    IPC_MESSAGE_HANDLER(FrameHostMsg_SerializeAsMHTMLResponse,
+                        OnSerializeAsMHTMLResponse)
 #if defined(OS_MACOSX) || defined(OS_ANDROID)
     IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
     IPC_MESSAGE_HANDLER(FrameHostMsg_HidePopup, OnHidePopup)
@@ -1704,6 +1707,10 @@
   frame_tree_node_->DidChangeLoadProgress(load_progress);
 }
 
+void RenderFrameHostImpl::OnSerializeAsMHTMLResponse(int job_id, bool success) {
+  MHTMLGenerationManager::GetInstance()->OnSavedFrameAsMHTML(job_id, success);
+}
+
 #if defined(OS_MACOSX) || defined(OS_ANDROID)
 void RenderFrameHostImpl::OnShowPopup(
     const FrameHostMsg_ShowPopup_Params& params) {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index dc05dbf0..3508bbee 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -6,6 +6,7 @@
 #define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_IMPL_H_
 
 #include <map>
+#include <string>
 #include <vector>
 
 #include "base/callback.h"
@@ -609,6 +610,7 @@
   void OnDidStartLoading(bool to_different_document);
   void OnDidStopLoading();
   void OnDidChangeLoadProgress(double load_progress);
+  void OnSerializeAsMHTMLResponse(int job_id, bool success);
 
 #if defined(OS_MACOSX) || defined(OS_ANDROID)
   void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params);
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index 8971b07f..f3ba93da 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -14,6 +14,8 @@
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/frame_host/render_widget_host_view_guest.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
 #include "content/common/browser_plugin/browser_plugin_messages.h"
 #include "content/common/frame_messages.h"
 #include "content/common/gpu/gpu_messages.h"
@@ -56,16 +58,9 @@
       // |guest| is NULL during test.
       guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()),
       platform_view_(platform_view) {
-#if defined(USE_AURA)
-  gesture_recognizer_.reset(ui::GestureRecognizer::Create());
-  gesture_recognizer_->AddGestureEventHelper(this);
-#endif  // defined(USE_AURA)
 }
 
 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
-#if defined(USE_AURA)
-  gesture_recognizer_->RemoveGestureEventHelper(this);
-#endif  // defined(USE_AURA)
 }
 
 bool RenderWidgetHostViewGuest::OnMessageReceivedFromEmbedder(
@@ -95,8 +90,22 @@
   // The two sizes may fall out of sync if we switch RenderWidgetHostViews,
   // resize, and then switch page, as is the case with interstitial pages.
   // NOTE: |guest_| is NULL in unit tests.
-  if (guest_)
+  if (guest_) {
     SetSize(guest_->web_contents()->GetViewBounds().size());
+    // Since we were last shown, our renderer may have had a different surface
+    // set (e.g. showing an interstitial), so we resend our current surface to
+    // the renderer.
+    if (!surface_id_.is_null()) {
+      cc::SurfaceSequence sequence = cc::SurfaceSequence(
+          id_allocator_->id_namespace(), next_surface_sequence_++);
+      GetSurfaceManager()
+          ->GetSurfaceForId(surface_id_)
+          ->AddDestructionDependency(sequence);
+      guest_->SetChildFrameSurface(surface_id_, current_surface_size_,
+                                   current_surface_scale_factor_,
+                                   sequence);
+    }
+  }
   host_->WasShown(ui::LatencyInfo());
 }
 
@@ -133,30 +142,44 @@
 #if defined(USE_AURA)
 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
     const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
-  // TODO(fsamuel): Currently we will only take this codepath if the guest has
-  // requested touch events. A better solution is to always forward touchpresses
-  // to the embedder process to target a BrowserPlugin, and then route all
-  // subsequent touch points of that touchdown to the appropriate guest until
-  // that touch point is released.
-  ScopedVector<ui::TouchEvent> events;
-  if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES))
-    return;
-
-  ui::EventResult result = (ack_result ==
-      INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
-  for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
-      end = events.end(); iter != end; ++iter)  {
-    if (!gesture_recognizer_->ProcessTouchEventPreDispatch(*iter, this))
-      continue;
-
-    scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
-    gestures.reset(gesture_recognizer_->AckTouchEvent(
-        (*iter)->unique_event_id(), result, this));
-    ProcessGestures(gestures.get());
-  }
+  // TODO(tdresser): Since all ProcessAckedTouchEvent() uses is the event id,
+  // don't pass the full event object here. https://crbug.com/550581.
+  GetOwnerRenderWidgetHostView()->ProcessAckedTouchEvent(touch, ack_result);
 }
 #endif
 
+void RenderWidgetHostViewGuest::ProcessTouchEvent(
+    const blink::WebTouchEvent& event,
+    const ui::LatencyInfo& latency) {
+  if (event.type == blink::WebInputEvent::TouchStart) {
+    DCHECK(guest_->GetOwnerRenderWidgetHostView());
+    RenderWidgetHostImpl* embedder = static_cast<RenderWidgetHostImpl*>(
+        guest_->GetOwnerRenderWidgetHostView()->GetRenderWidgetHost());
+    if (!embedder->GetView()->HasFocus())
+      embedder->GetView()->Focus();
+  }
+
+  host_->ForwardTouchEventWithLatencyInfo(event, latency);
+}
+
+void RenderWidgetHostViewGuest::RegisterSurfaceNamespaceId() {
+  DCHECK(host_);
+  if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
+    RenderWidgetHostInputEventRouter* router =
+        host_->delegate()->GetInputEventRouter();
+    if (!router->is_registered(GetSurfaceIdNamespace()))
+      router->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this);
+  }
+}
+
+void RenderWidgetHostViewGuest::UnregisterSurfaceNamespaceId() {
+  DCHECK(host_);
+  if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
+    host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
+        GetSurfaceIdNamespace());
+  }
+}
+
 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
   if (!guest_)
     return gfx::Rect();
@@ -538,32 +561,6 @@
   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
 }
 
-bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
-    ui::GestureConsumer* consumer) {
-  CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
-  return true;
-}
-
-void RenderWidgetHostViewGuest::DispatchGestureEvent(
-    ui::GestureEvent* event) {
-  ForwardGestureEventToRenderer(event);
-}
-
-void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
-    ui::TouchEvent* event) {
-  if (!host_)
-    return;
-
-  blink::WebTouchEvent cancel_event;
-  // TODO(rbyers): This event has no touches in it.  Don't we need to know what
-  // touches are currently active in order to cancel them all properly?
-  WebTouchEventTraits::ResetType(blink::WebInputEvent::TouchCancel,
-                                 event->time_stamp().InSecondsF(),
-                                 &cancel_event);
-
-  host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
-}
-
 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
     ui::GestureEvent* gesture) {
 #if defined(USE_AURA)
diff --git a/content/browser/frame_host/render_widget_host_view_guest.h b/content/browser/frame_host/render_widget_host_view_guest.h
index d2a6466..d345ac9e 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/content/browser/frame_host/render_widget_host_view_guest.h
@@ -39,8 +39,7 @@
 // the relevant calls to the platform view.
 class CONTENT_EXPORT RenderWidgetHostViewGuest
     : public RenderWidgetHostViewChildFrame,
-      public ui::GestureConsumer,
-      public ui::GestureEventHelper {
+      public ui::GestureConsumer {
  public:
   RenderWidgetHostViewGuest(
       RenderWidgetHost* widget,
@@ -97,6 +96,11 @@
   void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
                               InputEventAckState ack_result) override;
 #endif
+  void ProcessTouchEvent(const blink::WebTouchEvent& event,
+                         const ui::LatencyInfo& latency) override;
+  void RegisterSurfaceNamespaceId();
+  void UnregisterSurfaceNamespaceId();
+
   bool LockMouse() override;
   void UnlockMouse() override;
   void GetScreenInfo(blink::WebScreenInfo* results) override;
@@ -139,11 +143,6 @@
   void GestureEventAck(const blink::WebGestureEvent& event,
                        InputEventAckState ack_result) override;
 
-  // Overridden from ui::GestureEventHelper.
-  bool CanDispatchToConsumer(ui::GestureConsumer* consumer) override;
-  void DispatchGestureEvent(ui::GestureEvent* event) override;
-  void DispatchCancelTouchEvent(ui::TouchEvent* event) override;
-
  protected:
   friend class RenderWidgetHostView;
 
@@ -172,9 +171,6 @@
   // RenderWidgetHostViewGuest mostly only cares about stuff related to
   // compositing, the rest are directly forwared to this |platform_view_|.
   base::WeakPtr<RenderWidgetHostViewBase> platform_view_;
-#if defined(USE_AURA)
-  scoped_ptr<ui::GestureRecognizer> gesture_recognizer_;
-#endif
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuest);
 };
 
diff --git a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
new file mode 100644
index 0000000..fedda0fe
--- /dev/null
+++ b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
@@ -0,0 +1,345 @@
+// Copyright 2015 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/renderer_host/dwrite_font_proxy_message_filter_win.h"
+
+#include <dwrite.h>
+#include <shlobj.h>
+
+#include <set>
+#include <utility>
+
+#include "base/callback_helpers.h"
+#include "base/i18n/case_conversion.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/common/dwrite_font_proxy_messages.h"
+#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/win/direct_write.h"
+
+namespace mswr = Microsoft::WRL;
+
+namespace content {
+
+namespace {
+
+// This enum is used to define the buckets for an enumerated UMA histogram.
+// Hence,
+//   (a) existing enumerated constants should never be deleted or reordered, and
+//   (b) new constants should only be appended at the end of the enumeration.
+enum DirectWriteFontLoaderType {
+  FILE_SYSTEM_FONT_DIR = 0,
+  FILE_OUTSIDE_SANDBOX = 1,
+  OTHER_LOADER = 2,
+
+  FONT_LOADER_TYPE_MAX_VALUE
+};
+
+void LogLoaderType(DirectWriteFontLoaderType loader_type) {
+  UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.LoaderType", loader_type,
+                            FONT_LOADER_TYPE_MAX_VALUE);
+}
+
+const wchar_t* kFontsToIgnore[] = {
+    // "Gill Sans Ultra Bold" turns into an Ultra Bold weight "Gill Sans" in
+    // DirectWrite, but most users don't have any other weights. The regular
+    // weight font is named "Gill Sans MT", but that ends up in a different
+    // family with that name. On Mac, there's a "Gill Sans" with various
+    // weights, so CSS authors use { 'font-family': 'Gill Sans',
+    // 'Gill Sans MT', ... } and because of the DirectWrite family futzing,
+    // they end up with an Ultra Bold font, when they just wanted "Gill Sans".
+    // Mozilla implemented a more complicated hack where they effectively
+    // rename the Ultra Bold font to "Gill Sans MT Ultra Bold", but because the
+    // Ultra Bold font is so ugly anyway, we simply ignore it. See
+    // http://www.microsoft.com/typography/fonts/font.aspx?FMID=978 for a
+    // picture of the font, and the file name. We also ignore "Gill Sans Ultra
+    // Bold Condensed".
+    L"gilsanub.ttf", L"gillubcd.ttf",
+};
+
+base::string16 GetWindowsFontsPath() {
+  std::vector<base::char16> font_path_chars;
+  // SHGetSpecialFolderPath requires at least MAX_PATH characters.
+  font_path_chars.resize(MAX_PATH);
+  BOOL result = SHGetSpecialFolderPath(nullptr /* hwndOwner - reserved */,
+                                       font_path_chars.data(), CSIDL_FONTS,
+                                       FALSE /* fCreate */);
+  DCHECK(result);
+  return base::i18n::FoldCase(font_path_chars.data());
+}
+
+}  // namespace
+
+DWriteFontProxyMessageFilter::DWriteFontProxyMessageFilter()
+    : BrowserMessageFilter(DWriteFontProxyMsgStart),
+      windows_fonts_path_(GetWindowsFontsPath()) {}
+
+DWriteFontProxyMessageFilter::~DWriteFontProxyMessageFilter() = default;
+
+bool DWriteFontProxyMessageFilter::OnMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(DWriteFontProxyMessageFilter, message)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_FindFamily, OnFindFamily)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyCount, OnGetFamilyCount)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyNames, OnGetFamilyNames)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFontFiles, OnGetFontFiles)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void DWriteFontProxyMessageFilter::OverrideThreadForMessage(
+    const IPC::Message& message,
+    content::BrowserThread::ID* thread) {
+  if (IPC_MESSAGE_CLASS(message) == DWriteFontProxyMsgStart)
+    *thread = BrowserThread::FILE;
+}
+
+void DWriteFontProxyMessageFilter::OnFindFamily(
+    const base::string16& family_name,
+    UINT32* family_index) {
+  InitializeDirectWrite();
+  TRACE_EVENT0("dwrite", "FontProxyHost::OnFindFamily");
+  DCHECK(collection_);
+  *family_index = UINT32_MAX;
+  if (collection_) {
+    BOOL exists = FALSE;
+    UINT32 index = UINT32_MAX;
+    HRESULT hr =
+        collection_->FindFamilyName(family_name.data(), &index, &exists);
+    if (SUCCEEDED(hr) && exists)
+      *family_index = index;
+  }
+}
+
+void DWriteFontProxyMessageFilter::OnGetFamilyCount(UINT32* count) {
+  InitializeDirectWrite();
+  TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFamilyCount");
+  DCHECK(collection_);
+  if (!collection_)
+    *count = 0;
+  else
+    *count = collection_->GetFontFamilyCount();
+}
+
+void DWriteFontProxyMessageFilter::OnGetFamilyNames(
+    UINT32 family_index,
+    std::vector<DWriteStringPair>* family_names) {
+  InitializeDirectWrite();
+  TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFamilyNames");
+  DCHECK(collection_);
+  if (!collection_)
+    return;
+
+  TRACE_EVENT0("dwrite", "FontProxyHost::DoGetFamilyNames");
+
+  mswr::ComPtr<IDWriteFontFamily> family;
+  HRESULT hr = collection_->GetFontFamily(family_index, &family);
+  if (!SUCCEEDED(hr))
+    return;
+
+  mswr::ComPtr<IDWriteLocalizedStrings> localized_names;
+  hr = family->GetFamilyNames(&localized_names);
+  if (!SUCCEEDED(hr))
+    return;
+
+  size_t string_count = localized_names->GetCount();
+
+  std::vector<base::char16> locale;
+  std::vector<base::char16> name;
+  for (size_t index = 0; index < string_count; ++index) {
+    UINT32 length = 0;
+    hr = localized_names->GetLocaleNameLength(index, &length);
+    if (!SUCCEEDED(hr))
+      return;
+    ++length;  // Reserve space for the null terminator.
+    locale.resize(length);
+    hr = localized_names->GetLocaleName(index, locale.data(), length);
+    if (!SUCCEEDED(hr))
+      return;
+    DCHECK_EQ(L'\0', locale[length - 1]);
+
+    length = 0;
+    hr = localized_names->GetStringLength(index, &length);
+    if (!SUCCEEDED(hr))
+      return;
+    ++length;  // Reserve space for the null terminator.
+    name.resize(length);
+    hr = localized_names->GetString(index, name.data(), length);
+    if (!SUCCEEDED(hr))
+      return;
+    DCHECK_EQ(L'\0', name[length - 1]);
+
+    // Would be great to use emplace_back instead.
+    family_names->push_back(std::pair<base::string16, base::string16>(
+        base::string16(locale.data()), base::string16(name.data())));
+  }
+}
+
+void DWriteFontProxyMessageFilter::OnGetFontFiles(
+    uint32_t family_index,
+    std::vector<base::string16>* file_paths) {
+  InitializeDirectWrite();
+  TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFontFiles");
+  DCHECK(collection_);
+  if (!collection_)
+    return;
+
+  mswr::ComPtr<IDWriteFontFamily> family;
+  HRESULT hr = collection_->GetFontFamily(family_index, &family);
+  if (!SUCCEEDED(hr))
+    return;
+
+  UINT32 font_count = family->GetFontCount();
+
+  std::set<base::string16> path_set;
+  // Iterate through all the fonts in the family, and all the files for those
+  // fonts. If anything goes wrong, bail on the entire family to avoid having
+  // a partially-loaded font family.
+  for (UINT32 font_index = 0; font_index < font_count; ++font_index) {
+    mswr::ComPtr<IDWriteFont> font;
+    hr = family->GetFont(font_index, &font);
+    if (!SUCCEEDED(hr))
+      return;
+
+    AddFilesForFont(&path_set, font.Get());
+  }
+
+  file_paths->assign(path_set.begin(), path_set.end());
+}
+
+void DWriteFontProxyMessageFilter::InitializeDirectWrite() {
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  if (direct_write_initialized_)
+    return;
+  direct_write_initialized_ = true;
+
+  mswr::ComPtr<IDWriteFactory> factory;
+  gfx::win::CreateDWriteFactory(&factory);
+  if (factory == nullptr) {
+    // We won't be able to load fonts, but we should still return messages so
+    // renderers don't hang if they for some reason send us a font message.
+    return;
+  }
+
+  HRESULT hr = factory->GetSystemFontCollection(&collection_);
+  DCHECK(SUCCEEDED(hr));
+}
+
+bool DWriteFontProxyMessageFilter::AddFilesForFont(
+    std::set<base::string16>* path_set,
+    IDWriteFont* font) {
+  mswr::ComPtr<IDWriteFontFace> font_face;
+  HRESULT hr;
+  hr = font->CreateFontFace(&font_face);
+  if (!SUCCEEDED(hr))
+    return false;
+
+  UINT32 file_count;
+  hr = font_face->GetFiles(&file_count, nullptr);
+  if (!SUCCEEDED(hr))
+    return false;
+
+  std::vector<mswr::ComPtr<IDWriteFontFile>> font_files;
+  font_files.resize(file_count);
+  hr = font_face->GetFiles(
+      &file_count, reinterpret_cast<IDWriteFontFile**>(font_files.data()));
+  if (!SUCCEEDED(hr))
+    return false;
+
+  for (unsigned int file_index = 0; file_index < file_count; ++file_index) {
+    mswr::ComPtr<IDWriteFontFileLoader> loader;
+    hr = font_files[file_index]->GetLoader(&loader);
+    if (!SUCCEEDED(hr))
+      return false;
+
+    mswr::ComPtr<IDWriteLocalFontFileLoader> local_loader;
+    hr = loader.CopyTo(local_loader.GetAddressOf());  // QueryInterface.
+
+    if (hr == E_NOINTERFACE) {
+      // We could get here if the system font collection contains fonts that
+      // are backed by something other than files in the system fonts folder.
+      // I don't think that is actually possible, so for now we'll just
+      // ignore it (result will be that we'll be unable to match any styles
+      // for this font, forcing blink/skia to fall back to whatever font is
+      // next). If we get telemetry indicating that this case actually
+      // happens, we can implement this by exposing the loader via ipc. That
+      // will likely by loading the font data into shared memory, although we
+      // could proxy the stream reads directly instead.
+      LogLoaderType(OTHER_LOADER);
+      DCHECK(false);
+      return false;
+    } else if (!SUCCEEDED(hr)) {
+      return false;
+    }
+
+    if (!AddLocalFile(path_set, local_loader.Get(),
+                      font_files[file_index].Get())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool DWriteFontProxyMessageFilter::AddLocalFile(
+    std::set<base::string16>* path_set,
+    IDWriteLocalFontFileLoader* local_loader,
+    IDWriteFontFile* font_file) {
+  HRESULT hr;
+  const void* key;
+  UINT32 key_size;
+  hr = font_file->GetReferenceKey(&key, &key_size);
+  if (!SUCCEEDED(hr))
+    return false;
+
+  UINT32 path_length = 0;
+  hr = local_loader->GetFilePathLengthFromKey(key, key_size, &path_length);
+  if (!SUCCEEDED(hr))
+    return false;
+  ++path_length;  // Reserve space for the null terminator.
+  std::vector<base::char16> file_path_chars;
+  file_path_chars.resize(path_length);
+  hr = local_loader->GetFilePathFromKey(key, key_size, file_path_chars.data(),
+                                        path_length);
+  if (!SUCCEEDED(hr))
+    return false;
+
+  base::string16 file_path = base::i18n::FoldCase(file_path_chars.data());
+  if (!base::StartsWith(file_path, windows_fonts_path_,
+                        base::CompareCase::SENSITIVE)) {
+    // Skip loading fonts from outside the system fonts directory, since
+    // these families will not be accessible to the renderer process. If
+    // this turns out to be a common case, we can either grant the renderer
+    // access to these files (not sure if this is actually possible), or
+    // load the file data ourselves and hand it to the renderer.
+    LogLoaderType(FILE_OUTSIDE_SANDBOX);
+    NOTREACHED();  // Not yet implemented.
+    return false;
+  }
+
+  // Refer to comments in kFontsToIgnore for this block.
+  for (const auto& file_to_ignore : kFontsToIgnore) {
+    // Ok to do ascii comparison since the strings we are looking for are
+    // all ascii.
+    if (base::EndsWith(file_path, file_to_ignore,
+                       base::CompareCase::INSENSITIVE_ASCII)) {
+      // Unlike most other cases in this function, we do not abort loading
+      // the entire family, since we want to specifically ignore particular
+      // font styles and load the rest of the family if it exists. The
+      // renderer can deal with a family with zero files if that ends up
+      // being the case.
+      return true;
+    }
+  }
+
+  LogLoaderType(FILE_SYSTEM_FONT_DIR);
+  path_set->insert(file_path);
+  return true;
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h
new file mode 100644
index 0000000..25ef9b6
--- /dev/null
+++ b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h
@@ -0,0 +1,65 @@
+// Copyright 2015 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_RENDERER_HOST_DWRITE_FONT_PROXY_MESSAGE_FILTER_WIN_H_
+#define CONTENT_BROWSER_RENDERER_HOST_DWRITE_FONT_PROXY_MESSAGE_FILTER_WIN_H_
+
+#include <dwrite.h>
+#include <wrl.h>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+// Implements a message filter that handles the dwrite font proxy messages.
+// If DWrite is enabled, calls into the system font collection to obtain
+// results. Otherwise, acts as if the system collection contains no fonts.
+class CONTENT_EXPORT DWriteFontProxyMessageFilter
+    : public BrowserMessageFilter {
+ public:
+  DWriteFontProxyMessageFilter();
+
+  // BrowserMessageFilter:
+  bool OnMessageReceived(const IPC::Message& message) override;
+  void OverrideThreadForMessage(const IPC::Message& message,
+                                content::BrowserThread::ID* thread) override;
+
+ protected:
+  ~DWriteFontProxyMessageFilter() override;
+
+  void OnFindFamily(const base::string16& family_name, UINT32* family_index);
+  void OnGetFamilyCount(UINT32* count);
+  void OnGetFamilyNames(
+      UINT32 family_index,
+      std::vector<std::pair<base::string16, base::string16>>* family_names);
+  void OnGetFontFiles(UINT32 family_index,
+                      std::vector<base::string16>* file_paths);
+
+  void InitializeDirectWrite();
+
+ private:
+  bool AddFilesForFont(std::set<base::string16>* path_set, IDWriteFont* font);
+  bool AddLocalFile(std::set<base::string16>* path_set,
+                    IDWriteLocalFontFileLoader* local_loader,
+                    IDWriteFontFile* font_file);
+
+ private:
+  bool direct_write_initialized_ = false;
+  Microsoft::WRL::ComPtr<IDWriteFontCollection> collection_;
+  base::string16 windows_fonts_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(DWriteFontProxyMessageFilter);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_DWRITE_FONT_PROXY_MESSAGE_FILTER_WIN_H_
diff --git a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc
new file mode 100644
index 0000000..65359e9
--- /dev/null
+++ b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright 2015 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/renderer_host/dwrite_font_proxy_message_filter_win.h"
+
+#include <dwrite.h>
+
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/common/dwrite_font_proxy_messages.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "ipc/ipc_message_macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/win/direct_write.h"
+
+namespace mswr = Microsoft::WRL;
+
+namespace content {
+
+namespace {
+
+class FilterWithFakeSender : public DWriteFontProxyMessageFilter {
+ public:
+  bool Send(IPC::Message* msg) override {
+    EXPECT_EQ(nullptr, reply_message_.get());
+    reply_message_.reset(msg);
+    return true;
+  }
+
+  IPC::Message* GetReply() { return reply_message_.get(); }
+
+  void ResetReply() { reply_message_.reset(nullptr); }
+
+ private:
+  ~FilterWithFakeSender() override = default;
+
+  scoped_ptr<IPC::Message> reply_message_;
+};
+
+class DWriteFontProxyMessageFilterUnitTest : public testing::Test {
+ public:
+  DWriteFontProxyMessageFilterUnitTest() {
+    filter_ = new FilterWithFakeSender();
+  }
+
+  void Send(IPC::SyncMessage* message) {
+    std::unique_ptr<IPC::SyncMessage> deleter(message);
+    scoped_ptr<IPC::MessageReplyDeserializer> serializer(
+        message->GetReplyDeserializer());
+    filter_->OnMessageReceived(*message);
+    base::RunLoop().RunUntilIdle();
+    ASSERT_NE(nullptr, filter_->GetReply());
+    serializer->SerializeOutputParameters(*(filter_->GetReply()));
+  }
+
+  scoped_refptr<FilterWithFakeSender> filter_;
+  content::TestBrowserThreadBundle thread_bundle_;
+};
+
+TEST_F(DWriteFontProxyMessageFilterUnitTest, GetFamilyCount) {
+  if (!gfx::win::ShouldUseDirectWrite())
+    return;
+  UINT32 family_count = 0;
+  Send(new DWriteFontProxyMsg_GetFamilyCount(&family_count));
+  EXPECT_NE(0u, family_count);  // Assume there's some fonts on the test system.
+}
+
+TEST_F(DWriteFontProxyMessageFilterUnitTest, FindFamily) {
+  if (!gfx::win::ShouldUseDirectWrite())
+    return;
+  UINT32 arial_index = 0;
+  Send(new DWriteFontProxyMsg_FindFamily(L"Arial", &arial_index));
+  EXPECT_NE(UINT_MAX, arial_index);
+
+  filter_->ResetReply();
+  UINT32 times_index = 0;
+  Send(new DWriteFontProxyMsg_FindFamily(L"Times New Roman", &times_index));
+  EXPECT_NE(UINT_MAX, times_index);
+  EXPECT_NE(arial_index, times_index);
+
+  filter_->ResetReply();
+  UINT32 unknown_index = 0;
+  Send(new DWriteFontProxyMsg_FindFamily(L"Not a font family", &unknown_index));
+  EXPECT_EQ(UINT_MAX, unknown_index);
+}
+
+TEST_F(DWriteFontProxyMessageFilterUnitTest, GetFamilyNames) {
+  if (!gfx::win::ShouldUseDirectWrite())
+    return;
+  UINT32 arial_index = 0;
+  Send(new DWriteFontProxyMsg_FindFamily(L"Arial", &arial_index));
+  filter_->ResetReply();
+
+  std::vector<DWriteStringPair> names;
+  Send(new DWriteFontProxyMsg_GetFamilyNames(arial_index, &names));
+
+  EXPECT_LT(0u, names.size());
+  for (const auto& pair : names) {
+    EXPECT_STRNE(L"", pair.first.c_str());
+    EXPECT_STRNE(L"", pair.second.c_str());
+  }
+}
+
+TEST_F(DWriteFontProxyMessageFilterUnitTest, GetFamilyNamesIndexOutOfBounds) {
+  if (!gfx::win::ShouldUseDirectWrite())
+    return;
+  std::vector<DWriteStringPair> names;
+  UINT32 invalid_index = 1000000;
+  Send(new DWriteFontProxyMsg_GetFamilyNames(invalid_index, &names));
+
+  EXPECT_EQ(0u, names.size());
+}
+
+TEST_F(DWriteFontProxyMessageFilterUnitTest, GetFontFiles) {
+  if (!gfx::win::ShouldUseDirectWrite())
+    return;
+  UINT32 arial_index = 0;
+  Send(new DWriteFontProxyMsg_FindFamily(L"Arial", &arial_index));
+  filter_->ResetReply();
+
+  std::vector<base::string16> files;
+  Send(new DWriteFontProxyMsg_GetFontFiles(arial_index, &files));
+
+  EXPECT_LT(0u, files.size());
+  for (const base::string16& file : files) {
+    EXPECT_STRNE(L"", file.c_str());
+  }
+}
+
+TEST_F(DWriteFontProxyMessageFilterUnitTest, GetFontFilesIndexOutOfBounds) {
+  if (!gfx::win::ShouldUseDirectWrite())
+    return;
+  std::vector<base::string16> files;
+  UINT32 invalid_index = 1000000;
+  Send(new DWriteFontProxyMsg_GetFontFiles(invalid_index, &files));
+
+  EXPECT_EQ(0u, files.size());
+}
+
+}  // namespace
+
+}  // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index a91f8d56..82af565 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -38,6 +38,10 @@
 #endif
 #endif
 
+#if defined(OS_MACOSX)
+#include "media/base/mac/avfoundation_glue.h"
+#endif
+
 namespace {
 
 // Compares two VideoCaptureFormat by checking smallest frame_size area, then
@@ -192,6 +196,14 @@
   DCHECK(listener_);
   DCHECK_EQ(stream_type, MEDIA_DEVICE_VIDEO_CAPTURE);
 
+#if defined(OS_MACOSX)
+  if (NeedToInitializeCaptureDeviceApi(stream_type)) {
+    InitializeCaptureDeviceApiOnUIThread(
+        base::Bind(&VideoCaptureManager::EnumerateDevices, this, stream_type));
+    return;
+  }
+#endif
+
   // Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument
   // for another callback to OnDevicesInfoEnumerated() to be run in the current
   // loop, i.e. IO loop. Pass a timer for UMA histogram collection.
@@ -329,6 +341,14 @@
   DCHECK(entry_it != devices_.end());
   DeviceEntry* entry =  (*entry_it);
 
+#if defined(OS_MACOSX)
+  if (NeedToInitializeCaptureDeviceApi(entry->stream_type)) {
+    InitializeCaptureDeviceApiOnUIThread(
+        base::Bind(&VideoCaptureManager::HandleQueuedStartRequest, this));
+    return;
+  }
+#endif
+
   DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = "
            << entry->id << " start id = " << entry->serial_id;
 
@@ -932,4 +952,30 @@
 #endif
 }
 
+#if defined(OS_MACOSX)
+void VideoCaptureManager::OnDeviceLayerInitialized(
+    const base::Closure& and_then) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  capture_device_api_initialized_ = true;
+  and_then.Run();
+}
+
+bool VideoCaptureManager::NeedToInitializeCaptureDeviceApi(
+    MediaStreamType stream_type) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  return !capture_device_api_initialized_ &&
+         stream_type == MEDIA_DEVICE_VIDEO_CAPTURE;
+}
+
+void VideoCaptureManager::InitializeCaptureDeviceApiOnUIThread(
+    const base::Closure& and_then) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTaskAndReply(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&AVFoundationGlue::InitializeAVFoundation),
+      base::Bind(&VideoCaptureManager::OnDeviceLayerInitialized, this,
+                 and_then));
+}
+#endif
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h
index 7399bfe..54bd1ff 100644
--- a/content/browser/renderer_host/media/video_capture_manager.h
+++ b/content/browser/renderer_host/media/video_capture_manager.h
@@ -236,6 +236,26 @@
       media::VideoCaptureDevice* device,
       gfx::NativeViewId window_id);
 
+#if defined(OS_MACOSX)
+  // Called on the IO thread after the device layer has been initialized on Mac.
+  // Sets |capture_device_api_initialized_| to true and then executes and_then.
+  void OnDeviceLayerInitialized(const base::Closure& and_then);
+
+  // Returns true if the current operation needs to be preempted by a call to
+  // InitializeCaptureDeviceApiOnUIThread.
+  // Called on the IO thread.
+  bool NeedToInitializeCaptureDeviceApi(MediaStreamType stream_type);
+
+  // Called on the IO thread to do async initialization of the capture api.
+  // Once initialization is done, and_then will be run on the IO thread.
+  void InitializeCaptureDeviceApiOnUIThread(const base::Closure& and_then);
+
+  // Due to initialization issues with AVFoundation and QTKit on Mac, we need
+  // to make sure we initialize the APIs on the UI thread before we can reliably
+  // use them.  This variable is only checked and set on the IO thread.
+  bool capture_device_api_initialized_ = false;
+#endif
+
   // The message loop of media stream device thread, where VCD's live.
   scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
 
diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 87e723a..53fa76d 100644
--- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -21,7 +21,9 @@
 
 using ::testing::_;
 using ::testing::AnyNumber;
+using ::testing::DoAll;
 using ::testing::InSequence;
+using ::testing::InvokeWithoutArgs;
 using ::testing::Return;
 using ::testing::SaveArg;
 
@@ -72,6 +74,8 @@
   void SetUp() override {
     listener_.reset(new MockMediaStreamProviderListener());
     message_loop_.reset(new base::MessageLoopForIO);
+    ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
+                                           message_loop_.get()));
     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
                                            message_loop_.get()));
     vcm_ = new VideoCaptureManager(scoped_ptr<media::VideoCaptureDeviceFactory>(
@@ -156,6 +160,7 @@
   scoped_refptr<VideoCaptureManager> vcm_;
   scoped_ptr<MockMediaStreamProviderListener> listener_;
   scoped_ptr<base::MessageLoop> message_loop_;
+  scoped_ptr<BrowserThreadImpl> ui_thread_;
   scoped_ptr<BrowserThreadImpl> io_thread_;
   scoped_ptr<MockFrameObserver> frame_observer_;
   media::FakeVideoCaptureDeviceFactory* video_capture_device_factory_;
@@ -503,18 +508,21 @@
 // Open and start a device, close it before calling Stop.
 TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
   StreamDeviceInfoArray devices;
+  base::RunLoop run_loop;
 
   InSequence s;
   EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
-      .WillOnce(SaveArg<1>(&devices));
+      .WillOnce(
+          DoAll(SaveArg<1>(&devices),
+                InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)));
   EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _));
   EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _));
 
   vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
 
   // Wait to get device callback.
-  message_loop_->RunUntilIdle();
-
+  run_loop.Run();
+  ASSERT_FALSE(devices.empty());
   int video_session_id = vcm_->Open(devices.front());
 
   VideoCaptureControllerID client_id = StartClient(video_session_id, true);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 6d7ee1ff..9197d0c 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -57,7 +57,6 @@
 #include "content/browser/device_sensors/device_orientation_message_filter.h"
 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
 #include "content/browser/dom_storage/dom_storage_message_filter.h"
-#include "content/browser/download/mhtml_generation_manager.h"
 #include "content/browser/fileapi/chrome_blob_storage_context.h"
 #include "content/browser/fileapi/fileapi_message_filter.h"
 #include "content/browser/frame_host/render_frame_message_filter.h"
@@ -1456,6 +1455,7 @@
     // --in-process-webgl.
     switches::kUseGL,
     switches::kUseMobileUserAgent,
+    switches::kUseNewMediaCache,
     switches::kUseNormalPriorityForTileTaskWorkerThreads,
     switches::kV,
     switches::kVideoThreads,
@@ -1675,7 +1675,6 @@
                           SuddenTerminationChanged)
       IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
                           OnUserMetricsRecordAction)
-      IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML)
       IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK)
 #if defined(ENABLE_WEBRTC)
       IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer,
@@ -2579,12 +2578,6 @@
   holder->Release(old_route_id);
 }
 
-void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) {
-  bool mhtml_generation_in_renderer_succeeded = data_size >= 0;
-  MHTMLGenerationManager::GetInstance()->OnSavedPageAsMHTML(
-      job_id, mhtml_generation_in_renderer_succeeded);
-}
-
 void RenderProcessHostImpl::OnGpuSwitched() {
   // We are updating all widgets including swapped out ones.
   scoped_ptr<RenderWidgetHostIterator> widgets(
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index fed2f7adb..52167df 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -297,7 +297,6 @@
   void OnShutdownRequest();
   void SuddenTerminationChanged(bool enabled);
   void OnUserMetricsRecordAction(const std::string& action);
-  void OnSavedPageAsMHTML(int job_id, int64 mhtml_file_size);
   void OnCloseACK(int old_route_id);
 
   // Generates a command line to be used to spawn a renderer and appends the
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 49053b97..449b2f68 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -10,7 +10,8 @@
 
 namespace content {
 
-RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter() {}
+RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
+    : current_touch_target_(nullptr), active_touches_(0) {}
 
 RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() {
   owner_map_.clear();
@@ -67,6 +68,44 @@
   target->ProcessMouseWheelEvent(*event);
 }
 
+void RenderWidgetHostInputEventRouter::RouteTouchEvent(
+    RenderWidgetHostViewBase* root_view,
+    blink::WebTouchEvent* event,
+    const ui::LatencyInfo& latency) {
+  switch (event->type) {
+    case blink::WebInputEvent::TouchStart: {
+      if (!active_touches_) {
+        // Since this is the first touch, it defines the target for the rest
+        // of this sequence.
+        DCHECK(!current_touch_target_);
+        gfx::Point transformed_point;
+        gfx::Point original_point(event->touches[0].position.x,
+                                  event->touches[0].position.y);
+        current_touch_target_ =
+            FindEventTarget(root_view, original_point, &transformed_point);
+      }
+      ++active_touches_;
+      current_touch_target_->ProcessTouchEvent(*event, latency);
+      break;
+    }
+    case blink::WebInputEvent::TouchMove:
+      DCHECK(current_touch_target_);
+      current_touch_target_->ProcessTouchEvent(*event, latency);
+      break;
+    case blink::WebInputEvent::TouchEnd:
+    case blink::WebInputEvent::TouchCancel:
+      DCHECK(active_touches_);
+      DCHECK(current_touch_target_);
+      current_touch_target_->ProcessTouchEvent(*event, latency);
+      --active_touches_;
+      if (!active_touches_)
+        current_touch_target_ = nullptr;
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
 void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner(
     uint32_t id,
     RenderWidgetHostViewBase* owner) {
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index 3a2a967..54a10cfc 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -13,12 +13,17 @@
 namespace blink {
 class WebMouseEvent;
 class WebMouseWheelEvent;
+class WebTouchEvent;
 }
 
 namespace gfx {
 class Point;
 }
 
+namespace ui {
+class LatencyInfo;
+}
+
 namespace content {
 
 class RenderWidgetHostViewBase;
@@ -38,10 +43,17 @@
                        blink::WebMouseEvent* event);
   void RouteMouseWheelEvent(RenderWidgetHostViewBase* root_view,
                             blink::WebMouseWheelEvent* event);
+  void RouteTouchEvent(RenderWidgetHostViewBase* root_view,
+                       blink::WebTouchEvent *event,
+                       const ui::LatencyInfo& latency);
 
   void AddSurfaceIdNamespaceOwner(uint32_t id, RenderWidgetHostViewBase* owner);
   void RemoveSurfaceIdNamespaceOwner(uint32_t id);
 
+  bool is_registered(uint32_t id) {
+    return owner_map_.find(id) != owner_map_.end();
+  }
+
  private:
   RenderWidgetHostViewBase* FindEventTarget(RenderWidgetHostViewBase* root_view,
                                             const gfx::Point& point,
@@ -50,6 +62,8 @@
   typedef base::hash_map<uint32_t, RenderWidgetHostViewBase*>
       SurfaceIdNamespaceOwnerMap;
   SurfaceIdNamespaceOwnerMap owner_map_;
+  RenderWidgetHostViewBase* current_touch_target_;
+  int active_touches_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
 };
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index fd2a94cc..83d7118 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -45,6 +45,7 @@
 #include "content/browser/renderer_host/web_input_event_aura.h"
 #include "content/common/gpu/client/gl_helper.h"
 #include "content/common/gpu/gpu_messages.h"
+#include "content/common/site_isolation_policy.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/overscroll_configuration.h"
@@ -857,6 +858,23 @@
   return true;
 }
 
+bool RenderWidgetHostViewAura::ShouldRouteEvent(const ui::Event* event) const {
+  // We should route an event in two cases:
+  // 1) Mouse events are routed only if cross-process frames are possible.
+  // 2) Touch events are always routed. In the absence of a BrowserPlugin
+  //    we expect the routing to always send the event to this view. If
+  //    one or more BrowserPlugins are present, then the event may be targeted
+  //    to one of them, or this view. This allows GuestViews to have access to
+  //    them while still forcing pinch-zoom to be handled by the top-level
+  //    frame. TODO(wjmaclean): At present, this doesn't work for OOPIF, but
+  //    it should be a simple extension to modify RenderWidgetHostViewChildFrame
+  //    in a similar manner to RenderWidgetHostViewGuest.
+  bool result = host_->delegate() && host_->delegate()->GetInputEventRouter();
+  if (event->IsMouseEvent())
+    result = result && SiteIsolationPolicy::AreCrossProcessFramesPossible();
+  return result;
+}
+
 void RenderWidgetHostViewAura::HandleParentBoundsChanged() {
   SnapToPhysicalPixelBoundary();
 #if defined(OS_WIN)
@@ -2127,7 +2145,7 @@
     blink::WebMouseWheelEvent mouse_wheel_event =
         MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
     if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) {
-      if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
+      if (ShouldRouteEvent(event)) {
         host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
             this, &mouse_wheel_event);
       } else {
@@ -2146,7 +2164,7 @@
 
       blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
       ModifyEventMovementAndCoords(&mouse_event);
-      if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
+      if (ShouldRouteEvent(event)) {
         host_->delegate()->GetInputEventRouter()->RouteMouseEvent(this,
                                                                   &mouse_event);
       } else {
@@ -2219,6 +2237,12 @@
   host_->ForwardWheelEvent(event);
 }
 
+void RenderWidgetHostViewAura::ProcessTouchEvent(
+    const blink::WebTouchEvent& event,
+    const ui::LatencyInfo& latency) {
+  host_->ForwardTouchEventWithLatencyInfo(event, latency);
+}
+
 void RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
     const gfx::Point& point,
     cc::SurfaceId original_surface,
@@ -2293,7 +2317,12 @@
   // Set unchanged touch point to StateStationary for touchmove and
   // touchcancel to make sure only send one ack per WebTouchEvent.
   MarkUnchangedTouchPointsAsStationary(&touch_event, event->touch_id());
-  host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency());
+  if (ShouldRouteEvent(event)) {
+    host_->delegate()->GetInputEventRouter()->RouteTouchEvent(
+        this, &touch_event, *event->latency());
+  } else {
+    ProcessTouchEvent(touch_event, *event->latency());
+  }
 }
 
 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 476b4bb..6617b4b 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -192,6 +192,8 @@
                                      gfx::Point* transformed_point) override;
   void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
   void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
+  void ProcessTouchEvent(const blink::WebTouchEvent& event,
+                         const ui::LatencyInfo& latency) override;
   void TransformPointToLocalCoordSpace(const gfx::Point& point,
                                        cc::SurfaceId original_surface,
                                        gfx::Point* transformed_point) override;
@@ -485,6 +487,9 @@
                               bool mouse_locked,
                               bool selection_popup);
 
+  // Returns true when we can do SurfaceHitTesting for the event type.
+  bool ShouldRouteEvent(const ui::Event* event) const;
+
   // Called when the parent window bounds change.
   void HandleParentBoundsChanged();
 
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 1f1e43c0..3200d12 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -46,6 +46,10 @@
 class WebMouseWheelEvent;
 }
 
+namespace ui {
+class LatencyInfo;
+}
+
 namespace content {
 class BrowserAccessibilityDelegate;
 class BrowserAccessibilityManager;
@@ -192,6 +196,8 @@
   virtual void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) {}
   virtual void ProcessMouseEvent(const blink::WebMouseEvent& event) {}
   virtual void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) {}
+  virtual void ProcessTouchEvent(const blink::WebTouchEvent& event,
+                         const ui::LatencyInfo& latency) {}
 
   // If a RenderWidgetHost is dealing with points that are transformed from the
   // root frame for a page (i.e. because its content is contained within
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index ad80a2a..3eb4f69 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -349,6 +349,8 @@
   uint32_t GetSurfaceIdNamespace() override;
   uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
                                      gfx::Point* transformed_point) override;
+  // Returns true when we can do SurfaceHitTesting for the event type.
+  bool ShouldRouteEvent(const blink::WebInputEvent& event) const;
   void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
   void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
   void TransformPointToLocalCoordSpace(const gfx::Point& point,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 6fda5e1..29fd891 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -54,6 +54,7 @@
 #include "content/common/edit_command.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "content/common/input_messages.h"
+#include "content/common/site_isolation_policy.h"
 #include "content/common/view_messages.h"
 #include "content/common/webplugin_geometry.h"
 #include "content/public/browser/browser_context.h"
@@ -1610,6 +1611,18 @@
   return cc::SurfaceIdAllocator::NamespaceForId(id);
 }
 
+bool RenderWidgetHostViewMac::ShouldRouteEvent(
+    const WebInputEvent& event) const {
+  // See also RenderWidgetHostViewAura::ShouldRouteEvent.
+  // TODO(wjmaclean): Update this function if RenderWidgetHostViewMac implements
+  // OnTouchEvent(), to match what we are doing in RenderWidgetHostViewAura.
+  DCHECK(WebInputEvent::isMouseEventType(event.type) ||
+         event.type == WebInputEvent::MouseWheel);
+  return render_widget_host_->delegate() &&
+         render_widget_host_->delegate()->GetInputEventRouter() &&
+         SiteIsolationPolicy::AreCrossProcessFramesPossible();
+}
+
 void RenderWidgetHostViewMac::ProcessMouseEvent(
     const blink::WebMouseEvent& event) {
   render_widget_host_->ForwardMouseEvent(event);
@@ -1956,14 +1969,12 @@
       WebMouseEvent enterEvent = WebMouseEventBuilder::Build(theEvent, self);
       enterEvent.type = WebInputEvent::MouseMove;
       enterEvent.button = WebMouseEvent::ButtonNone;
-      if (renderWidgetHostView_->render_widget_host_->delegate() &&
-          renderWidgetHostView_->render_widget_host_->delegate()
-              ->GetInputEventRouter()) {
+      if (renderWidgetHostView_->ShouldRouteEvent(enterEvent)) {
         renderWidgetHostView_->render_widget_host_->delegate()
             ->GetInputEventRouter()
             ->RouteMouseEvent(renderWidgetHostView_.get(), &enterEvent);
       } else {
-        renderWidgetHostView_->ForwardMouseEvent(enterEvent);
+        renderWidgetHostView_->ProcessMouseEvent(enterEvent);
       }
     }
   }
@@ -1993,14 +2004,12 @@
   }
 
   WebMouseEvent event = WebMouseEventBuilder::Build(theEvent, self);
-  if (renderWidgetHostView_->render_widget_host_->delegate() &&
-      renderWidgetHostView_->render_widget_host_->delegate()
-          ->GetInputEventRouter()) {
+  if (renderWidgetHostView_->ShouldRouteEvent(event)) {
     renderWidgetHostView_->render_widget_host_->delegate()
         ->GetInputEventRouter()
         ->RouteMouseEvent(renderWidgetHostView_.get(), &event);
   } else {
-    renderWidgetHostView_->ForwardMouseEvent(event);
+    renderWidgetHostView_->ProcessMouseEvent(event);
   }
 }
 
@@ -2504,14 +2513,12 @@
     WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(
         event, self, canRubberbandLeft, canRubberbandRight);
     webEvent.railsMode = mouseWheelFilter_.UpdateRailsMode(webEvent);
-    if (renderWidgetHostView_->render_widget_host_->delegate() &&
-        renderWidgetHostView_->render_widget_host_->delegate()
-            ->GetInputEventRouter()) {
+    if (renderWidgetHostView_->ShouldRouteEvent(webEvent)) {
       renderWidgetHostView_->render_widget_host_->delegate()
           ->GetInputEventRouter()
           ->RouteMouseWheelEvent(renderWidgetHostView_.get(), &webEvent);
     } else {
-      renderWidgetHostView_->render_widget_host_->ForwardWheelEvent(webEvent);
+      renderWidgetHostView_->ProcessMouseWheelEvent(webEvent);
     }
   }
 }
diff --git a/content/browser/speech/speech_recognizer_impl_android.cc b/content/browser/speech/speech_recognizer_impl_android.cc
index 8b170176..52b5087 100644
--- a/content/browser/speech/speech_recognizer_impl_android.cc
+++ b/content/browser/speech/speech_recognizer_impl_android.cc
@@ -99,11 +99,14 @@
   return state_ == STATE_CAPTURING_AUDIO;
 }
 
-void SpeechRecognizerImplAndroid::OnAudioStart(JNIEnv* env, jobject obj) {
+void SpeechRecognizerImplAndroid::OnAudioStart(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
-        &SpeechRecognizerImplAndroid::OnAudioStart, this,
-        static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&SpeechRecognizerImplAndroid::OnAudioStart, this, nullptr,
+                   nullptr));
     return;
   }
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -111,33 +114,38 @@
   listener()->OnAudioStart(session_id());
 }
 
-void SpeechRecognizerImplAndroid::OnSoundStart(JNIEnv* env, jobject obj) {
+void SpeechRecognizerImplAndroid::OnSoundStart(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
-        &SpeechRecognizerImplAndroid::OnSoundStart, this,
-        static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&SpeechRecognizerImplAndroid::OnSoundStart, this, nullptr,
+                   nullptr));
     return;
   }
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   listener()->OnSoundStart(session_id());
 }
 
-void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env, jobject obj) {
+void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
-        &SpeechRecognizerImplAndroid::OnSoundEnd, this,
-        static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
+    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                            base::Bind(&SpeechRecognizerImplAndroid::OnSoundEnd,
+                                       this, nullptr, nullptr));
     return;
   }
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   listener()->OnSoundEnd(session_id());
 }
 
-void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env, jobject obj) {
+void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
-        &SpeechRecognizerImplAndroid::OnAudioEnd, this,
-        static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
+    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                            base::Bind(&SpeechRecognizerImplAndroid::OnAudioEnd,
+                                       this, nullptr, nullptr));
     return;
   }
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -146,8 +154,12 @@
   listener()->OnAudioEnd(session_id());
 }
 
-void SpeechRecognizerImplAndroid::OnRecognitionResults(JNIEnv* env, jobject obj,
-    jobjectArray strings, jfloatArray floats, jboolean provisional) {
+void SpeechRecognizerImplAndroid::OnRecognitionResults(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobjectArray>& strings,
+    const JavaParamRef<jfloatArray>& floats,
+    jboolean provisional) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::vector<base::string16> options;
   AppendJavaStringArrayToStringVector(env, strings, &options);
@@ -174,12 +186,15 @@
   listener()->OnRecognitionResults(session_id(), results);
 }
 
-void SpeechRecognizerImplAndroid::OnRecognitionError(JNIEnv* env,
-    jobject obj, jint error) {
+void SpeechRecognizerImplAndroid::OnRecognitionError(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint error) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
-        &SpeechRecognizerImplAndroid::OnRecognitionError, this,
-        static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL), error));
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionError, this,
+                   nullptr, nullptr, error));
     return;
   }
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -188,12 +203,14 @@
   listener()->OnRecognitionError(session_id(), SpeechRecognitionError(code));
 }
 
-void SpeechRecognizerImplAndroid::OnRecognitionEnd(JNIEnv* env,
-    jobject obj) {
+void SpeechRecognizerImplAndroid::OnRecognitionEnd(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
-        &SpeechRecognizerImplAndroid::OnRecognitionEnd, this,
-        static_cast<JNIEnv*>(NULL), static_cast<jobject>(NULL)));
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionEnd, this,
+                   nullptr, nullptr));
     return;
   }
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/content/browser/speech/speech_recognizer_impl_android.h b/content/browser/speech/speech_recognizer_impl_android.h
index 9472ca6..878e7ae1 100644
--- a/content/browser/speech/speech_recognizer_impl_android.h
+++ b/content/browser/speech/speech_recognizer_impl_android.h
@@ -31,14 +31,23 @@
   bool IsCapturingAudio() const override;
 
   // Called from Java methods via JNI.
-  void OnAudioStart(JNIEnv* env, jobject obj);
-  void OnSoundStart(JNIEnv* env, jobject obj);
-  void OnSoundEnd(JNIEnv* env, jobject obj);
-  void OnAudioEnd(JNIEnv* env, jobject obj);
-  void OnRecognitionResults(JNIEnv* env, jobject obj, jobjectArray strings,
-                            jfloatArray floats, jboolean interim);
-  void OnRecognitionError(JNIEnv* env, jobject obj, jint error);
-  void OnRecognitionEnd(JNIEnv* env, jobject obj);
+  void OnAudioStart(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj);
+  void OnSoundStart(JNIEnv* env,
+                    const base::android::JavaParamRef<jobject>& obj);
+  void OnSoundEnd(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void OnAudioEnd(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+  void OnRecognitionResults(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jobjectArray>& strings,
+      const base::android::JavaParamRef<jfloatArray>& floats,
+      jboolean interim);
+  void OnRecognitionError(JNIEnv* env,
+                          const base::android::JavaParamRef<jobject>& obj,
+                          jint error);
+  void OnRecognitionEnd(JNIEnv* env,
+                        const base::android::JavaParamRef<jobject>& obj);
 
   static bool RegisterSpeechRecognizer(JNIEnv* env);
 
diff --git a/content/browser/theme_helper_mac.mm b/content/browser/theme_helper_mac.mm
index 9b2656b7..aa5ebd05 100644
--- a/content/browser/theme_helper_mac.mm
+++ b/content/browser/theme_helper_mac.mm
@@ -37,17 +37,17 @@
   return enabled;
 }
 
-blink::ScrollbarButtonsPlacement GetButtonPlacement() {
+blink::WebScrollbarButtonsPlacement GetButtonPlacement() {
   NSString* scrollbar_variant = [[NSUserDefaults standardUserDefaults]
       objectForKey:@"AppleScrollBarVariant"];
   if ([scrollbar_variant isEqualToString:@"Single"])
-    return blink::ScrollbarButtonsPlacementSingle;
+    return blink::WebScrollbarButtonsPlacementSingle;
   else if ([scrollbar_variant isEqualToString:@"DoubleMin"])
-    return blink::ScrollbarButtonsPlacementDoubleStart;
+    return blink::WebScrollbarButtonsPlacementDoubleStart;
   else if ([scrollbar_variant isEqualToString:@"DoubleBoth"])
-    return blink::ScrollbarButtonsPlacementDoubleBoth;
+    return blink::WebScrollbarButtonsPlacementDoubleBoth;
   else
-    return blink::ScrollbarButtonsPlacementDoubleEnd;
+    return blink::WebScrollbarButtonsPlacementDoubleEnd;
 }
 
 void FillScrollbarThemeParams(ViewMsg_UpdateScrollbarTheme_Params* params) {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 3ff2c4d3..4755716e 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1595,9 +1595,10 @@
 }
 
 RenderWidgetHostInputEventRouter* WebContentsImpl::GetInputEventRouter() {
-  // Currently only supported in site per process mode (--site-per-process).
-  if (!rwh_input_event_router_.get() && !is_being_destroyed_ &&
-      SiteIsolationPolicy::AreCrossProcessFramesPossible())
+  if (!is_being_destroyed_ && GetOuterWebContents())
+    return GetOuterWebContents()->GetInputEventRouter();
+
+  if (!rwh_input_event_router_.get() && !is_being_destroyed_)
     rwh_input_event_router_.reset(new RenderWidgetHostInputEventRouter);
   return rwh_input_event_router_.get();
 }
diff --git a/content/child/dwrite_font_proxy/OWNERS b/content/child/dwrite_font_proxy/OWNERS
new file mode 100644
index 0000000..54db994a2
--- /dev/null
+++ b/content/child/dwrite_font_proxy/OWNERS
@@ -0,0 +1,3 @@
+kulshin@chromium.org
+jschuh@chromium.org
+scottmg@chromium.org
\ No newline at end of file
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
new file mode 100644
index 0000000..7ec2a42
--- /dev/null
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
@@ -0,0 +1,118 @@
+// Copyright 2015 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/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h"
+
+#include <dwrite.h>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/debug/alias.h"
+#include "base/win/iat_patch_function.h"
+#include "base/win/windows_version.h"
+#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
+#include "content/common/font_warmup_win.h"
+#include "skia/ext/fontmgr_default_win.h"
+#include "third_party/WebKit/public/web/win/WebFontRendering.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
+
+namespace mswr = Microsoft::WRL;
+
+namespace content {
+
+namespace {
+
+mswr::ComPtr<DWriteFontCollectionProxy> g_font_collection;
+IPC::Sender* g_sender_override = nullptr;
+
+// Windows-only DirectWrite support. These warm up the DirectWrite paths
+// before sandbox lock down to allow Skia access to the Font Manager service.
+void CreateDirectWriteFactory(IDWriteFactory** factory) {
+  typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
+  HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
+  // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
+  if (!dwrite_dll) {
+    DWORD load_library_get_last_error = GetLastError();
+    base::debug::Alias(&dwrite_dll);
+    base::debug::Alias(&load_library_get_last_error);
+    CHECK(false);
+  }
+
+  // This shouldn't be necessary, but not having this causes breakage in
+  // content_browsertests, and possibly other high-stress cases.
+  PatchServiceManagerCalls();
+
+  DWriteCreateFactoryProc dwrite_create_factory_proc =
+      reinterpret_cast<DWriteCreateFactoryProc>(
+          GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
+  // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
+  if (!dwrite_create_factory_proc) {
+    DWORD get_proc_address_get_last_error = GetLastError();
+    base::debug::Alias(&dwrite_create_factory_proc);
+    base::debug::Alias(&get_proc_address_get_last_error);
+    CHECK(false);
+  }
+  CHECK(SUCCEEDED(dwrite_create_factory_proc(
+      DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory),
+      reinterpret_cast<IUnknown**>(factory))));
+}
+
+HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory,
+                                             IDWriteFontCollection** col,
+                                             BOOL checkUpdates) {
+  DCHECK(g_font_collection);
+  g_font_collection.CopyTo(col);
+  return S_OK;
+}
+
+// Copied from content/common/font_warmup_win.cc
+void PatchDWriteFactory(IDWriteFactory* factory) {
+  const unsigned int kGetSystemFontCollectionVTableIndex = 3;
+
+  PROC* vtable = *reinterpret_cast<PROC**>(factory);
+  PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex];
+  void* stub_function = &StubFontCollection;
+  base::win::ModifyCode(function_ptr, &stub_function, sizeof(PROC));
+}
+
+// Needed as a function for Bind()
+IPC::Sender* GetSenderOverride() {
+  return g_sender_override;
+}
+
+}  // namespace
+
+void InitializeDWriteFontProxy(
+    const base::Callback<IPC::Sender*(void)>& sender) {
+  mswr::ComPtr<IDWriteFactory> factory;
+
+  CreateDirectWriteFactory(&factory);
+
+  if (!g_font_collection) {
+    if (g_sender_override) {
+      mswr::MakeAndInitialize<DWriteFontCollectionProxy>(
+          &g_font_collection, factory.Get(), base::Bind(&GetSenderOverride));
+    } else {
+      mswr::MakeAndInitialize<DWriteFontCollectionProxy>(&g_font_collection,
+                                                         factory.Get(), sender);
+    }
+  }
+
+  PatchDWriteFactory(factory.Get());
+
+  blink::WebFontRendering::setDirectWriteFactory(factory.Get());
+  SkFontMgr* skia_font_manager = SkFontMgr_New_DirectWrite(factory.Get());
+  SetDefaultSkiaFactory(skia_font_manager);
+}
+
+void UninitializeDWriteFontProxy() {
+  if (g_font_collection)
+    g_font_collection->Unregister();
+}
+
+void SetDWriteFontProxySenderForTesting(IPC::Sender* sender) {
+  g_sender_override = sender;
+}
+
+}  // namespace content
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h
new file mode 100644
index 0000000..e346cb0
--- /dev/null
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h
@@ -0,0 +1,30 @@
+// Copyright 2015 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_CHILD_DWRITE_FONT_PROXY_DWRITE_FONT_PROXY_INIT_WIN_H_
+#define CONTENT_CHILD_DWRITE_FONT_PROXY_DWRITE_FONT_PROXY_INIT_WIN_H_
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_sender.h"
+
+namespace content {
+
+// Initializes the dwrite font proxy, using the specified callback to obtain
+// the sender to be used for sending IPC messages to the browser process.
+CONTENT_EXPORT void InitializeDWriteFontProxy(
+    const base::Callback<IPC::Sender*(void)>& sender);
+
+// Uninitialize the dwrite font proxy. This is safe to call even if the proxy
+// has not been initialized. After this, calls to load fonts may fail.
+CONTENT_EXPORT void UninitializeDWriteFontProxy();
+
+// Configures the dwrite font proxy to use the specified sender. This can be
+// useful in tests which use a fake render thread which is unable to process
+// font IPC messages. This should only be called when running as a test.
+CONTENT_EXPORT void SetDWriteFontProxySenderForTesting(IPC::Sender* sender);
+
+}  // namespace content
+
+#endif  // CONTENT_CHILD_DWRITE_FONT_PROXY_DWRITE_FONT_PROXY_INIT_WIN_H_
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
new file mode 100644
index 0000000..0462d711
--- /dev/null
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -0,0 +1,514 @@
+// Copyright 2015 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/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
+
+#include <utility>
+
+#include "base/debug/crash_logging.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/scoped_handle.h"
+#include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h"
+#include "content/common/dwrite_font_proxy_messages.h"
+#include "ipc/ipc_sender.h"
+
+namespace mswr = Microsoft::WRL;
+
+namespace content {
+
+namespace {
+
+// This enum is used to define the buckets for an enumerated UMA histogram.
+// Hence,
+//   (a) existing enumerated constants should never be deleted or reordered, and
+//   (b) new constants should only be appended at the end of the enumeration.
+enum DirectWriteLoadFamilyResult {
+  LOAD_FAMILY_SUCCESS_SINGLE_FAMILY = 0,
+  LOAD_FAMILY_SUCCESS_MATCHED_FAMILY = 1,
+  LOAD_FAMILY_ERROR_MULTIPLE_FAMILIES = 2,
+  LOAD_FAMILY_ERROR_NO_FAMILIES = 3,
+  LOAD_FAMILY_ERROR_NO_COLLECTION = 4,
+
+  LOAD_FAMILY_MAX_VALUE
+};
+
+const char kFontKeyName[] = "font_key_name";
+
+void LogLoadFamilyResult(DirectWriteLoadFamilyResult result) {
+  UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.LoadFamily", result,
+                            LOAD_FAMILY_MAX_VALUE);
+}
+
+}  // namespace
+
+DWriteFontCollectionProxy::DWriteFontCollectionProxy() = default;
+
+DWriteFontCollectionProxy::~DWriteFontCollectionProxy() = default;
+
+HRESULT DWriteFontCollectionProxy::FindFamilyName(const WCHAR* family_name,
+                                                  UINT32* index,
+                                                  BOOL* exists) {
+  DCHECK(family_name);
+  DCHECK(index);
+  DCHECK(exists);
+  TRACE_EVENT0("dwrite", "FontProxy::FindFamilyName");
+
+  uint32_t family_index = 0;
+  base::string16 name(family_name);
+
+  auto iter = family_names_.find(name);
+  if (iter != family_names_.end()) {
+    *index = iter->second;
+    *exists = iter->second != UINT_MAX;
+    return S_OK;
+  }
+
+  if (!sender_.Run()->Send(
+          new DWriteFontProxyMsg_FindFamily(name, &family_index))) {
+    return E_FAIL;
+  }
+
+  if (family_index != UINT32_MAX) {
+    if (!CreateFamily(family_index))
+      return E_FAIL;
+    *exists = TRUE;
+    *index = family_index;
+    families_[family_index]->SetName(name);
+  } else {
+    *exists = FALSE;
+    *index = UINT32_MAX;
+  }
+
+  family_names_[name] = *index;
+  return S_OK;
+}
+
+HRESULT DWriteFontCollectionProxy::GetFontFamily(
+    UINT32 index,
+    IDWriteFontFamily** font_family) {
+  DCHECK(font_family);
+
+  if (index < families_.size() && families_[index]) {
+    families_[index].CopyTo(font_family);
+    return S_OK;
+  }
+
+  if (!CreateFamily(index))
+    return E_FAIL;
+
+  families_[index].CopyTo(font_family);
+  return S_OK;
+}
+
+UINT32 DWriteFontCollectionProxy::GetFontFamilyCount() {
+  if (family_count_ != UINT_MAX)
+    return family_count_;
+
+  TRACE_EVENT0("dwrite", "FontProxy::GetFontFamilyCount");
+
+  uint32_t family_count = 0;
+  if (!sender_.Run()->Send(
+          new DWriteFontProxyMsg_GetFamilyCount(&family_count))) {
+    return 0;
+  }
+  family_count_ = family_count;
+  return family_count;
+}
+
+HRESULT DWriteFontCollectionProxy::GetFontFromFontFace(
+    IDWriteFontFace* font_face,
+    IDWriteFont** font) {
+  DCHECK(font_face);
+  DCHECK(font);
+
+  for (const auto& family : families_) {
+    if (family && family->GetFontFromFontFace(font_face, font))
+      return S_OK;
+  }
+  return E_FAIL;
+}
+
+HRESULT DWriteFontCollectionProxy::CreateEnumeratorFromKey(
+    IDWriteFactory* factory,
+    const void* collection_key,
+    UINT32 collection_key_size,
+    IDWriteFontFileEnumerator** font_file_enumerator) {
+  if (!collection_key || collection_key_size != sizeof(uint32_t))
+    return E_INVALIDARG;
+
+  TRACE_EVENT0("dwrite", "FontProxy::LoadingFontFiles");
+
+  const uint32_t* family_index =
+      reinterpret_cast<const uint32_t*>(collection_key);
+
+  if (*family_index >= GetFontFamilyCount())
+    return E_INVALIDARG;
+
+  // If we already loaded the family we should reuse the existing collection.
+  DCHECK(!families_[*family_index]->IsLoaded());
+
+  std::vector<base::string16> file_names;
+  if (!sender_.Run()->Send(
+          new DWriteFontProxyMsg_GetFontFiles(*family_index, &file_names))) {
+    return E_FAIL;
+  }
+
+  HRESULT hr = mswr::MakeAndInitialize<FontFileEnumerator>(
+      font_file_enumerator, factory, this, &file_names);
+
+  if (!SUCCEEDED(hr))
+    return E_FAIL;
+
+  return S_OK;
+}
+
+HRESULT DWriteFontCollectionProxy::CreateStreamFromKey(
+    const void* font_file_reference_key,
+    UINT32 font_file_reference_key_size,
+    IDWriteFontFileStream** font_file_stream) {
+  if (!font_file_reference_key)
+    return E_FAIL;
+
+  const base::char16* file_name =
+      reinterpret_cast<const base::char16*>(font_file_reference_key);
+  DCHECK_EQ(font_file_reference_key_size % sizeof(base::char16), 0u);
+  size_t file_name_size =
+      static_cast<size_t>(font_file_reference_key_size) / sizeof(base::char16);
+
+  if (file_name_size == 0 || file_name[file_name_size - 1] != L'\0')
+    return E_FAIL;
+
+  TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey");
+
+  mswr::ComPtr<IDWriteFontFileStream> stream;
+  if (!SUCCEEDED(mswr::MakeAndInitialize<FontFileStream>(&stream, file_name)))
+    return E_FAIL;
+  *font_file_stream = stream.Detach();
+  return S_OK;
+}
+
+HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize(
+    IDWriteFactory* factory,
+    const base::Callback<IPC::Sender*(void)>& sender) {
+  DCHECK(factory);
+
+  factory_ = factory;
+  sender_ = sender;
+
+  HRESULT hr = factory->RegisterFontCollectionLoader(this);
+  DCHECK(SUCCEEDED(hr));
+  hr = factory_->RegisterFontFileLoader(this);
+  DCHECK(SUCCEEDED(hr));
+  return S_OK;
+}
+
+void DWriteFontCollectionProxy::Unregister() {
+  factory_->UnregisterFontCollectionLoader(this);
+  factory_->UnregisterFontFileLoader(this);
+}
+
+bool DWriteFontCollectionProxy::LoadFamily(
+    UINT32 family_index,
+    IDWriteFontCollection** containing_collection) {
+  TRACE_EVENT0("dwrite", "FontProxy::LoadFamily");
+
+  uint32_t index = family_index;
+  // CreateCustomFontCollection ends up calling
+  // DWriteFontCollectionProxy::CreateEnumeratorFromKey.
+  HRESULT hr = factory_->CreateCustomFontCollection(
+      this /*collectionLoader*/, reinterpret_cast<const void*>(&index),
+      sizeof(index), containing_collection);
+
+  return SUCCEEDED(hr);
+}
+
+bool DWriteFontCollectionProxy::LoadFamilyNames(
+    UINT32 family_index,
+    IDWriteLocalizedStrings** localized_strings) {
+  TRACE_EVENT0("dwrite", "FontProxy::LoadFamilyNames");
+
+  std::vector<std::pair<base::string16, base::string16>> strings;
+  if (!sender_.Run()->Send(
+          new DWriteFontProxyMsg_GetFamilyNames(family_index, &strings))) {
+    return false;
+  }
+
+  HRESULT hr = mswr::MakeAndInitialize<DWriteLocalizedStrings>(
+      localized_strings, &strings);
+
+  return SUCCEEDED(hr);
+}
+
+bool DWriteFontCollectionProxy::CreateFamily(UINT32 family_index) {
+  if (family_index < families_.size() && families_[family_index])
+    return true;
+
+  UINT32 family_count = GetFontFamilyCount();
+  if (family_index >= family_count)
+    return false;
+
+  if (families_.size() < family_count)
+    families_.resize(family_count);
+
+  mswr::ComPtr<DWriteFontFamilyProxy> family;
+  HRESULT hr = mswr::MakeAndInitialize<DWriteFontFamilyProxy>(&family, this,
+                                                              family_index);
+  DCHECK(SUCCEEDED(hr));
+  DCHECK_LT(family_index, families_.size());
+
+  families_[family_index] = family;
+  return true;
+}
+
+DWriteFontFamilyProxy::DWriteFontFamilyProxy() = default;
+
+DWriteFontFamilyProxy::~DWriteFontFamilyProxy() = default;
+
+HRESULT DWriteFontFamilyProxy::GetFontCollection(
+    IDWriteFontCollection** font_collection) {
+  DCHECK(font_collection);
+
+  proxy_collection_.CopyTo(font_collection);
+  return S_OK;
+}
+
+UINT32 DWriteFontFamilyProxy::GetFontCount() {
+  // We could conceivably proxy just the font count. However, calling
+  // GetFontCount is almost certain to be followed by a series of GetFont
+  // calls which will need to load all the fonts anyway, so we might as
+  // well save an IPC here.
+  if (!LoadFamily())
+    return 0;
+
+  return family_->GetFontCount();
+}
+
+HRESULT DWriteFontFamilyProxy::GetFont(UINT32 index, IDWriteFont** font) {
+  DCHECK(font);
+
+  if (index >= GetFontCount())
+    return E_INVALIDARG;
+  if (!LoadFamily())
+    return E_FAIL;
+
+  return family_->GetFont(index, font);
+}
+
+HRESULT DWriteFontFamilyProxy::GetFamilyNames(IDWriteLocalizedStrings** names) {
+  DCHECK(names);
+
+  // Prefer the real thing, if available.
+  if (family_) {
+    family_names_.Reset();  // Release cached data.
+    return family_->GetFamilyNames(names);
+  }
+
+  // If already cached, use the cache.
+  if (family_names_) {
+    family_names_.CopyTo(names);
+    return S_OK;
+  }
+
+  TRACE_EVENT0("dwrite", "FontProxy::GetFamilyNames");
+
+  // Otherwise, do the IPC.
+  if (!proxy_collection_->LoadFamilyNames(family_index_, &family_names_))
+    return E_FAIL;
+
+  family_names_.CopyTo(names);
+  return S_OK;
+}
+
+HRESULT DWriteFontFamilyProxy::GetFirstMatchingFont(
+    DWRITE_FONT_WEIGHT weight,
+    DWRITE_FONT_STRETCH stretch,
+    DWRITE_FONT_STYLE style,
+    IDWriteFont** matching_font) {
+  DCHECK(matching_font);
+
+  if (!LoadFamily())
+    return E_FAIL;
+
+  return family_->GetFirstMatchingFont(weight, stretch, style, matching_font);
+}
+
+HRESULT DWriteFontFamilyProxy::GetMatchingFonts(
+    DWRITE_FONT_WEIGHT weight,
+    DWRITE_FONT_STRETCH stretch,
+    DWRITE_FONT_STYLE style,
+    IDWriteFontList** matching_fonts) {
+  DCHECK(matching_fonts);
+
+  if (!LoadFamily())
+    return E_FAIL;
+
+  return family_->GetMatchingFonts(weight, stretch, style, matching_fonts);
+}
+
+HRESULT DWriteFontFamilyProxy::RuntimeClassInitialize(
+    DWriteFontCollectionProxy* collection,
+    UINT32 index) {
+  DCHECK(collection);
+
+  proxy_collection_ = collection;
+  family_index_ = index;
+  return S_OK;
+}
+
+bool DWriteFontFamilyProxy::GetFontFromFontFace(IDWriteFontFace* font_face,
+                                                IDWriteFont** font) {
+  DCHECK(font_face);
+  DCHECK(font);
+
+  if (!family_)
+    return false;
+
+  mswr::ComPtr<IDWriteFontCollection> collection;
+  HRESULT hr = family_->GetFontCollection(&collection);
+  DCHECK(SUCCEEDED(hr));
+  hr = collection->GetFontFromFontFace(font_face, font);
+
+  return SUCCEEDED(hr);
+}
+
+void DWriteFontFamilyProxy::SetName(const base::string16& family_name) {
+  family_name_.assign(family_name);
+}
+
+bool DWriteFontFamilyProxy::IsLoaded() {
+  return family_ != nullptr;
+}
+
+bool DWriteFontFamilyProxy::LoadFamily() {
+  if (family_)
+    return true;
+
+  SCOPED_UMA_HISTOGRAM_TIMER("DirectWrite.Fonts.Proxy.LoadFamilyTime");
+
+  base::debug::ScopedCrashKey crash_key(kFontKeyName,
+                                        base::WideToUTF8(family_name_));
+
+  mswr::ComPtr<IDWriteFontCollection> collection;
+  if (!proxy_collection_->LoadFamily(family_index_, &collection)) {
+    LogLoadFamilyResult(LOAD_FAMILY_ERROR_NO_COLLECTION);
+    return false;
+  }
+
+  UINT32 family_count = collection->GetFontFamilyCount();
+
+  HRESULT hr;
+  if (family_count > 1) {
+    // Some fonts are packaged in a single file containing multiple families. In
+    // such a case we can find the right family by family name.
+    DCHECK(!family_name_.empty());
+    UINT32 family_index = 0;
+    BOOL found = FALSE;
+    hr =
+        collection->FindFamilyName(family_name_.c_str(), &family_index, &found);
+    if (SUCCEEDED(hr) && found) {
+      hr = collection->GetFontFamily(family_index, &family_);
+      LogLoadFamilyResult(LOAD_FAMILY_SUCCESS_MATCHED_FAMILY);
+      return SUCCEEDED(hr);
+    }
+  }
+
+  DCHECK_LE(family_count, 1u);
+
+  if (family_count == 0) {
+    // This is really strange, we successfully loaded no fonts?!
+    LogLoadFamilyResult(LOAD_FAMILY_ERROR_NO_FAMILIES);
+    return false;
+  }
+
+  LogLoadFamilyResult(family_count == 1 ? LOAD_FAMILY_SUCCESS_SINGLE_FAMILY
+                                        : LOAD_FAMILY_ERROR_MULTIPLE_FAMILIES);
+
+  hr = collection->GetFontFamily(0, &family_);
+
+  return SUCCEEDED(hr);
+}
+
+FontFileEnumerator::FontFileEnumerator() = default;
+
+FontFileEnumerator::~FontFileEnumerator() = default;
+
+HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) {
+  DCHECK(file);
+  if (current_file_ >= file_names_.size())
+    return E_FAIL;
+
+  TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile (memmap)");
+  // CreateCustomFontFileReference ends up calling
+  // DWriteFontCollectionProxy::CreateStreamFromKey.
+  return factory_->CreateCustomFontFileReference(
+      reinterpret_cast<const void*>(file_names_[current_file_].c_str()),
+      (file_names_[current_file_].length() + 1) * sizeof(base::char16),
+      loader_.Get() /*IDWriteFontFileLoader*/, file);
+}
+
+HRESULT FontFileEnumerator::MoveNext(BOOL* has_current_file) {
+  DCHECK(has_current_file);
+
+  TRACE_EVENT0("dwrite", "FontFileEnumerator::MoveNext");
+  if (next_file_ >= file_names_.size()) {
+    *has_current_file = FALSE;
+    current_file_ = UINT_MAX;
+    return S_OK;
+  }
+
+  current_file_ = next_file_;
+  ++next_file_;
+  *has_current_file = TRUE;
+  return S_OK;
+}
+
+HRESULT FontFileEnumerator::RuntimeClassInitialize(
+    IDWriteFactory* factory,
+    IDWriteFontFileLoader* loader,
+    std::vector<base::string16>* file_names) {
+  factory_ = factory;
+  loader_ = loader;
+  file_names_.swap(*file_names);
+  file_streams_.resize(file_names_.size());
+  return S_OK;
+}
+
+FontFileStream::FontFileStream() = default;
+
+FontFileStream::~FontFileStream() = default;
+
+HRESULT FontFileStream::GetFileSize(UINT64* file_size) {
+  *file_size = data_.length();
+  return S_OK;
+}
+
+HRESULT FontFileStream::GetLastWriteTime(UINT64* last_write_time) {
+  *last_write_time = 0;
+  return S_OK;
+}
+
+HRESULT FontFileStream::ReadFileFragment(const void** fragment_start,
+                                         UINT64 fragment_offset,
+                                         UINT64 fragment_size,
+                                         void** fragment_context) {
+  if (fragment_offset + fragment_size < fragment_offset)
+    return E_FAIL;
+  if (fragment_offset + fragment_size > data_.length())
+    return E_FAIL;
+  *fragment_start = data_.data() + fragment_offset;
+  *fragment_context = nullptr;
+  return S_OK;
+}
+
+HRESULT FontFileStream::RuntimeClassInitialize(
+    const base::string16& file_name) {
+  data_.Initialize(base::FilePath(file_name));
+  if (!data_.IsValid())
+    return E_FAIL;
+  return S_OK;
+}
+
+}  // namespace content
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h
new file mode 100644
index 0000000..bdee58f
--- /dev/null
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h
@@ -0,0 +1,202 @@
+// Copyright 2015 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_CHILD_DWRITE_FONT_PROXY_DWRITE_FONT_PROXY_WIN_H_
+#define CONTENT_CHILD_DWRITE_FONT_PROXY_DWRITE_FONT_PROXY_WIN_H_
+
+#include <dwrite.h>
+#include <wrl.h>
+
+#include <map>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+
+namespace IPC {
+class Sender;
+}
+
+namespace content {
+
+class DWriteFontFamilyProxy;
+
+// Implements a DirectWrite font collection that uses IPC to the browser to do
+// font enumeration. If a matching family is found, it will be loaded locally
+// into a custom font collection.
+// This is needed because the sandbox interferes with DirectWrite's
+// communication with the system font service.
+class CONTENT_EXPORT DWriteFontCollectionProxy
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
+          IDWriteFontCollection,
+          IDWriteFontCollectionLoader,
+          IDWriteFontFileLoader> {
+ public:
+  DWriteFontCollectionProxy();
+  ~DWriteFontCollectionProxy() override;
+
+  // IDWriteFontCollection:
+  HRESULT STDMETHODCALLTYPE FindFamilyName(const WCHAR* family_name,
+                                           UINT32* index,
+                                           BOOL* exists) override;
+  HRESULT STDMETHODCALLTYPE
+  GetFontFamily(UINT32 index, IDWriteFontFamily** font_family) override;
+  UINT32 STDMETHODCALLTYPE GetFontFamilyCount() override;
+  HRESULT STDMETHODCALLTYPE GetFontFromFontFace(IDWriteFontFace* font_face,
+                                                IDWriteFont** font) override;
+
+  // IDWriteFontCollectionLoader:
+  HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
+      IDWriteFactory* factory,
+      const void* collection_key,
+      UINT32 collection_key_size,
+      IDWriteFontFileEnumerator** font_file_enumerator) override;
+
+  // IDWriteFontFileLoader:
+  HRESULT STDMETHODCALLTYPE
+  CreateStreamFromKey(const void* font_file_reference_key,
+                      UINT32 font_file_reference_key_size,
+                      IDWriteFontFileStream** font_file_stream) override;
+
+  HRESULT STDMETHODCALLTYPE
+  RuntimeClassInitialize(IDWriteFactory* factory,
+                         const base::Callback<IPC::Sender*(void)>& sender);
+
+  void Unregister();
+
+  bool LoadFamily(UINT32 family_index,
+                  IDWriteFontCollection** containing_collection);
+
+  bool LoadFamilyNames(UINT32 family_index, IDWriteLocalizedStrings** strings);
+
+  bool CreateFamily(UINT32 family_index);
+
+ private:
+  Microsoft::WRL::ComPtr<IDWriteFactory> factory_;
+  std::vector<Microsoft::WRL::ComPtr<DWriteFontFamilyProxy>> families_;
+  std::map<base::string16, UINT32> family_names_;
+  UINT32 family_count_ = UINT_MAX;
+  base::Callback<IPC::Sender*(void)> sender_;
+
+  DISALLOW_ASSIGN(DWriteFontCollectionProxy);
+};
+
+// Implements the DirectWrite font family interface. This class is just a
+// stub, until something calls a method that requires actual font data. At that
+// point this will load the font files into a custom collection and
+// subsequently calls will be proxied to the resulting DirectWrite object.
+class CONTENT_EXPORT DWriteFontFamilyProxy
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
+          IDWriteFontFamily> {
+ public:
+  DWriteFontFamilyProxy();
+  ~DWriteFontFamilyProxy() override;
+
+  // IDWriteFontFamily:
+  HRESULT STDMETHODCALLTYPE
+  GetFontCollection(IDWriteFontCollection** font_collection) override;
+  UINT32 STDMETHODCALLTYPE GetFontCount() override;
+  HRESULT STDMETHODCALLTYPE GetFont(UINT32 index, IDWriteFont** font) override;
+  HRESULT STDMETHODCALLTYPE
+  GetFamilyNames(IDWriteLocalizedStrings** names) override;
+  HRESULT STDMETHODCALLTYPE
+  GetFirstMatchingFont(DWRITE_FONT_WEIGHT weight,
+                       DWRITE_FONT_STRETCH stretch,
+                       DWRITE_FONT_STYLE style,
+                       IDWriteFont** matching_font) override;
+  HRESULT STDMETHODCALLTYPE
+  GetMatchingFonts(DWRITE_FONT_WEIGHT weight,
+                   DWRITE_FONT_STRETCH stretch,
+                   DWRITE_FONT_STYLE style,
+                   IDWriteFontList** matching_fonts) override;
+
+  HRESULT STDMETHODCALLTYPE
+  RuntimeClassInitialize(DWriteFontCollectionProxy* collection, UINT32 index);
+
+  bool GetFontFromFontFace(IDWriteFontFace* font_face, IDWriteFont** font);
+
+  void SetName(const base::string16& family_name);
+
+  bool IsLoaded();
+
+ protected:
+  bool LoadFamily();
+
+ private:
+  UINT32 family_index_;
+  base::string16 family_name_;
+  Microsoft::WRL::ComPtr<DWriteFontCollectionProxy> proxy_collection_;
+  Microsoft::WRL::ComPtr<IDWriteFontFamily> family_;
+  Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> family_names_;
+
+  DISALLOW_ASSIGN(DWriteFontFamilyProxy);
+};
+
+// Implements the DirectWrite font file enumerator interface, backed by a list
+// of font files.
+class CONTENT_EXPORT FontFileEnumerator
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
+          IDWriteFontFileEnumerator> {
+ public:
+  FontFileEnumerator();
+  ~FontFileEnumerator() override;
+
+  // IDWriteFontFileEnumerator:
+  HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** file) override;
+  HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) override;
+
+  HRESULT STDMETHODCALLTYPE
+  RuntimeClassInitialize(IDWriteFactory* factory,
+                         IDWriteFontFileLoader* loader,
+                         std::vector<base::string16>* file_names);
+
+ private:
+  Microsoft::WRL::ComPtr<IDWriteFactory> factory_;
+  Microsoft::WRL::ComPtr<IDWriteFontFileLoader> loader_;
+  std::vector<base::string16> file_names_;
+  std::vector<Microsoft::WRL::ComPtr<IDWriteFontFileStream>> file_streams_;
+  UINT32 next_file_ = 0;
+  UINT32 current_file_ = UINT_MAX;
+
+  DISALLOW_ASSIGN(FontFileEnumerator);
+};
+
+// Implements the DirectWrite font file stream interface that maps the file to
+// be loaded as a memory mapped file, and subsequently returns pointers into
+// the mapped memory block.
+// TODO(kulshin): confirm that using custom streams is actually an improvement
+class CONTENT_EXPORT FontFileStream
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
+          IDWriteFontFileStream> {
+ public:
+  FontFileStream();
+  ~FontFileStream() override;
+
+  // IDWriteFontFileStream:
+  HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) override;
+  HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* last_write_time) override;
+  HRESULT STDMETHODCALLTYPE ReadFileFragment(const void** fragment_start,
+                                             UINT64 file_offset,
+                                             UINT64 fragment_size,
+                                             void** fragment_context) override;
+  void STDMETHODCALLTYPE ReleaseFileFragment(void* fragment_context) override {}
+
+  HRESULT STDMETHODCALLTYPE
+  RuntimeClassInitialize(const base::string16& file_name);
+
+ private:
+  base::MemoryMappedFile data_;
+
+  DISALLOW_ASSIGN(FontFileStream);
+};
+
+}  // namespace content
+#endif  // CONTENT_CHILD_DWRITE_FONT_PROXY_DWRITE_FONT_PROXY_WIN_H_
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc
new file mode 100644
index 0000000..10b83781
--- /dev/null
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc
@@ -0,0 +1,378 @@
+// Copyright (c) 2015 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/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
+
+#include <dwrite.h>
+#include <shlobj.h>
+#include <wrl.h>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/dwrite_font_proxy_messages.h"
+#include "content/common/view_messages.h"
+#include "content/test/dwrite_font_fake_sender_win.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_sender.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mswr = Microsoft::WRL;
+
+namespace content {
+
+namespace {
+
+void CreateDWriteFactory(IUnknown** factory) {
+  using DWriteCreateFactoryProc = decltype(DWriteCreateFactory)*;
+  HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
+  if (!dwrite_dll)
+    return;
+
+  DWriteCreateFactoryProc dwrite_create_factory_proc =
+      reinterpret_cast<DWriteCreateFactoryProc>(
+          GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
+  if (!dwrite_create_factory_proc)
+    return;
+
+  dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
+                             __uuidof(IDWriteFactory), factory);
+}
+
+class DWriteFontProxyUnitTest : public testing::Test {
+ public:
+  DWriteFontProxyUnitTest() {
+    if (!factory)
+      return;
+    fake_collection_ = new FakeFontCollection();
+    SetupFonts(fake_collection_.get());
+    mswr::MakeAndInitialize<DWriteFontCollectionProxy>(
+        &collection_, factory.Get(),
+        base::Bind(&FakeFontCollection::GetTrackingSender, fake_collection_));
+  }
+
+  ~DWriteFontProxyUnitTest() override {
+    if (collection_)
+      collection_->Unregister();
+  }
+
+  static void SetupFonts(FakeFontCollection* fonts) {
+    fonts->AddFont(L"Aardvark")
+        .AddFamilyName(L"en-us", L"Aardvark")
+        .AddFamilyName(L"de-de", L"Erdferkel")
+        .AddFilePath(L"X:\\Nonexistent\\Folder\\Aardvark.ttf");
+    FakeFont& arial =
+        fonts->AddFont(L"Arial").AddFamilyName(L"en-us", L"Arial");
+    for (auto& path : arial_font_files)
+      arial.AddFilePath(path);
+    fonts->AddFont(L"Times New Roman")
+        .AddFamilyName(L"en-us", L"Times New Roman")
+        .AddFilePath(L"X:\\Nonexistent\\Folder\\Times.ttf");
+  }
+
+  static void SetUpTestCase() {
+    CreateDWriteFactory(&factory);
+
+    std::vector<base::char16> font_path;
+    font_path.resize(MAX_PATH);
+    SHGetSpecialFolderPath(nullptr /* hwndOwner - reserved */, font_path.data(),
+                           CSIDL_FONTS, FALSE /* fCreate*/);
+    base::string16 arial;
+    arial.append(font_path.data()).append(L"\\arial.ttf");
+    base::string16 arialbd;
+    arialbd.append(font_path.data()).append(L"\\arialbd.ttf");
+    arial_font_files.push_back(arial);
+    arial_font_files.push_back(arialbd);
+  }
+
+ protected:
+  scoped_refptr<FakeFontCollection> fake_collection_;
+  mswr::ComPtr<DWriteFontCollectionProxy> collection_;
+
+  static std::vector<base::string16> arial_font_files;
+  static mswr::ComPtr<IDWriteFactory> factory;
+};
+std::vector<base::string16> DWriteFontProxyUnitTest::arial_font_files;
+mswr::ComPtr<IDWriteFactory> DWriteFontProxyUnitTest::factory;
+
+TEST_F(DWriteFontProxyUnitTest, GetFontFamilyCount) {
+  if (!factory)
+    return;
+
+  UINT32 family_count = collection_->GetFontFamilyCount();
+
+  EXPECT_EQ(3u, family_count);
+  ASSERT_EQ(1u, fake_collection_->MessageCount());
+  EXPECT_EQ(DWriteFontProxyMsg_GetFamilyCount::ID,
+            fake_collection_->GetMessage(0)->type());
+
+  // Calling again should not cause another message to be sent.
+  family_count = collection_->GetFontFamilyCount();
+  EXPECT_EQ(3u, family_count);
+  ASSERT_EQ(1u, fake_collection_->MessageCount());
+}
+
+TEST_F(DWriteFontProxyUnitTest, FindFamilyNameShouldFindFamily) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  hr = collection_->FindFamilyName(L"Arial", &index, &exists);
+
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(1u, index);
+  EXPECT_TRUE(exists);
+  ASSERT_EQ(2u, fake_collection_->MessageCount());
+  EXPECT_EQ(DWriteFontProxyMsg_FindFamily::ID,
+            fake_collection_->GetMessage(0)->type());
+  EXPECT_EQ(DWriteFontProxyMsg_GetFamilyCount::ID,
+            fake_collection_->GetMessage(1)->type());
+}
+
+TEST_F(DWriteFontProxyUnitTest, FindFamilyNameShouldReturnUINTMAXWhenNotFound) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  hr = collection_->FindFamilyName(L"Not a font", &index, &exists);
+
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(UINT32_MAX, index);
+  EXPECT_FALSE(exists);
+  ASSERT_EQ(1u, fake_collection_->MessageCount());
+  EXPECT_EQ(DWriteFontProxyMsg_FindFamily::ID,
+            fake_collection_->GetMessage(0)->type());
+}
+
+TEST_F(DWriteFontProxyUnitTest, FindFamilyNameShouldNotSendDuplicateIPC) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  hr = collection_->FindFamilyName(L"Arial", &index, &exists);
+  ASSERT_EQ(S_OK, hr);
+  ASSERT_EQ(2u, fake_collection_->MessageCount());
+
+  hr = collection_->FindFamilyName(L"Arial", &index, &exists);
+
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(2u, fake_collection_->MessageCount());
+}
+
+TEST_F(DWriteFontProxyUnitTest, GetFontFamilyShouldCreateFamily) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  hr = collection_->FindFamilyName(L"Arial", &index, &exists);
+  ASSERT_EQ(2u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteFontFamily> family;
+  hr = collection_->GetFontFamily(2, &family);
+
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(2u, fake_collection_->MessageCount());
+  EXPECT_NE(nullptr, family.Get());
+}
+
+void CheckLocale(const base::string16& locale_name,
+                 const base::string16& expected_value,
+                 IDWriteLocalizedStrings* strings) {
+  UINT32 locale_index = 0;
+  BOOL locale_exists = FALSE;
+  strings->FindLocaleName(locale_name.data(), &locale_index, &locale_exists);
+  EXPECT_TRUE(locale_exists);
+
+  UINT32 name_length = 0;
+  strings->GetLocaleNameLength(locale_index, &name_length);
+  EXPECT_EQ(locale_name.size(), name_length);
+  base::string16 actual_name;
+  name_length++;
+  actual_name.resize(name_length);
+  strings->GetLocaleName(locale_index, const_cast<WCHAR*>(actual_name.data()),
+                         name_length);
+  EXPECT_STREQ(locale_name.c_str(), actual_name.c_str());
+
+  UINT32 string_length = 0;
+  strings->GetStringLength(locale_index, &string_length);
+  EXPECT_EQ(expected_value.size(), string_length);
+  base::string16 actual_value;
+  string_length++;
+  actual_value.resize(string_length);
+  strings->GetString(locale_index, const_cast<WCHAR*>(actual_value.data()),
+                     string_length);
+  EXPECT_STREQ(expected_value.c_str(), actual_value.c_str());
+}
+
+TEST_F(DWriteFontProxyUnitTest, GetFamilyNames) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  hr = collection_->FindFamilyName(L"Aardvark", &index, &exists);
+  ASSERT_EQ(2u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteFontFamily> family;
+  hr = collection_->GetFontFamily(index, &family);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(2u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteLocalizedStrings> names;
+  hr = family->GetFamilyNames(&names);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+  EXPECT_EQ(DWriteFontProxyMsg_GetFamilyNames::ID,
+            fake_collection_->GetMessage(2)->type());
+
+  EXPECT_EQ(2, names->GetCount());
+  UINT32 locale_index = 0;
+  BOOL locale_exists = FALSE;
+  hr = names->FindLocaleName(L"fr-fr", &locale_index, &locale_exists);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_FALSE(locale_exists);
+
+  CheckLocale(L"en-us", L"Aardvark", names.Get());
+  CheckLocale(L"de-de", L"Erdferkel", names.Get());
+
+  base::string16 unused;
+  unused.resize(25);
+  hr = names->GetLocaleName(15234, const_cast<WCHAR*>(unused.data()),
+                            unused.size() - 1);
+  EXPECT_FALSE(SUCCEEDED(hr));
+}
+
+TEST_F(DWriteFontProxyUnitTest, GetFontCollection) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  hr = collection_->FindFamilyName(L"Arial", &index, &exists);
+  ASSERT_EQ(2u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteFontFamily> family;
+  hr = collection_->GetFontFamily(2, &family);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(2u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteFontCollection> returned_collection;
+  hr = family->GetFontCollection(&returned_collection);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(2u, fake_collection_->MessageCount());
+  EXPECT_EQ(collection_.Get(), returned_collection.Get());
+}
+
+TEST_F(DWriteFontProxyUnitTest, GetFamilyNamesShouldNotIPCAfterLoadingFamily) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  collection_->FindFamilyName(L"Arial", &index, &exists);
+  mswr::ComPtr<IDWriteFontFamily> family;
+  collection_->GetFontFamily(index, &family);
+  family->GetFontCount();
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteLocalizedStrings> names;
+  hr = family->GetFamilyNames(&names);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+}
+
+TEST_F(DWriteFontProxyUnitTest,
+       GetFontFamilyShouldNotCreateFamilyWhenIndexIsInvalid) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  hr = collection_->FindFamilyName(L"Arial", &index, &exists);
+  ASSERT_EQ(2u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteFontFamily> family;
+  hr = collection_->GetFontFamily(1654, &family);
+
+  EXPECT_FALSE(SUCCEEDED(hr));
+  EXPECT_EQ(2u, fake_collection_->MessageCount());
+}
+
+TEST_F(DWriteFontProxyUnitTest, LoadingFontFamily) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  collection_->FindFamilyName(L"Arial", &index, &exists);
+  mswr::ComPtr<IDWriteFontFamily> family;
+  collection_->GetFontFamily(index, &family);
+  ASSERT_EQ(2u, fake_collection_->MessageCount());
+
+  UINT32 font_count = family->GetFontCount();
+  EXPECT_LT(0u, font_count);
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+  EXPECT_EQ(DWriteFontProxyMsg_GetFontFiles::ID,
+            fake_collection_->GetMessage(2)->type());
+  mswr::ComPtr<IDWriteFont> font;
+  hr = family->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL,
+                                    DWRITE_FONT_STRETCH_NORMAL,
+                                    DWRITE_FONT_STYLE_NORMAL, &font);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+  mswr::ComPtr<IDWriteFont> font2;
+  hr = family->GetFont(0, &font2);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+  mswr::ComPtr<IDWriteFontList> matching_fonts;
+  hr = family->GetMatchingFonts(DWRITE_FONT_WEIGHT_NORMAL,
+                                DWRITE_FONT_STRETCH_NORMAL,
+                                DWRITE_FONT_STYLE_NORMAL, &matching_fonts);
+  EXPECT_EQ(S_OK, hr);
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+  EXPECT_NE(nullptr, matching_fonts.Get());
+}
+
+TEST_F(DWriteFontProxyUnitTest, GetFontFromFontFaceShouldFindFont) {
+  HRESULT hr;
+  if (!factory)
+    return;
+
+  UINT32 index = UINT_MAX;
+  BOOL exists = FALSE;
+  collection_->FindFamilyName(L"Arial", &index, &exists);
+  mswr::ComPtr<IDWriteFontFamily> family;
+  collection_->GetFontFamily(index, &family);
+
+  mswr::ComPtr<IDWriteFont> font;
+  family->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL,
+                               DWRITE_FONT_STRETCH_NORMAL,
+                               DWRITE_FONT_STYLE_NORMAL, &font);
+
+  mswr::ComPtr<IDWriteFontFace> font_face;
+  hr = font->CreateFontFace(&font_face);
+  ASSERT_TRUE(SUCCEEDED(hr));
+  ASSERT_EQ(3u, fake_collection_->MessageCount());
+
+  mswr::ComPtr<IDWriteFont> found_font;
+  collection_->GetFontFromFontFace(font_face.Get(), &found_font);
+  EXPECT_NE(nullptr, found_font.Get());
+  EXPECT_EQ(3u, fake_collection_->MessageCount());
+}
+
+}  // namespace
+
+}  // namespace content
diff --git a/content/child/dwrite_font_proxy/dwrite_localized_strings_win.cc b/content/child/dwrite_font_proxy/dwrite_localized_strings_win.cc
new file mode 100644
index 0000000..27f8fa4
--- /dev/null
+++ b/content/child/dwrite_font_proxy/dwrite_localized_strings_win.cc
@@ -0,0 +1,91 @@
+// Copyright 2015 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/child/dwrite_font_proxy/dwrite_localized_strings_win.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+DWriteLocalizedStrings::DWriteLocalizedStrings() = default;
+
+DWriteLocalizedStrings::~DWriteLocalizedStrings() = default;
+
+HRESULT DWriteLocalizedStrings::FindLocaleName(const WCHAR* locale_name,
+                                               UINT32* index,
+                                               BOOL* exists) {
+  for (size_t n = 0; n < strings_.size(); ++n) {
+    if (_wcsicmp(strings_[n].first.data(), locale_name) == 0) {
+      *index = n;
+      *exists = TRUE;
+      return S_OK;
+    }
+  }
+
+  *index = UINT_MAX;
+  *exists = FALSE;
+  return S_OK;
+}
+
+UINT32 DWriteLocalizedStrings::GetCount() {
+  return strings_.size();
+}
+
+HRESULT DWriteLocalizedStrings::GetLocaleName(UINT32 index,
+                                              WCHAR* locale_name,
+                                              UINT32 size) {
+  if (index >= strings_.size())
+    return E_INVALIDARG;
+  // string16::size does not count the null terminator as part of the string,
+  // but GetLocaleName requires the caller to reserve space for the null
+  // terminator, so we need to ensure |size| is greater than the count of
+  // characters.
+  if (size <= strings_[index].first.size())
+    return E_INVALIDARG;
+  wcsncpy(locale_name, strings_[index].first.c_str(), size);
+  return S_OK;
+}
+
+HRESULT DWriteLocalizedStrings::GetLocaleNameLength(UINT32 index,
+                                                    UINT32* length) {
+  if (index >= strings_.size())
+    return E_INVALIDARG;
+  // Oddly, GetLocaleNameLength requires the length to not count the null
+  // terminator, even though GetLocaleName requires the output to be null
+  // terminated.
+  *length = strings_[index].first.size();
+  return S_OK;
+}
+
+HRESULT DWriteLocalizedStrings::GetString(UINT32 index,
+                                          WCHAR* string_buffer,
+                                          UINT32 size) {
+  if (index >= strings_.size())
+    return E_INVALIDARG;
+  // string16::size does not count the null terminator as part of the string,
+  // but GetString requires the caller to reserve space for the null terminator,
+  // so we need to ensure |size| is greater than the count of characters.
+  if (size <= strings_[index].second.size())
+    return E_INVALIDARG;
+  wcsncpy(string_buffer, strings_[index].second.c_str(), size);
+  return S_OK;
+}
+
+HRESULT DWriteLocalizedStrings::GetStringLength(UINT32 index, UINT32* length) {
+  if (index >= strings_.size())
+    return E_INVALIDARG;
+  // Oddly, GetStringLength requires the length to not count the null
+  // terminator, even though GetString requires the output to be null
+  // terminated.
+  *length = strings_[index].second.size();
+  return S_OK;
+}
+
+HRESULT DWriteLocalizedStrings::RuntimeClassInitialize(
+    std::vector<std::pair<base::string16, base::string16>>* strings) {
+  strings_.swap(*strings);
+  return S_OK;
+}
+
+}  // namespace content
diff --git a/content/child/dwrite_font_proxy/dwrite_localized_strings_win.h b/content/child/dwrite_font_proxy/dwrite_localized_strings_win.h
new file mode 100644
index 0000000..796f435
--- /dev/null
+++ b/content/child/dwrite_font_proxy/dwrite_localized_strings_win.h
@@ -0,0 +1,57 @@
+// Copyright 2015 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_CHILD_DWRITE_FONT_PROXY_DWRITE_LOCALIZED_STRINGS_WIN_H_
+#define CONTENT_CHILD_DWRITE_FONT_PROXY_DWRITE_LOCALIZED_STRINGS_WIN_H_
+
+#include <dwrite.h>
+#include <wrl.h>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+
+namespace content {
+
+// Impements IDWriteLocalizedStrings, backed by a vector of string pairs.
+class DWriteLocalizedStrings
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
+          IDWriteLocalizedStrings> {
+ public:
+  DWriteLocalizedStrings();
+  ~DWriteLocalizedStrings() override;
+
+  // IDWriteLocalizedStrings:
+  HRESULT STDMETHODCALLTYPE FindLocaleName(const WCHAR* locale_name,
+                                           UINT32* index,
+                                           BOOL* exists) override;
+  UINT32 STDMETHODCALLTYPE GetCount() override;
+  HRESULT STDMETHODCALLTYPE GetLocaleName(UINT32 index,
+                                          WCHAR* locale_name,
+                                          UINT32 size) override;
+  HRESULT STDMETHODCALLTYPE GetLocaleNameLength(UINT32 index,
+                                                UINT32* length) override;
+  HRESULT STDMETHODCALLTYPE GetString(UINT32 index,
+                                      WCHAR* string_buffer,
+                                      UINT32 size) override;
+  HRESULT STDMETHODCALLTYPE GetStringLength(UINT32 index,
+                                            UINT32* length) override;
+
+  HRESULT STDMETHODCALLTYPE RuntimeClassInitialize(
+      std::vector<std::pair<base::string16, base::string16>>* strings);
+
+ private:
+  // List of strings. First element of each pair is the locale, and the second
+  // element is the associated value. Use a vector because the expected number
+  // of pairs is small (typically 1-2, rarely up to a few dozen?) and we need
+  // index-based access.
+  std::vector<std::pair<base::string16, base::string16>> strings_;
+
+  DISALLOW_ASSIGN(DWriteLocalizedStrings);
+};
+
+}  // namespace content
+#endif  // CONTENT_CHILD_DWRITE_FONT_PROXY_DWRITE_LOCALIZED_STRINGS_WIN_H_
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 3a8bffa..274a9026 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -19,7 +19,7 @@
 #include <cpu-features.h>
 #include "base/android/build_info.h"
 #include "base/metrics/field_trial.h"
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #elif defined(OS_WIN)
 #include "base/win/windows_version.h"
 #endif
@@ -34,7 +34,7 @@
 
 #if defined(OS_ANDROID)
   // MSE/EME implementation needs Android MediaCodec API.
-  if (!media::MediaCodecUtil::IsMediaCodecAvailable()) {
+  if (!media::MediaCodecBridge::IsAvailable()) {
     WebRuntimeFeatures::enableMediaSource(false);
     WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
     WebRuntimeFeatures::enableEncryptedMedia(false);
@@ -43,7 +43,7 @@
   // is available.
   AndroidCpuFamily cpu_family = android_getCpuFamily();
   WebRuntimeFeatures::enableWebAudio(
-      media::MediaCodecUtil::IsMediaCodecAvailable() &&
+      media::MediaCodecBridge::IsAvailable() &&
       ((cpu_family == ANDROID_CPU_FAMILY_ARM) ||
        (cpu_family == ANDROID_CPU_FAMILY_ARM64) ||
        (cpu_family == ANDROID_CPU_FAMILY_X86) ||
@@ -121,7 +121,7 @@
   // API is available.
   WebRuntimeFeatures::enableWebAudio(
       !command_line.HasSwitch(switches::kDisableWebAudio) &&
-      media::MediaCodecUtil::IsMediaCodecAvailable());
+      media::MediaCodecBridge::IsAvailable());
 #else
   if (command_line.HasSwitch(switches::kDisableWebAudio))
     WebRuntimeFeatures::enableWebAudio(false);
diff --git a/content/common/DEPS b/content/common/DEPS
index a890606f..3ba16c40 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -25,11 +25,11 @@
   "+third_party/WebKit/public/platform/WebPageVisibilityState.h",
   "+third_party/WebKit/public/platform/WebReferrerPolicy.h",
   "+third_party/WebKit/public/platform/WebScreenInfo.h",
+  "+third_party/WebKit/public/platform/WebScrollbarButtonsPlacement.h",
   "+third_party/WebKit/public/platform/WebStorageArea.h",
   "+third_party/WebKit/public/platform/WebString.h",
   "+third_party/WebKit/public/platform/linux/WebFallbackFont.h",
   "+third_party/WebKit/public/platform/linux/WebFontRenderStyle.h",
-  "+third_party/WebKit/public/platform/mac/MacScrollTypes.h",
   "+third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h",
   "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h",
   "+third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h",
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index a3b31ad4..9210587 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -74,3 +74,7 @@
 #include "content/common/media/media_player_messages_android.h"
 #include "content/common/media/media_session_messages_android.h"
 #endif  // defined(OS_ANDROID)
+
+#if defined(OS_WIN)
+#include "content/common/dwrite_font_proxy_messages.h"
+#endif  // defined(OS_WIN)
diff --git a/content/common/dwrite_font_proxy_messages.h b/content/common/dwrite_font_proxy_messages.h
new file mode 100644
index 0000000..84cb751
--- /dev/null
+++ b/content/common/dwrite_font_proxy_messages.h
@@ -0,0 +1,39 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_message_macros.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+#define IPC_MESSAGE_START DWriteFontProxyMsgStart
+
+// The macros can't handle a complex template declaration, so we typedef it.
+typedef std::pair<base::string16, base::string16> DWriteStringPair;
+
+// Locates the index of the specified font family within the system collection.
+IPC_SYNC_MESSAGE_CONTROL1_1(DWriteFontProxyMsg_FindFamily,
+                            base::string16 /* family_name */,
+                            uint32_t /* out index */)
+
+// Returns the number of font families in the system collection.
+IPC_SYNC_MESSAGE_CONTROL0_1(DWriteFontProxyMsg_GetFamilyCount,
+                            uint32_t /* out count */)
+
+// Returns the list of locale and family name pairs for the font family at the
+// specified index.
+IPC_SYNC_MESSAGE_CONTROL1_1(
+    DWriteFontProxyMsg_GetFamilyNames,
+    uint32_t /* family_index */,
+    std::vector<DWriteStringPair> /* out family_names */)
+
+// Returns the list of font file paths in the system font directory that contain
+// font data for the font family at the specified index.
+IPC_SYNC_MESSAGE_CONTROL1_1(DWriteFontProxyMsg_GetFontFiles,
+                            uint32_t /* family_index */,
+                            std::vector<base::string16> /* out file_paths */)
diff --git a/content/common/font_warmup_win.cc b/content/common/font_warmup_win.cc
index 6a059d0..ddc1889 100644
--- a/content/common/font_warmup_win.cc
+++ b/content/common/font_warmup_win.cc
@@ -96,56 +96,6 @@
   return STATUS_ACCESS_DENIED;
 }
 
-// Directwrite connects to the font cache service to retrieve information about
-// fonts installed on the system etc. This works well outside the sandbox and
-// within the sandbox as long as the lpc connection maintained by the current
-// process with the font cache service remains valid. It appears that there
-// are cases when this connection is dropped after which directwrite is unable
-// to connect to the font cache service which causes problems with characters
-// disappearing.
-// Directwrite has fallback code to enumerate fonts if it is unable to connect
-// to the font cache service. We need to intercept the following APIs to
-// ensure that it does not connect to the font cache service.
-// NtALpcConnectPort
-// OpenSCManagerW
-// OpenServiceW
-// StartServiceW
-// CloseServiceHandle.
-// These are all IAT patched.
-void PatchServiceManagerCalls() {
-  static bool is_patched = false;
-  if (is_patched)
-    return;
-  const char* service_provider_dll =
-      (base::win::GetVersion() >= base::win::VERSION_WIN8
-           ? "api-ms-win-service-management-l1-1-0.dll"
-           : "advapi32.dll");
-
-  is_patched = true;
-
-  DWORD patched =
-      g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", service_provider_dll,
-                                        "OpenSCManagerW", OpenSCManagerWPatch);
-  DCHECK(patched == 0);
-
-  patched = g_iat_patch_close_service_handle.Patch(
-      L"dwrite.dll", service_provider_dll, "CloseServiceHandle",
-      CloseServiceHandlePatch);
-  DCHECK(patched == 0);
-
-  patched = g_iat_patch_open_service.Patch(L"dwrite.dll", service_provider_dll,
-                                           "OpenServiceW", OpenServiceWPatch);
-  DCHECK(patched == 0);
-
-  patched = g_iat_patch_start_service.Patch(
-      L"dwrite.dll", service_provider_dll, "StartServiceW", StartServiceWPatch);
-  DCHECK(patched == 0);
-
-  patched = g_iat_patch_nt_connect_port.Patch(
-      L"dwrite.dll", "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch);
-  DCHECK(patched == 0);
-}
-
 // Windows-only DirectWrite support. These warm up the DirectWrite paths
 // before sandbox lock down to allow Skia access to the Font Manager service.
 void CreateDirectWriteFactory(IDWriteFactory** factory) {
@@ -461,6 +411,56 @@
 
 }  // namespace
 
+// Directwrite connects to the font cache service to retrieve information about
+// fonts installed on the system etc. This works well outside the sandbox and
+// within the sandbox as long as the lpc connection maintained by the current
+// process with the font cache service remains valid. It appears that there
+// are cases when this connection is dropped after which directwrite is unable
+// to connect to the font cache service which causes problems with characters
+// disappearing.
+// Directwrite has fallback code to enumerate fonts if it is unable to connect
+// to the font cache service. We need to intercept the following APIs to
+// ensure that it does not connect to the font cache service.
+// NtALpcConnectPort
+// OpenSCManagerW
+// OpenServiceW
+// StartServiceW
+// CloseServiceHandle.
+// These are all IAT patched.
+void PatchServiceManagerCalls() {
+  static bool is_patched = false;
+  if (is_patched)
+    return;
+  const char* service_provider_dll =
+      (base::win::GetVersion() >= base::win::VERSION_WIN8
+           ? "api-ms-win-service-management-l1-1-0.dll"
+           : "advapi32.dll");
+
+  is_patched = true;
+
+  DWORD patched =
+      g_iat_patch_open_sc_manager.Patch(L"dwrite.dll", service_provider_dll,
+                                        "OpenSCManagerW", OpenSCManagerWPatch);
+  DCHECK(patched == 0);
+
+  patched = g_iat_patch_close_service_handle.Patch(
+      L"dwrite.dll", service_provider_dll, "CloseServiceHandle",
+      CloseServiceHandlePatch);
+  DCHECK(patched == 0);
+
+  patched = g_iat_patch_open_service.Patch(L"dwrite.dll", service_provider_dll,
+                                           "OpenServiceW", OpenServiceWPatch);
+  DCHECK(patched == 0);
+
+  patched = g_iat_patch_start_service.Patch(
+      L"dwrite.dll", service_provider_dll, "StartServiceW", StartServiceWPatch);
+  DCHECK(patched == 0);
+
+  patched = g_iat_patch_nt_connect_port.Patch(
+      L"dwrite.dll", "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch);
+  DCHECK(patched == 0);
+}
+
 void DoPreSandboxWarmupForTypeface(SkTypeface* typeface) {
   SkPaint paint_warmup;
   paint_warmup.setTypeface(typeface);
diff --git a/content/common/font_warmup_win.h b/content/common/font_warmup_win.h
index 7a0e9b5..587b731a 100644
--- a/content/common/font_warmup_win.h
+++ b/content/common/font_warmup_win.h
@@ -50,6 +50,24 @@
 // Warmup the direct write font manager for content processes.
 CONTENT_EXPORT void WarmupDirectWrite();
 
+// Directwrite connects to the font cache service to retrieve information about
+// fonts installed on the system etc. This works well outside the sandbox and
+// within the sandbox as long as the lpc connection maintained by the current
+// process with the font cache service remains valid. It appears that there
+// are cases when this connection is dropped after which directwrite is unable
+// to connect to the font cache service which causes problems with characters
+// disappearing.
+// Directwrite has fallback code to enumerate fonts if it is unable to connect
+// to the font cache service. We need to intercept the following APIs to
+// ensure that it does not connect to the font cache service.
+// NtALpcConnectPort
+// OpenSCManagerW
+// OpenServiceW
+// StartServiceW
+// CloseServiceHandle.
+// These are all IAT patched.
+CONTENT_EXPORT void PatchServiceManagerCalls();
+
 }  // namespace content
 
 #endif  // CONTENT_COMMON_FONT_WARMUP_WIN_H_
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 08b7337..3e7e8e49 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -29,6 +29,7 @@
 #include "content/public/common/three_d_api_types.h"
 #include "content/public/common/transition_element.h"
 #include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_platform_file.h"
 #include "third_party/WebKit/public/platform/WebFocusType.h"
 #include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
 #include "third_party/WebKit/public/web/WebTreeScopeType.h"
@@ -47,6 +48,9 @@
 using FrameMsg_GetSerializedHtmlWithLocalLinks_Map =
     std::map<GURL, base::FilePath>;
 
+using FrameMsg_SerializeAsMHTML_FrameRoutingIdToContentIdMap =
+    std::map<int, std::string>;
+
 #endif  // CONTENT_COMMON_FRAME_MESSAGES_H_
 
 #undef IPC_MESSAGE_EXPORT
@@ -727,6 +731,30 @@
 IPC_MESSAGE_ROUTED1(FrameMsg_GetSerializedHtmlWithLocalLinks,
                     FrameMsg_GetSerializedHtmlWithLocalLinks_Map)
 
+// Serialize target frame and its resources into MHTML and write it into the
+// provided destination file handle.
+//
+// When starting generation of a new MHTML document, one needs to start by
+// sending FrameMsg_SerializeAsMHTML for the *main* frame (main frame needs to
+// be the first part in the MHTML document + main frame will trigger generation
+// of the MHTML header).
+//
+// The same |mhtml_boundary_marker| should be used for serialization of each
+// frame (this string will be used as a mime multipart boundary within the mhtml
+// document).
+//
+// For more details about frame to content id map please see
+// WebPageSerializer::generateMHTMLParts method.
+//
+// |is_last_frame| controls whether the serializer in the renderer will
+// emit the MHTML footer.
+IPC_MESSAGE_ROUTED5(FrameMsg_SerializeAsMHTML,
+                    int /* job_id (used to match responses to requests) */,
+                    IPC::PlatformFileForTransit /* destination file handle */,
+                    std::string /* mhtml boundary marker */,
+                    FrameMsg_SerializeAsMHTML_FrameRoutingIdToContentIdMap,
+                    bool /* is last frame */)
+
 IPC_MESSAGE_ROUTED1(FrameMsg_SetFrameOwnerProperties,
                     blink::WebFrameOwnerProperties /* frame_owner_properties */)
 
@@ -1264,6 +1292,11 @@
                     std::string /* data buffer */,
                     bool /* end of data? */)
 
+// Response to FrameMsg_SerializeAsMHTML.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_SerializeAsMHTMLResponse,
+                    int /* job_id (used to match responses to requests) */,
+                    bool /* true if success, false if error */)
+
 // Sent when the renderer updates hint for importance of a tab.
 IPC_MESSAGE_ROUTED1(FrameHostMsg_UpdatePageImportanceSignals,
                     content::PageImportanceSignals)
diff --git a/content/common/gpu/media/android_video_decode_accelerator.h b/content/common/gpu/media/android_video_decode_accelerator.h
index 6221ad9..e79f0c0 100644
--- a/content/common/gpu/media/android_video_decode_accelerator.h
+++ b/content/common/gpu/media/android_video_decode_accelerator.h
@@ -17,7 +17,7 @@
 #include "content/common/content_export.h"
 #include "content/common/gpu/media/avda_state_provider.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/video/video_decode_accelerator.h"
 
 namespace gfx {
diff --git a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
index 400d7cc..5ad3f2c 100644
--- a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
@@ -12,7 +12,7 @@
 #include "content/common/gpu/media/android_copying_backing_strategy.h"
 #include "content/common/gpu/media/android_video_decode_accelerator.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_jni_registrar.h"
 #include "media/video/picture.h"
 #include "media/video/video_decode_accelerator.h"
@@ -91,7 +91,7 @@
 }
 
 TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureSupportedCodec) {
-  if (!media::MediaCodecUtil::IsMediaCodecAvailable())
+  if (!media::MediaCodecBridge::IsAvailable())
     return;
   EXPECT_TRUE(Configure(media::kCodecVP8));
 }
diff --git a/content/common/gpu/media/android_video_encode_accelerator.cc b/content/common/gpu/media/android_video_encode_accelerator.cc
index 72689c90..06931bf 100644
--- a/content/common/gpu/media/android_video_encode_accelerator.cc
+++ b/content/common/gpu/media/android_video_encode_accelerator.cc
@@ -14,7 +14,7 @@
 #include "content/common/gpu/gpu_channel.h"
 #include "content/public/common/content_switches.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/bitstream_buffer.h"
 #include "media/base/limits.h"
 #include "media/video/picture.h"
@@ -22,6 +22,7 @@
 #include "ui/gl/android/scoped_java_surface.h"
 #include "ui/gl/gl_bindings.h"
 
+using media::MediaCodecBridge;
 using media::VideoCodecBridge;
 using media::VideoFrame;
 
@@ -82,7 +83,7 @@
   if (mime.empty())
     return false;
 
-  std::set<int> formats = media::MediaCodecUtil::GetEncoderColorFormats(mime);
+  std::set<int> formats = MediaCodecBridge::GetEncoderColorFormats(mime);
   if (formats.count(COLOR_FORMAT_YUV420_SEMIPLANAR) > 0)
     *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR;
   else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0)
@@ -156,8 +157,8 @@
 
   client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
 
-  if (!(media::MediaCodecUtil::SupportsSetParameters() &&
-      format == media::PIXEL_FORMAT_I420)) {
+  if (!(media::MediaCodecBridge::SupportsSetParameters() &&
+        format == media::PIXEL_FORMAT_I420)) {
     DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile;
     return false;
   }
diff --git a/content/common/gpu/media/android_video_encode_accelerator.h b/content/common/gpu/media/android_video_encode_accelerator.h
index 1528726..6608b87a 100644
--- a/content/common/gpu/media/android_video_encode_accelerator.h
+++ b/content/common/gpu/media/android_video_encode_accelerator.h
@@ -16,7 +16,7 @@
 #include "base/timer/timer.h"
 #include "base/tuple.h"
 #include "content/common/content_export.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/video/video_encode_accelerator.h"
 
 namespace media {
diff --git a/content/common/gpu/media/avda_shared_state.h b/content/common/gpu/media/avda_shared_state.h
index 474037d..a64bf3a 100644
--- a/content/common/gpu/media/avda_shared_state.h
+++ b/content/common/gpu/media/avda_shared_state.h
@@ -6,7 +6,7 @@
 #define CONTENT_COMMON_GPU_AVDA_SHARED_STATE_H_
 
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "ui/gl/gl_image.h"
 
 namespace gfx {
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index a95ad796..860c1981 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -35,7 +35,6 @@
 #include "content/public/common/window_container_type.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_platform_file.h"
 #include "media/audio/audio_parameters.h"
 #include "media/base/channel_layout.h"
 #include "media/base/media_log_event.h"
@@ -66,7 +65,7 @@
 #include "ui/gfx/range/range.h"
 
 #if defined(OS_MACOSX)
-#include "third_party/WebKit/public/platform/mac/MacScrollTypes.h"
+#include "third_party/WebKit/public/platform/WebScrollbarButtonsPlacement.h"
 #include "third_party/WebKit/public/web/mac/WebScrollbarTheme.h"
 #endif
 
@@ -119,8 +118,8 @@
 
 #if defined(OS_MACOSX)
 IPC_ENUM_TRAITS_MAX_VALUE(
-    blink::ScrollbarButtonsPlacement,
-    blink::ScrollbarButtonsPlacement::ScrollbarButtonsPlacementLast)
+    blink::WebScrollbarButtonsPlacement,
+    blink::WebScrollbarButtonsPlacement::WebScrollbarButtonsPlacementLast)
 
 IPC_ENUM_TRAITS_MAX_VALUE(blink::ScrollerStyle, blink::ScrollerStyleOverlay)
 #endif
@@ -575,7 +574,7 @@
   IPC_STRUCT_MEMBER(blink::ScrollerStyle, preferred_scroller_style)
   IPC_STRUCT_MEMBER(bool, redraw)
   IPC_STRUCT_MEMBER(bool, scroll_animation_enabled)
-  IPC_STRUCT_MEMBER(blink::ScrollbarButtonsPlacement, button_placement)
+  IPC_STRUCT_MEMBER(blink::WebScrollbarButtonsPlacement, button_placement)
 IPC_STRUCT_END()
 #endif
 
@@ -886,11 +885,6 @@
 // Used to instruct the RenderView to go into "view source" mode.
 IPC_MESSAGE_ROUTED0(ViewMsg_EnableViewSourceMode)
 
-// Instructs the renderer to save the current page to MHTML.
-IPC_MESSAGE_ROUTED2(ViewMsg_SavePageAsMHTML,
-                    int /* job_id */,
-                    IPC::PlatformFileForTransit /* file handle */)
-
 // An acknowledge to ViewHostMsg_MultipleTargetsTouched to notify the renderer
 // process to release the magnified image.
 IPC_MESSAGE_ROUTED1(ViewMsg_ReleaseDisambiguationPopupBitmap,
@@ -1295,11 +1289,6 @@
 IPC_MESSAGE_CONTROL1(ViewHostMsg_UserMetricsRecordAction,
                      std::string /* action */)
 
-// Notifies the browser that the page was or was not saved as MHTML.
-IPC_MESSAGE_CONTROL2(ViewHostMsg_SavedPageAsMHTML,
-                     int /* job_id */,
-                     int64 /* size of the MHTML file, -1 if error */)
-
 // Notifies the browser of an event occurring in the media pipeline.
 IPC_MESSAGE_CONTROL1(ViewHostMsg_MediaLogEvents,
                      std::vector<media::MediaLogEvent> /* events */)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 6cea7d4..2fba878b 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1126,6 +1126,8 @@
       'browser/renderer_host/delegated_frame_evictor.h',
       'browser/renderer_host/dip_util.cc',
       'browser/renderer_host/dip_util.h',
+      'browser/renderer_host/dwrite_font_proxy_message_filter_win.cc',
+      'browser/renderer_host/dwrite_font_proxy_message_filter_win.h',
       'browser/renderer_host/event_with_latency_info.h',
       'browser/renderer_host/file_utilities_message_filter.cc',
       'browser/renderer_host/file_utilities_message_filter.h',
diff --git a/content/content_child.gypi b/content/content_child.gypi
index 792e2fe03..81c0a05 100644
--- a/content/content_child.gypi
+++ b/content/content_child.gypi
@@ -82,6 +82,12 @@
       'child/database_util.h',
       'child/db_message_filter.cc',
       'child/db_message_filter.h',
+      'child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc',
+      'child/dwrite_font_proxy/dwrite_font_proxy_init_win.h',
+      'child/dwrite_font_proxy/dwrite_font_proxy_win.cc',
+      'child/dwrite_font_proxy/dwrite_font_proxy_win.h',
+      'child/dwrite_font_proxy/dwrite_localized_strings_win.cc',
+      'child/dwrite_font_proxy/dwrite_localized_strings_win.h',
       'child/file_info_util.cc',
       'child/file_info_util.h',
       'child/fileapi/file_system_dispatcher.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi
index d1fb8a7..463b8cd 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -249,6 +249,7 @@
       'common/drag_messages.h',
       'common/drag_traits.h',
       'common/dwrite_font_platform_win.cc',
+      'common/dwrite_font_proxy_messages.h',
       'common/edit_command.h',
       'common/file_utilities_messages.h',
       'common/fileapi/file_system_messages.h',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 0dd79c6f..92d135e 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -343,8 +343,6 @@
       'renderer/memory_benchmarking_extension.h',
       'renderer/menu_item_builder.cc',
       'renderer/menu_item_builder.h',
-      'renderer/mhtml_generator.cc',
-      'renderer/mhtml_generator.h',
       'renderer/mojo/service_registry_js_wrapper.cc',
       'renderer/mojo/service_registry_js_wrapper.h',
       'renderer/mojo_bindings_controller.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 8fc67f52..cf3427c 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -116,6 +116,8 @@
       'test/content_browser_sanity_checker.h',
       'test/content_test_suite.cc',
       'test/content_test_suite.h',
+      'test/dwrite_font_fake_sender_win.h',
+      'test/dwrite_font_fake_sender_win.cc',
       'test/fake_compositor_dependencies.cc',
       'test/fake_compositor_dependencies.h',
       'test/fake_plugin_service.cc',
@@ -533,6 +535,7 @@
       'browser/quota/usage_tracker_unittest.cc',
       'browser/renderer_host/begin_frame_observer_proxy_unittest.cc',
       'browser/renderer_host/clipboard_message_filter_unittest.cc',
+      'browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc',
       'browser/renderer_host/event_with_latency_info_unittest.cc',
       'browser/renderer_host/input/gesture_event_queue_unittest.cc',
       'browser/renderer_host/input/input_router_impl_unittest.cc',
@@ -624,6 +627,7 @@
       'child/blink_platform_impl_unittest.cc',
       'child/blob_storage/blob_consolidation_unittest.cc',
       'child/blob_storage/blob_transport_controller_unittest.cc',
+      'child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc',
       'child/fileapi/webfilewriter_base_unittest.cc',
       'child/indexed_db/indexed_db_dispatcher_unittest.cc',
       'child/indexed_db/mock_webidbcallbacks.cc',
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index e2d6cef..04c3745c 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -12,6 +12,7 @@
 import android.os.ParcelUuid;
 import android.os.Parcelable;
 
+import org.chromium.base.ObserverList;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -425,6 +426,12 @@
         mObserverProxy.removeObserver(observer);
     }
 
+    @VisibleForTesting
+    @Override
+    public ObserverList.RewindableIterator<WebContentsObserver> getObserversForTesting() {
+        return mObserverProxy.getObserversForTesting();
+    }
+
     @Override
     public void getContentBitmapAsync(Bitmap.Config config, float scale, Rect srcRect,
             ContentBitmapCallback callback) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
index 1c364305..9521812 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
@@ -7,6 +7,7 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.ObserverList.RewindableIterator;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.MainDex;
@@ -61,6 +62,14 @@
         return !mObservers.isEmpty();
     }
 
+    /**
+     * @return The list of proxied observers.
+     */
+    @VisibleForTesting
+    public ObserverList.RewindableIterator<WebContentsObserver> getObserversForTesting() {
+        return mObservers.rewindableIterator();
+    }
+
     @Override
     @CalledByNative
     public void renderViewReady() {
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
index 4a1729b1..e58dd60 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -8,6 +8,7 @@
 import android.graphics.Rect;
 import android.os.Parcelable;
 
+import org.chromium.base.ObserverList;
 import org.chromium.base.VisibleForTesting;
 
 /**
@@ -323,6 +324,12 @@
     void removeObserver(WebContentsObserver observer);
 
     /**
+     * @return The list of observers.
+     */
+    @VisibleForTesting
+    ObserverList.RewindableIterator<WebContentsObserver> getObserversForTesting();
+
+    /**
      * Called when context menu gets opened.
      */
     void onContextMenuOpened();
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index d4669bb..abe79f2 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -382,6 +382,9 @@
 // Enables the memory benchmarking extension
 const char kEnableMemoryBenchmarking[]      = "enable-memory-benchmarking";
 
+// Enable the Mojo shell connection in renderers.
+const char kEnableMojoShellConnection[] = "enable-mojo-shell-connection";
+
 // Enables the network information API.
 const char kEnableNetworkInformation[]      = "enable-network-information";
 
@@ -988,9 +991,6 @@
 const char kTraceExportEventsToETW[] = "trace-export-events-to-etw";
 #endif
 
-// Enable the Mojo shell connection in renderers.
-const char kEnableMojoShellConnection[] = "enable-mojo-shell-connection";
-
 // Don't dump stuff here, follow the same order as the header.
 
 }  // namespace switches
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index d6451bd4..bd68910 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -118,6 +118,7 @@
 CONTENT_EXPORT extern const char kEnableLCDText[];
 CONTENT_EXPORT extern const char kEnableLogging[];
 extern const char kEnableMemoryBenchmarking[];
+CONTENT_EXPORT extern const char kEnableMojoShellConnection[];
 CONTENT_EXPORT extern const char kEnableNetworkInformation[];
 CONTENT_EXPORT extern const char kEnablePartialRaster[];
 CONTENT_EXPORT extern const char kEnablePinch[];
@@ -301,8 +302,6 @@
 CONTENT_EXPORT extern const char kTraceExportEventsToETW[];
 #endif
 
-CONTENT_EXPORT extern const char kEnableMojoShellConnection[];
-
 // DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
 // alphabetical order, or in one of the ifdefs (also in order in each section).
 
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index dc055ef..2011c4e6 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -29,7 +29,6 @@
 
 namespace gfx {
 class Range;
-class Size;
 }
 
 namespace url {
@@ -57,24 +56,6 @@
 class CONTENT_EXPORT RenderFrame : public IPC::Listener,
                                    public IPC::Sender {
  public:
-  // These numeric values are used in UMA logs; do not change them.
-  enum PeripheralContentStatus {
-    // Content is peripheral because it doesn't meet any of the below criteria.
-    CONTENT_STATUS_PERIPHERAL = 0,
-    // Content is essential because it's same-origin with the top-level frame.
-    CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN = 1,
-    // Content is essential even though it's cross-origin, because it's large.
-    CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG = 2,
-    // Content is essential because there's large content from the same origin.
-    CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED = 3,
-    // Content is essential because it's tiny in size.
-    CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_TINY = 4,
-    // Content is essential because it has an unknown size.
-    CONTENT_STATUS_ESSENTIAL_UNKNOWN_SIZE = 5,
-    // Must be last.
-    CONTENT_STATUS_NUM_ITEMS
-  };
-
   // Returns the RenderFrame given a WebFrame.
   static RenderFrame* FromWebFrame(blink::WebFrame* web_frame);
 
@@ -150,7 +131,7 @@
       const url::Origin& content_origin,
       const base::Closure& unthrottle_callback) = 0;
 
-  // Returns the peripheral content heuristic decision.
+  // Returns true if this plugin should have power saver enabled.
   //
   // Power Saver is enabled for plugin content that are cross-origin and
   // heuristically determined to be not essential to the web page content.
@@ -165,11 +146,15 @@
   //
   // |content_origin| is the origin of the plugin content.
   //
-  // |unobscured_size| are zoom and device scale independent logical pixels.
-  virtual PeripheralContentStatus GetPeripheralContentStatus(
-      const url::Origin& main_frame_origin,
-      const url::Origin& content_origin,
-      const gfx::Size& unobscured_size) const = 0;
+  // |width| and |height| are zoom and device scale independent logical pixels.
+  //
+  // |cross_origin_main_content| may be NULL. It is set to true if the
+  // plugin content is cross-origin but still the "main attraction" of the page.
+  virtual bool ShouldThrottleContent(const url::Origin& main_frame_origin,
+                                     const url::Origin& content_origin,
+                                     int width,
+                                     int height,
+                                     bool* cross_origin_main_content) const = 0;
 
   // Whitelists a |content_origin| so its content will never be throttled in
   // this RenderFrame. Whitelist is cleared by top level navigation.
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 79fd617..3455dd8 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -49,10 +49,12 @@
 #include "ui/resources/grit/webui_resources.h"
 
 #if defined(USE_AURA)
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "ui/aura/test/window_event_dispatcher_test_api.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
+#include "ui/events/event.h"
 #endif  // USE_AURA
 
 namespace content {
@@ -526,13 +528,14 @@
   widget_host->ForwardGestureEvent(tap);
 }
 
+#if defined(USE_AURA)
 void SimulateTouchPressAt(WebContents* web_contents, const gfx::Point& point) {
-  SyntheticWebTouchEvent touch;
-  touch.PressPoint(point.x(), point.y());
-  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
-      web_contents->GetRenderViewHost()->GetWidget());
-  widget_host->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
+  ui::TouchEvent touch(ui::ET_TOUCH_PRESSED, point, 0, base::TimeDelta());
+  static_cast<RenderWidgetHostViewAura*>(
+      web_contents->GetRenderWidgetHostView())
+      ->OnTouchEvent(&touch);
 }
+#endif
 
 void SimulateKeyPress(WebContents* web_contents,
                       ui::KeyboardCode key_code,
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index f18d4e9..2d3f1a6 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -129,8 +129,10 @@
 // Taps the screen at |point|.
 void SimulateTapAt(WebContents* web_contents, const gfx::Point& point);
 
+#if defined(USE_AURA)
 // Generates a TouchStart at |point|.
 void SimulateTouchPressAt(WebContents* web_contents, const gfx::Point& point);
+#endif
 
 // Taps the screen with modifires at |point|.
 void SimulateTapWithModifiersAt(WebContents* web_contents,
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index 0af3aa46..60451d6 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -84,6 +84,8 @@
 }
 
 BrowserPlugin::~BrowserPlugin() {
+  Detach();
+
   if (compositing_helper_.get())
     compositing_helper_->OnContainerDestroy();
 
@@ -489,6 +491,8 @@
   if (guest_crashed_ || !attached())
     return blink::WebInputEventResult::NotHandled;
 
+  DCHECK(!blink::WebInputEvent::isTouchEventType(event.type));
+
   if (event.type == blink::WebInputEvent::MouseWheel) {
     auto wheel_event = static_cast<const blink::WebMouseWheelEvent&>(event);
     if (wheel_event.resendingPluginId == browser_plugin_instance_id_)
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 3775d3e..ac524a6 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -63,7 +63,7 @@
 #include "third_party/webrtc/base/ssladapter.h"
 
 #if defined(OS_ANDROID)
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #endif
 
 namespace content {
@@ -136,87 +136,6 @@
   }
 }
 
-class P2PPortAllocatorFactory
-    : public rtc::RefCountedObject<webrtc::PortAllocatorFactoryInterface> {
- public:
-  P2PPortAllocatorFactory(
-      scoped_ptr<media::MediaPermission> media_permission,
-      const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
-      rtc::NetworkManager* network_manager,
-      rtc::PacketSocketFactory* socket_factory,
-      const P2PPortAllocator::Config& config,
-      const GURL& origin,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
-      : media_permission_(media_permission.Pass()),
-        socket_dispatcher_(socket_dispatcher),
-        network_manager_(network_manager),
-        socket_factory_(socket_factory),
-        config_(config),
-        origin_(origin),
-        task_runner_(task_runner) {}
-
-  cricket::PortAllocator* CreatePortAllocator(
-      const std::vector<StunConfiguration>& stun_servers,
-      const std::vector<TurnConfiguration>& turn_configurations) override {
-    P2PPortAllocator::Config config = config_;
-    for (size_t i = 0; i < stun_servers.size(); ++i) {
-      config.stun_servers.insert(rtc::SocketAddress(
-          stun_servers[i].server.hostname(),
-          stun_servers[i].server.port()));
-    }
-    for (size_t i = 0; i < turn_configurations.size(); ++i) {
-      P2PPortAllocator::Config::RelayServerConfig relay_config;
-      relay_config.server_address = turn_configurations[i].server.hostname();
-      relay_config.port = turn_configurations[i].server.port();
-      relay_config.username = turn_configurations[i].username;
-      relay_config.password = turn_configurations[i].password;
-      relay_config.transport_type = turn_configurations[i].transport_type;
-      relay_config.secure = turn_configurations[i].secure;
-      config.relays.push_back(relay_config);
-    }
-
-    scoped_ptr<rtc::NetworkManager> network_manager;
-    if (config.enable_multiple_routes) {
-      media::MediaPermission* media_permission = media_permission_.get();
-      FilteringNetworkManager* filtering_network_manager =
-          new FilteringNetworkManager(network_manager_, origin_,
-                                      media_permission_.Pass());
-      if (media_permission) {
-        // Start permission check earlier to reduce any impact to call set up
-        // time. It's safe to use Unretained here since both destructor and
-        // Initialize can only be called on the worker thread.
-        task_runner_->PostTask(
-            FROM_HERE, base::Bind(&FilteringNetworkManager::Initialize,
-                                  base::Unretained(filtering_network_manager)));
-      }
-      network_manager.reset(filtering_network_manager);
-    } else {
-      network_manager.reset(new EmptyNetworkManager(network_manager_));
-    }
-
-    return new P2PPortAllocator(socket_dispatcher_, network_manager.Pass(),
-                                socket_factory_, config, origin_, task_runner_);
-  }
-
- protected:
-  ~P2PPortAllocatorFactory() override {}
-
- private:
-  // Ownership of |media_permission_| will be passed to FilteringNetworkManager
-  // during CreatePortAllocator.
-  scoped_ptr<media::MediaPermission> media_permission_;
-
-  scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
-  rtc::NetworkManager* network_manager_;
-  rtc::PacketSocketFactory* socket_factory_;
-  P2PPortAllocator::Config config_;
-  GURL origin_;
-
-  // This is the worker thread where |media_permission_| and |network_manager_|
-  // live on.
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-};
-
 PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
     P2PSocketDispatcher* p2p_socket_dispatcher)
     : network_manager_(NULL),
@@ -416,7 +335,7 @@
   }
 
 #if defined(OS_ANDROID)
-  if (!media::MediaCodecUtil::SupportsSetParameters())
+  if (!media::MediaCodecBridge::SupportsSetParameters())
     encoder_factory.reset();
 #endif
 
@@ -541,14 +460,30 @@
   const GURL& requesting_origin =
       GURL(web_frame->document().url().spec()).GetOrigin();
 
-  scoped_refptr<P2PPortAllocatorFactory> pa_factory =
-      new P2PPortAllocatorFactory(
-          media_permission.Pass(), p2p_socket_dispatcher_, network_manager_,
-          socket_factory_.get(), port_config, requesting_origin,
-          chrome_worker_thread_.task_runner());
+  scoped_ptr<rtc::NetworkManager> network_manager;
+  if (port_config.enable_multiple_routes) {
+    media::MediaPermission* media_permission_ptr = media_permission.get();
+    FilteringNetworkManager* filtering_network_manager =
+        new FilteringNetworkManager(network_manager_, requesting_origin,
+                                    std::move(media_permission));
+    if (media_permission_ptr) {
+      // Start permission check earlier to reduce any impact to call set up
+      // time. It's safe to use Unretained here since both destructor and
+      // Initialize can only be called on the worker thread.
+      chrome_worker_thread_.task_runner()->PostTask(
+          FROM_HERE, base::Bind(&FilteringNetworkManager::Initialize,
+                                base::Unretained(filtering_network_manager)));
+    }
+    network_manager.reset(filtering_network_manager);
+  } else {
+    network_manager.reset(new EmptyNetworkManager(network_manager_));
+  }
+  rtc::scoped_ptr<P2PPortAllocator> port_allocator(new P2PPortAllocator(
+      p2p_socket_dispatcher_, std::move(network_manager), socket_factory_.get(),
+      port_config, requesting_origin, chrome_worker_thread_.task_runner()));
 
   return GetPcFactory()
-      ->CreatePeerConnection(config, constraints, pa_factory.get(),
+      ->CreatePeerConnection(config, constraints, std::move(port_allocator),
                              std::move(identity_store), observer)
       .get();
 }
diff --git a/content/renderer/mhtml_generator.cc b/content/renderer/mhtml_generator.cc
deleted file mode 100644
index 046c66b..0000000
--- a/content/renderer/mhtml_generator.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2011 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/renderer/mhtml_generator.h"
-
-#include "content/common/view_messages.h"
-#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/web/WebPageSerializer.h"
-
-namespace content {
-
-MHTMLGenerator::MHTMLGenerator(RenderViewImpl* render_view)
-    : RenderViewObserver(render_view) {
-}
-
-MHTMLGenerator::~MHTMLGenerator() {
-}
-
-// RenderViewObserver implementation:
-bool MHTMLGenerator::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(MHTMLGenerator, message)
-      IPC_MESSAGE_HANDLER(ViewMsg_SavePageAsMHTML, OnSavePageAsMHTML)
-      IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void MHTMLGenerator::OnSavePageAsMHTML(
-    int job_id, IPC::PlatformFileForTransit file_for_transit) {
-  file_ = IPC::PlatformFileForTransitToFile(file_for_transit);
-  int64 size = GenerateMHTML();
-  file_.Close();
-  NotifyBrowser(job_id, size);
-}
-
-void MHTMLGenerator::NotifyBrowser(int job_id, int64 data_size) {
-  render_view()->Send(new ViewHostMsg_SavedPageAsMHTML(job_id, data_size));
-}
-
-// TODO(jcivelli): write the chunks in deferred tasks to give a chance to the
-//                 message loop to process other events.
-int64 MHTMLGenerator::GenerateMHTML() {
-  blink::WebCString mhtml =
-      blink::WebPageSerializer::serializeToMHTML(render_view()->GetWebView());
-  const size_t chunk_size = 1024;
-  const char* data = mhtml.data();
-  size_t total_bytes_written = 0;
-  while (total_bytes_written < mhtml.length()) {
-    size_t copy_size =
-        std::min(mhtml.length() - total_bytes_written, chunk_size);
-    int bytes_written = file_.Write(total_bytes_written,
-                                    data + total_bytes_written, copy_size);
-    if (bytes_written == -1)
-      return -1;
-    total_bytes_written += bytes_written;
-  }
-  return total_bytes_written;
-}
-
-}  // namespace content
diff --git a/content/renderer/mhtml_generator.h b/content/renderer/mhtml_generator.h
deleted file mode 100644
index 8a65b46..0000000
--- a/content/renderer/mhtml_generator.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2011 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_RENDERER_MHTML_GENERATOR_H_
-#define CONTENT_RENDERER_MHTML_GENERATOR_H_
-
-#include "base/files/file.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "ipc/ipc_platform_file.h"
-
-namespace content {
-class RenderViewImpl;
-
-class MHTMLGenerator : public RenderViewObserver {
- public:
-  explicit MHTMLGenerator(RenderViewImpl* render_view);
-  ~MHTMLGenerator() override;
-
- private:
-  // RenderViewObserver implementation:
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  void OnSavePageAsMHTML(int job_id,
-                         IPC::PlatformFileForTransit file_for_transit);
-
-  void NotifyBrowser(int job_id, int64 data_size);
-  // Returns the size of the generated MHTML, -1 if it failed.
-  int64 GenerateMHTML();
-
-  base::File file_;
-
-  DISALLOW_COPY_AND_ASSIGN(MHTMLGenerator);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MHTML_GENERATOR_H_
diff --git a/content/renderer/p2p/filtering_network_manager.h b/content/renderer/p2p/filtering_network_manager.h
index 167666a..8eb7bba5d 100644
--- a/content/renderer/p2p/filtering_network_manager.h
+++ b/content/renderer/p2p/filtering_network_manager.h
@@ -45,7 +45,8 @@
 
   CONTENT_EXPORT ~FilteringNetworkManager() override;
 
-  // Check mic/camera permission. This is called by P2PPortAllocatorFactory.
+  // Check mic/camera permission.
+  // This is called by PeerConnectionDependencyFactory.
   CONTENT_EXPORT void Initialize();
 
   // rtc::NetworkManager:
diff --git a/content/renderer/p2p/port_allocator.cc b/content/renderer/p2p/port_allocator.cc
index 681e5cbb..1f2d1e3 100644
--- a/content/renderer/p2p/port_allocator.cc
+++ b/content/renderer/p2p/port_allocator.cc
@@ -11,18 +11,6 @@
 
 namespace content {
 
-P2PPortAllocator::Config::Config() {}
-
-P2PPortAllocator::Config::~Config() {
-}
-
-P2PPortAllocator::Config::RelayServerConfig::RelayServerConfig()
-    : port(0) {
-}
-
-P2PPortAllocator::Config::RelayServerConfig::~RelayServerConfig() {
-}
-
 P2PPortAllocator::P2PPortAllocator(
     const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
     scoped_ptr<rtc::NetworkManager> network_manager,
@@ -37,10 +25,12 @@
       origin_(origin),
       network_manager_task_runner_(task_runner) {
   uint32 flags = 0;
-  if (!config_.enable_multiple_routes)
+  if (!config_.enable_multiple_routes) {
     flags |= cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION;
-  if (!config_.enable_default_local_candidate)
+  }
+  if (!config_.enable_default_local_candidate) {
     flags |= cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE;
+  }
   if (!config_.enable_nonproxied_udp) {
     flags |= cricket::PORTALLOCATOR_DISABLE_UDP |
              cricket::PORTALLOCATOR_DISABLE_STUN |
@@ -65,61 +55,4 @@
                                            network_manager_.release());
 }
 
-cricket::PortAllocatorSession* P2PPortAllocator::CreateSessionInternal(
-    const std::string& content_name,
-    int component,
-    const std::string& ice_username_fragment,
-    const std::string& ice_password) {
-  return new P2PPortAllocatorSession(
-      this, content_name, component, ice_username_fragment, ice_password);
-}
-
-P2PPortAllocatorSession::P2PPortAllocatorSession(
-    P2PPortAllocator* allocator,
-    const std::string& content_name,
-    int component,
-    const std::string& ice_username_fragment,
-    const std::string& ice_password)
-    : cricket::BasicPortAllocatorSession(allocator,
-                                         content_name,
-                                         component,
-                                         ice_username_fragment,
-                                         ice_password),
-      allocator_(allocator) {
-}
-
-P2PPortAllocatorSession::~P2PPortAllocatorSession() {
-}
-
-void P2PPortAllocatorSession::GetPortConfigurations() {
-  const P2PPortAllocator::Config& config = allocator_->config_;
-  cricket::PortConfiguration* port_config = new cricket::PortConfiguration(
-      config.stun_servers, std::string(), std::string());
-
-  for (size_t i = 0; i < config.relays.size(); ++i) {
-    cricket::RelayCredentials credentials(config.relays[i].username,
-                                          config.relays[i].password);
-    cricket::RelayServerConfig relay_server(cricket::RELAY_TURN);
-    cricket::ProtocolType protocol;
-    if (!cricket::StringToProto(config.relays[i].transport_type.c_str(),
-                                &protocol)) {
-      DLOG(WARNING) << "Ignoring TURN server "
-                    << config.relays[i].server_address << ". "
-                    << "Reason= Incorrect "
-                    << config.relays[i].transport_type
-                    << " transport parameter.";
-      continue;
-    }
-
-    relay_server.ports.push_back(cricket::ProtocolAddress(
-        rtc::SocketAddress(config.relays[i].server_address,
-                                 config.relays[i].port),
-        protocol,
-        config.relays[i].secure));
-    relay_server.credentials = credentials;
-    port_config->AddRelay(relay_server);
-  }
-  ConfigReady(port_config);
-}
-
 }  // namespace content
diff --git a/content/renderer/p2p/port_allocator.h b/content/renderer/p2p/port_allocator.h
index 28ebf94..e8436765 100644
--- a/content/renderer/p2p/port_allocator.h
+++ b/content/renderer/p2p/port_allocator.h
@@ -12,31 +12,11 @@
 
 namespace content {
 
-class P2PPortAllocatorSession;
 class P2PSocketDispatcher;
 
 class P2PPortAllocator : public cricket::BasicPortAllocator {
  public:
   struct Config {
-    Config();
-    ~Config();
-
-    struct RelayServerConfig {
-      RelayServerConfig();
-      ~RelayServerConfig();
-
-      std::string username;
-      std::string password;
-      std::string server_address;
-      int port;
-      std::string transport_type;
-      bool secure;
-    };
-
-    std::set<rtc::SocketAddress> stun_servers;
-
-    std::vector<RelayServerConfig> relays;
-
     // Enable non-proxied UDP-based transport when set to true. When set to
     // false, it effectively disables all UDP traffic until UDP-supporting proxy
     // RETURN is available in the future.
@@ -64,14 +44,7 @@
       const scoped_refptr<base::SingleThreadTaskRunner> task_runner);
   ~P2PPortAllocator() override;
 
-  cricket::PortAllocatorSession* CreateSessionInternal(
-      const std::string& content_name,
-      int component,
-      const std::string& ice_username_fragment,
-      const std::string& ice_password) override;
-
  private:
-  friend class P2PPortAllocatorSession;
   scoped_ptr<rtc::NetworkManager> network_manager_;
   scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
   Config config_;
@@ -85,26 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(P2PPortAllocator);
 };
 
-class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession {
- public:
-  P2PPortAllocatorSession(
-      P2PPortAllocator* allocator,
-      const std::string& content_name,
-      int component,
-      const std::string& ice_username_fragment,
-      const std::string& ice_password);
-  ~P2PPortAllocatorSession() override;
-
- protected:
-  // Overrides for cricket::BasicPortAllocatorSession.
-  void GetPortConfigurations() override;
-
- private:
-  P2PPortAllocator* allocator_;
-
-  DISALLOW_COPY_AND_ASSIGN(P2PPortAllocatorSession);
-};
-
 }  // namespace content
 
 #endif  // CONTENT_RENDERER_P2P_PORT_ALLOCATOR_H_
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.cc b/content/renderer/pepper/plugin_instance_throttler_impl.cc
index 5a153b7..22bfec87 100644
--- a/content/renderer/pepper/plugin_instance_throttler_impl.cc
+++ b/content/renderer/pepper/plugin_instance_throttler_impl.cc
@@ -139,17 +139,18 @@
 
   // |frame| may be nullptr in tests.
   if (frame) {
+    bool cross_origin_main_content = false;
     float zoom_factor = GetWebPlugin()->container()->pageZoomFactor();
-    auto status = frame->GetPeripheralContentStatus(
-        frame->GetWebFrame()->top()->securityOrigin(), content_origin,
-        gfx::Size(roundf(unobscured_size.width() / zoom_factor),
-                  roundf(unobscured_size.height() / zoom_factor)));
-    if (status != RenderFrame::CONTENT_STATUS_PERIPHERAL) {
+    if (!frame->ShouldThrottleContent(
+            frame->GetWebFrame()->top()->securityOrigin(), content_origin,
+            roundf(unobscured_size.width() / zoom_factor),
+            roundf(unobscured_size.height() / zoom_factor),
+            &cross_origin_main_content)) {
       DCHECK_NE(THROTTLER_STATE_MARKED_ESSENTIAL, state_);
       state_ = THROTTLER_STATE_MARKED_ESSENTIAL;
       FOR_EACH_OBSERVER(Observer, observer_list_, OnPeripheralStateChange());
 
-      if (status == RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG)
+      if (cross_origin_main_content)
         frame->WhitelistContentOrigin(content_origin);
 
       return;
diff --git a/content/renderer/pepper/plugin_power_saver_helper.cc b/content/renderer/pepper/plugin_power_saver_helper.cc
index cd1f27cc..2544162 100644
--- a/content/renderer/pepper/plugin_power_saver_helper.cc
+++ b/content/renderer/pepper/plugin_power_saver_helper.cc
@@ -15,7 +15,6 @@
 #include "content/renderer/peripheral_content_heuristic.h"
 #include "ppapi/shared_impl/ppapi_constants.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "ui/gfx/geometry/size.h"
 
 namespace content {
 
@@ -85,28 +84,33 @@
       PeripheralPlugin(content_origin, unthrottle_callback));
 }
 
-RenderFrame::PeripheralContentStatus
-PluginPowerSaverHelper::GetPeripheralContentStatus(
+bool PluginPowerSaverHelper::ShouldThrottleContent(
     const url::Origin& main_frame_origin,
     const url::Origin& content_origin,
-    const gfx::Size& unobscured_size) const {
+    int width,
+    int height,
+    bool* cross_origin_main_content) const {
+  if (cross_origin_main_content)
+    *cross_origin_main_content = false;
+
   if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kOverridePluginPowerSaverForTesting) == "always") {
-    return RenderFrame::CONTENT_STATUS_PERIPHERAL;
+    return true;
   }
 
-  auto status = PeripheralContentHeuristic::GetPeripheralStatus(
-      origin_whitelist_, main_frame_origin, content_origin, unobscured_size);
-  if (status == RenderFrame::CONTENT_STATUS_ESSENTIAL_UNKNOWN_SIZE) {
-    // Early exit here to avoid recording a UMA. Every plugin will call this
-    // method once before the size is known (to faciliate early-exit for
-    // same-origin and whitelisted-origin content).
-    return status;
-  }
+  auto decision = PeripheralContentHeuristic::GetPeripheralStatus(
+      origin_whitelist_, main_frame_origin, content_origin, width, height);
 
-  UMA_HISTOGRAM_ENUMERATION(kPeripheralHeuristicHistogram, status,
-                            RenderFrame::CONTENT_STATUS_NUM_ITEMS);
-  return status;
+  UMA_HISTOGRAM_ENUMERATION(
+      kPeripheralHeuristicHistogram, decision,
+      PeripheralContentHeuristic::HEURISTIC_DECISION_NUM_ITEMS);
+
+  if (decision == PeripheralContentHeuristic::
+                      HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG &&
+      cross_origin_main_content)
+    *cross_origin_main_content = true;
+
+  return decision == PeripheralContentHeuristic::HEURISTIC_DECISION_PERIPHERAL;
 }
 
 void PluginPowerSaverHelper::WhitelistContentOrigin(
diff --git a/content/renderer/pepper/plugin_power_saver_helper.h b/content/renderer/pepper/plugin_power_saver_helper.h
index 1b97006..b962993 100644
--- a/content/renderer/pepper/plugin_power_saver_helper.h
+++ b/content/renderer/pepper/plugin_power_saver_helper.h
@@ -10,7 +10,6 @@
 
 #include "base/callback.h"
 #include "content/common/content_export.h"
-#include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "url/origin.h"
 
@@ -19,10 +18,6 @@
 struct WebRect;
 }
 
-namespace gfx {
-class Size;
-}
-
 namespace content {
 
 class CONTENT_EXPORT PluginPowerSaverHelper : public RenderFrameObserver {
@@ -45,10 +40,11 @@
   // See RenderFrame for documentation.
   void RegisterPeripheralPlugin(const url::Origin& content_origin,
                                 const base::Closure& unthrottle_callback);
-  RenderFrame::PeripheralContentStatus GetPeripheralContentStatus(
-      const url::Origin& main_frame_origin,
-      const url::Origin& content_origin,
-      const gfx::Size& unobscured_size) const;
+  bool ShouldThrottleContent(const url::Origin& main_frame_origin,
+                             const url::Origin& content_origin,
+                             int width,
+                             int height,
+                             bool* cross_origin_main_content) const;
   void WhitelistContentOrigin(const url::Origin& content_origin);
 
   // RenderFrameObserver implementation.
diff --git a/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc b/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
index 9e42241..ad6a0c1 100644
--- a/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
+++ b/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
@@ -16,7 +16,6 @@
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebPluginParams.h"
-#include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -34,27 +33,101 @@
     return static_cast<RenderFrameImpl*>(view_->GetMainRenderFrame());
   }
 
+  blink::WebPluginParams MakeParams(const std::string& url,
+                                    const std::string& poster,
+                                    const std::string& width,
+                                    const std::string& height) {
+    const size_t size = 3;
+    blink::WebVector<blink::WebString> names(size);
+    blink::WebVector<blink::WebString> values(size);
+
+    blink::WebPluginParams params;
+    params.url = GURL(url);
+
+    params.attributeNames.swap(names);
+    params.attributeValues.swap(values);
+
+    params.attributeNames[0] = "poster";
+    params.attributeNames[1] = "height";
+    params.attributeNames[2] = "width";
+    params.attributeValues[0] = blink::WebString::fromUTF8(poster);
+    params.attributeValues[1] = blink::WebString::fromUTF8(height);
+    params.attributeValues[2] = blink::WebString::fromUTF8(width);
+
+    return params;
+  }
+
  protected:
   IPC::TestSink* sink_;
 
   DISALLOW_COPY_AND_ASSIGN(PluginPowerSaverHelperTest);
 };
 
+TEST_F(PluginPowerSaverHelperTest, AllowSameOrigin) {
+  EXPECT_FALSE(frame()->ShouldThrottleContent(
+      url::Origin(GURL("http://same.com")),
+      url::Origin(GURL("http://same.com")), 100, 100, nullptr));
+  EXPECT_FALSE(frame()->ShouldThrottleContent(
+      url::Origin(GURL("http://same.com")),
+      url::Origin(GURL("http://same.com")), 1000, 1000, nullptr));
+}
+
+TEST_F(PluginPowerSaverHelperTest, DisallowCrossOriginUnlessLarge) {
+  bool cross_origin_main_content = false;
+  EXPECT_TRUE(
+      frame()->ShouldThrottleContent(url::Origin(GURL("http://same.com")),
+                                     url::Origin(GURL("http://other.com")), 100,
+                                     100, &cross_origin_main_content));
+  EXPECT_FALSE(cross_origin_main_content);
+
+  EXPECT_FALSE(
+      frame()->ShouldThrottleContent(url::Origin(GURL("http://same.com")),
+                                     url::Origin(GURL("http://other.com")),
+                                     1000, 1000, &cross_origin_main_content));
+  EXPECT_TRUE(cross_origin_main_content);
+}
+
+TEST_F(PluginPowerSaverHelperTest, AlwaysAllowTinyContent) {
+  bool cross_origin_main_content = false;
+  EXPECT_FALSE(frame()->ShouldThrottleContent(
+      url::Origin(GURL("http://same.com")),
+      url::Origin(GURL("http://same.com")), 1, 1, nullptr));
+  EXPECT_FALSE(cross_origin_main_content);
+
+  EXPECT_FALSE(frame()->ShouldThrottleContent(
+      url::Origin(GURL("http://same.com")),
+      url::Origin(GURL("http://other.com")), 1, 1, &cross_origin_main_content));
+  EXPECT_FALSE(cross_origin_main_content);
+
+  EXPECT_FALSE(frame()->ShouldThrottleContent(
+      url::Origin(GURL("http://same.com")),
+      url::Origin(GURL("http://other.com")), 5, 5, &cross_origin_main_content));
+  EXPECT_FALSE(cross_origin_main_content);
+
+  EXPECT_TRUE(
+      frame()->ShouldThrottleContent(url::Origin(GURL("http://same.com")),
+                                     url::Origin(GURL("http://other.com")), 10,
+                                     10, &cross_origin_main_content));
+  EXPECT_FALSE(cross_origin_main_content);
+}
+
 TEST_F(PluginPowerSaverHelperTest, TemporaryOriginWhitelist) {
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_PERIPHERAL,
-            frame()->GetPeripheralContentStatus(
-                url::Origin(GURL("http://same.com")),
-                url::Origin(GURL("http://other.com")), gfx::Size(100, 100)));
+  bool cross_origin_main_content = false;
+  EXPECT_TRUE(
+      frame()->ShouldThrottleContent(url::Origin(GURL("http://same.com")),
+                                     url::Origin(GURL("http://other.com")), 100,
+                                     100, &cross_origin_main_content));
+  EXPECT_FALSE(cross_origin_main_content);
 
   // Clear out other messages so we find just the plugin power saver IPCs.
   sink_->ClearMessages();
 
   frame()->WhitelistContentOrigin(url::Origin(GURL("http://other.com")));
-
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED,
-            frame()->GetPeripheralContentStatus(
-                url::Origin(GURL("http://same.com")),
-                url::Origin(GURL("http://other.com")), gfx::Size(100, 100)));
+  EXPECT_FALSE(
+      frame()->ShouldThrottleContent(url::Origin(GURL("http://same.com")),
+                                     url::Origin(GURL("http://other.com")), 100,
+                                     100, &cross_origin_main_content));
+  EXPECT_FALSE(cross_origin_main_content);
 
   // Test that we've sent an IPC to the browser.
   ASSERT_EQ(1u, sink_->message_count());
@@ -83,17 +156,15 @@
 TEST_F(PluginPowerSaverHelperTest, ClearWhitelistOnNavigate) {
   frame()->WhitelistContentOrigin(url::Origin(GURL("http://other.com")));
 
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED,
-            frame()->GetPeripheralContentStatus(
-                url::Origin(GURL("http://same.com")),
-                url::Origin(GURL("http://other.com")), gfx::Size(100, 100)));
+  EXPECT_FALSE(frame()->ShouldThrottleContent(
+      url::Origin(GURL("http://same.com")),
+      url::Origin(GURL("http://other.com")), 100, 100, nullptr));
 
   LoadHTML("<html></html>");
 
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_PERIPHERAL,
-            frame()->GetPeripheralContentStatus(
-                url::Origin(GURL("http://same.com")),
-                url::Origin(GURL("http://other.com")), gfx::Size(100, 100)));
+  EXPECT_TRUE(frame()->ShouldThrottleContent(
+      url::Origin(GURL("http://same.com")),
+      url::Origin(GURL("http://other.com")), 100, 100, nullptr));
 }
 
 }  // namespace content
diff --git a/content/renderer/peripheral_content_heuristic.cc b/content/renderer/peripheral_content_heuristic.cc
index 3b36af81..b2c59c9 100644
--- a/content/renderer/peripheral_content_heuristic.cc
+++ b/content/renderer/peripheral_content_heuristic.cc
@@ -6,8 +6,6 @@
 
 #include <cmath>
 
-#include "ui/gfx/geometry/size.h"
-
 namespace content {
 
 namespace {
@@ -32,37 +30,33 @@
 }  // namespace
 
 // static
-RenderFrame::PeripheralContentStatus
+PeripheralContentHeuristic::Decision
 PeripheralContentHeuristic::GetPeripheralStatus(
     const std::set<url::Origin>& origin_whitelist,
     const url::Origin& main_frame_origin,
     const url::Origin& content_origin,
-    const gfx::Size& unobscured_size) {
+    int width,
+    int height) {
   if (main_frame_origin.IsSameOriginWith(content_origin))
-    return RenderFrame::CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN;
+    return HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN;
+
+  if (width <= 0 || height <= 0)
+    return HEURISTIC_DECISION_ESSENTIAL_UNKNOWN_SIZE;
 
   if (origin_whitelist.count(content_origin))
-    return RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED;
+    return HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED;
 
-  if (unobscured_size.IsEmpty())
-    return RenderFrame::CONTENT_STATUS_ESSENTIAL_UNKNOWN_SIZE;
+  if (width <= kTinyContentSize && height <= kTinyContentSize)
+    return HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY;
 
-  if (unobscured_size.width() <= kTinyContentSize &&
-      unobscured_size.height() <= kTinyContentSize) {
-    return RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_TINY;
-  }
+  if (IsLargeContent(width, height))
+    return HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG;
 
-  if (IsLargeContent(unobscured_size))
-    return RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG;
-
-  return RenderFrame::CONTENT_STATUS_PERIPHERAL;
+  return HEURISTIC_DECISION_PERIPHERAL;
 }
 
 // static
-bool PeripheralContentHeuristic::IsLargeContent(
-    const gfx::Size& unobscured_size) {
-  int width = unobscured_size.width();
-  int height = unobscured_size.height();
+bool PeripheralContentHeuristic::IsLargeContent(int width, int height) {
   if (width >= kLargeContentMinWidth && height >= kLargeContentMinHeight)
     return true;
 
diff --git a/content/renderer/peripheral_content_heuristic.h b/content/renderer/peripheral_content_heuristic.h
index 251edaa9..5b28693 100644
--- a/content/renderer/peripheral_content_heuristic.h
+++ b/content/renderer/peripheral_content_heuristic.h
@@ -8,17 +8,24 @@
 #include <set>
 
 #include "content/common/content_export.h"
-#include "content/public/renderer/render_frame.h"
 #include "url/origin.h"
 
-namespace gfx {
-class Size;
-}
-
 namespace content {
 
 class CONTENT_EXPORT PeripheralContentHeuristic {
  public:
+  // Initial decision of the peripheral content decision.
+  // These numeric values are used in UMA logs; do not change them.
+  enum Decision {
+    HEURISTIC_DECISION_PERIPHERAL = 0,
+    HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN = 1,
+    HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG = 2,
+    HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED = 3,
+    HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY = 4,
+    HEURISTIC_DECISION_ESSENTIAL_UNKNOWN_SIZE = 5,
+    HEURISTIC_DECISION_NUM_ITEMS
+  };
+
   // Returns true if this content should have power saver enabled.
   //
   // Power Saver is enabled for content that are cross-origin and
@@ -36,16 +43,17 @@
   //
   // |content_origin| is the origin of the content e.g. plugin or video source.
   //
-  // |unobscured_size| is in zoom and device scale independent logical pixels.
-  static RenderFrame::PeripheralContentStatus GetPeripheralStatus(
+  // |width| and |height| are zoom and device scale independent logical pixels.
+  static Decision GetPeripheralStatus(
       const std::set<url::Origin>& origin_whitelist,
       const url::Origin& main_frame_origin,
       const url::Origin& content_origin,
-      const gfx::Size& unobscured_size);
+      int width,
+      int height);
 
   // Returns true if content is considered "large", and thus essential.
-  // |unobscured_size| is in zoom and device scale independent logical pixels.
-  static bool IsLargeContent(const gfx::Size& unobscured_size);
+  // |width| and |height| are zoom and device scale independent logical pixels.
+  static bool IsLargeContent(int width, int height);
 };
 
 }  // namespace content
diff --git a/content/renderer/peripheral_content_heuristic_unittest.cc b/content/renderer/peripheral_content_heuristic_unittest.cc
index 99f8e9eb..ddd78d5 100644
--- a/content/renderer/peripheral_content_heuristic_unittest.cc
+++ b/content/renderer/peripheral_content_heuristic_unittest.cc
@@ -5,7 +5,6 @@
 #include "content/renderer/peripheral_content_heuristic.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -19,78 +18,66 @@
 }  // namespaces
 
 TEST(PeripheralContentHeuristic, AllowSameOrigin) {
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN,
-            PeripheralContentHeuristic::GetPeripheralStatus(
-                std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kSameOrigin)), gfx::Size(100, 100)));
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN,
-            PeripheralContentHeuristic::GetPeripheralStatus(
-                std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kSameOrigin)), gfx::Size(1000, 1000)));
+  EXPECT_EQ(
+      PeripheralContentHeuristic::HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN,
+      PeripheralContentHeuristic::GetPeripheralStatus(
+          std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
+          url::Origin(GURL(kSameOrigin)), 100, 100));
+  EXPECT_EQ(
+      PeripheralContentHeuristic::HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN,
+      PeripheralContentHeuristic::GetPeripheralStatus(
+          std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
+          url::Origin(GURL(kSameOrigin)), 1000, 1000));
 }
 
 TEST(PeripheralContentHeuristic, DisallowCrossOriginUnlessLarge) {
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_PERIPHERAL,
+  EXPECT_EQ(PeripheralContentHeuristic::HEURISTIC_DECISION_PERIPHERAL,
             PeripheralContentHeuristic::GetPeripheralStatus(
                 std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size(100, 100)));
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG,
-            PeripheralContentHeuristic::GetPeripheralStatus(
-                std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size(1000, 1000)));
+                url::Origin(GURL(kOtherOrigin)), 100, 100));
+  EXPECT_EQ(
+      PeripheralContentHeuristic::HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG,
+      PeripheralContentHeuristic::GetPeripheralStatus(
+          std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
+          url::Origin(GURL(kOtherOrigin)), 1000, 1000));
 }
 
 TEST(PeripheralContentHeuristic, AlwaysAllowTinyContent) {
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN,
+  EXPECT_EQ(
+      PeripheralContentHeuristic::HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN,
+      PeripheralContentHeuristic::GetPeripheralStatus(
+          std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
+          url::Origin(GURL(kSameOrigin)), 1, 1));
+  EXPECT_EQ(PeripheralContentHeuristic::
+                HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY,
             PeripheralContentHeuristic::GetPeripheralStatus(
                 std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kSameOrigin)), gfx::Size(1, 1)));
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_TINY,
+                url::Origin(GURL(kOtherOrigin)), 1, 1));
+  EXPECT_EQ(PeripheralContentHeuristic::
+                HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_TINY,
             PeripheralContentHeuristic::GetPeripheralStatus(
                 std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size(1, 1)));
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_TINY,
+                url::Origin(GURL(kOtherOrigin)), 5, 5));
+  EXPECT_EQ(PeripheralContentHeuristic::HEURISTIC_DECISION_PERIPHERAL,
             PeripheralContentHeuristic::GetPeripheralStatus(
                 std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size(5, 5)));
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_PERIPHERAL,
-            PeripheralContentHeuristic::GetPeripheralStatus(
-                std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size(10, 10)));
+                url::Origin(GURL(kOtherOrigin)), 10, 10));
 }
 
 TEST(PeripheralContentHeuristic, TemporaryOriginWhitelist) {
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_PERIPHERAL,
+  EXPECT_EQ(PeripheralContentHeuristic::HEURISTIC_DECISION_PERIPHERAL,
             PeripheralContentHeuristic::GetPeripheralStatus(
                 std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size(100, 100)));
+                url::Origin(GURL(kOtherOrigin)), 100, 100));
 
   std::set<url::Origin> whitelist;
   whitelist.insert(url::Origin(GURL(kOtherOrigin)));
 
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED,
+  EXPECT_EQ(PeripheralContentHeuristic::
+                HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED,
             PeripheralContentHeuristic::GetPeripheralStatus(
                 whitelist, url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size(100, 100)));
-}
-
-TEST(PeripheralContentHeuristic, UndefinedSize) {
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_SAME_ORIGIN,
-            PeripheralContentHeuristic::GetPeripheralStatus(
-                std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kSameOrigin)), gfx::Size()));
-
-  std::set<url::Origin> whitelist;
-  whitelist.insert(url::Origin(GURL(kOtherOrigin)));
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_WHITELISTED,
-            PeripheralContentHeuristic::GetPeripheralStatus(
-                whitelist, url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size()));
-
-  EXPECT_EQ(RenderFrame::CONTENT_STATUS_ESSENTIAL_UNKNOWN_SIZE,
-            PeripheralContentHeuristic::GetPeripheralStatus(
-                std::set<url::Origin>(), url::Origin(GURL(kSameOrigin)),
-                url::Origin(GURL(kOtherOrigin)), gfx::Size()));
+                url::Origin(GURL(kOtherOrigin)), 100, 100));
 }
 
 }  // namespace content
diff --git a/content/renderer/raster_worker_pool.cc b/content/renderer/raster_worker_pool.cc
index 89ed6d6..ddeb57d 100644
--- a/content/renderer/raster_worker_pool.cc
+++ b/content/renderer/raster_worker_pool.cc
@@ -4,6 +4,8 @@
 
 #include "content/renderer/raster_worker_pool.h"
 
+#include <utility>
+
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/trace_event/trace_event.h"
@@ -47,7 +49,8 @@
       if (!graph_.nodes.empty())
         dependencies = 1;
 
-      cc::TaskGraph::Node node(graph_task.get(), 0, dependencies);
+      cc::TaskGraph::Node node(graph_task.get(), 0u /* category */,
+                               0u /* priority */, dependencies);
       if (dependencies) {
         graph_.edges.push_back(
             cc::TaskGraph::Edge(graph_.nodes.back().task, node.task));
@@ -148,7 +151,9 @@
   tasks_.push_back(make_scoped_refptr(new ClosureTask(task)));
   graph_.Reset();
   for (const auto& graph_task : tasks_)
-    graph_.nodes.push_back(cc::TaskGraph::Node(graph_task.get(), 0, 0));
+    graph_.nodes.push_back(
+        cc::TaskGraph::Node(graph_task.get(), 0u /* category */,
+                            0u /* priority */, 0u /* dependencies */));
 
   ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
   completed_tasks_.clear();
@@ -164,7 +169,7 @@
   base::AutoLock lock(lock_);
 
   while (true) {
-    if (!work_queue_.HasReadyToRunTasks()) {
+    if (!RunTaskWithLockAcquired()) {
       // Exit when shutdown is set and no more tasks are pending.
       if (shutdown_)
         break;
@@ -173,8 +178,6 @@
       has_ready_to_run_tasks_cv_.Wait();
       continue;
     }
-
-    RunTaskWithLockAcquired();
   }
 }
 
@@ -258,12 +261,28 @@
   work_queue_.CollectCompletedTasks(token, completed_tasks);
 }
 
-void RasterWorkerPool::RunTaskWithLockAcquired() {
+bool RasterWorkerPool::RunTaskWithLockAcquired() {
   TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
 
   lock_.AssertAcquired();
 
-  auto prioritized_task = work_queue_.GetNextTaskToRun();
+  // Find the first category with any tasks to run. This task graph runner
+  // treats categories as an additional priority.
+  // TODO(ericrk): Add more category/thread logic.
+  const auto& ready_to_run_namespaces = work_queue_.ready_to_run_namespaces();
+  auto found = std::find_if(
+      ready_to_run_namespaces.cbegin(), ready_to_run_namespaces.cend(),
+      [](const std::pair<uint16_t,
+                         cc::TaskGraphWorkQueue::TaskNamespace::Vector>& pair) {
+        return !pair.second.empty();
+      });
+
+  if (found == ready_to_run_namespaces.cend()) {
+    return false;
+  }
+
+  const uint16_t category = found->first;
+  auto prioritized_task = work_queue_.GetNextTaskToRun(category);
   cc::Task* task = prioritized_task.task;
 
   // There may be more work available, so wake up another worker thread.
@@ -288,6 +307,8 @@
   if (work_queue_.HasFinishedRunningTasksInNamespace(
           prioritized_task.task_namespace))
     has_namespaces_with_finished_running_tasks_cv_.Broadcast();
+
+  return true;
 }
 
 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
diff --git a/content/renderer/raster_worker_pool.h b/content/renderer/raster_worker_pool.h
index 547eeb8..e7473a9 100644
--- a/content/renderer/raster_worker_pool.h
+++ b/content/renderer/raster_worker_pool.h
@@ -74,9 +74,9 @@
   class RasterWorkerPoolSequencedTaskRunner;
   friend class RasterWorkerPoolSequencedTaskRunner;
 
-  // Run next task. Caller must acquire |lock_| prior to calling this function
-  // and make sure at least one task is ready to run.
-  void RunTaskWithLockAcquired();
+  // Run next task. Caller must acquire |lock_| prior to calling this function.
+  // Returns true if there was a task available to run.
+  bool RunTaskWithLockAcquired();
 
   // Simple Task for the TaskGraphRunner that wraps a closure.
   // This class is used to schedule TaskRunner tasks on the
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d324d66..4858362 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -6,13 +6,16 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/debug/alias.h"
 #include "base/debug/asan_invalid_access.h"
 #include "base/debug/dump_without_crashing.h"
+#include "base/files/file.h"
 #include "base/i18n/char_iterator.h"
+#include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram.h"
 #include "base/process/process.h"
@@ -128,6 +131,7 @@
 #include "media/base/audio_renderer_mixer_input.h"
 #include "media/base/media_log.h"
 #include "media/base/media_switches.h"
+#include "media/blink/url_index.h"
 #include "media/blink/webencryptedmediaclient_impl.h"
 #include "media/blink/webmediaplayer_impl.h"
 #include "media/renderers/gpu_video_accelerator_factories.h"
@@ -136,6 +140,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/http/http_util.h"
+#include "third_party/WebKit/public/platform/WebData.h"
 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
@@ -1265,6 +1270,7 @@
                         OnGetSavableResourceLinks)
     IPC_MESSAGE_HANDLER(FrameMsg_GetSerializedHtmlWithLocalLinks,
                         OnGetSerializedHtmlWithLocalLinks)
+    IPC_MESSAGE_HANDLER(FrameMsg_SerializeAsMHTML, OnSerializeAsMHTML)
 #if defined(OS_ANDROID)
     IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
 #elif defined(OS_MACOSX)
@@ -2128,13 +2134,15 @@
       content_origin, unthrottle_callback);
 }
 
-RenderFrame::PeripheralContentStatus
-RenderFrameImpl::GetPeripheralContentStatus(
+bool RenderFrameImpl::ShouldThrottleContent(
     const url::Origin& main_frame_origin,
     const url::Origin& content_origin,
-    const gfx::Size& unobscured_size) const {
-  return plugin_power_saver_helper_->GetPeripheralContentStatus(
-      main_frame_origin, content_origin, unobscured_size);
+    int width,
+    int height,
+    bool* cross_origin_main_content) const {
+  return plugin_power_saver_helper_->ShouldThrottleContent(
+      main_frame_origin, content_origin, width, height,
+      cross_origin_main_content);
 }
 
 void RenderFrameImpl::WhitelistContentOrigin(
@@ -2315,9 +2323,13 @@
 #endif  // defined(ENABLE_MOJO_MEDIA) &&
         // !defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID)
 
+  if (!url_index_.get() || url_index_->frame() != frame) {
+    url_index_.reset(new media::UrlIndex(frame));
+  }
+
   return new media::WebMediaPlayerImpl(
       frame, client, encrypted_client, GetWebMediaPlayerDelegate()->AsWeakPtr(),
-      media_renderer_factory.Pass(), GetCdmFactory(), params);
+      media_renderer_factory.Pass(), GetCdmFactory(), url_index_, params);
 #endif  // defined(OS_ANDROID) && !defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID)
 }
 
@@ -4740,6 +4752,63 @@
                                weburl_to_local_path);
 }
 
+void RenderFrameImpl::OnSerializeAsMHTML(
+    int job_id,
+    IPC::PlatformFileForTransit file_for_transit,
+    const std::string& std_mhtml_boundary,
+    const std::map<int, std::string>& frame_routing_id_to_content_id,
+    bool is_last_frame) {
+  // Unpack IPC payload.
+  base::File file = IPC::PlatformFileForTransitToFile(file_for_transit);
+  const WebString mhtml_boundary = WebString::fromUTF8(std_mhtml_boundary);
+  DCHECK(!mhtml_boundary.isEmpty());
+  std::vector<std::pair<WebFrame*, WebString>> web_frame_to_content_id;
+  for (const auto& it : frame_routing_id_to_content_id) {
+    const std::string& content_id = it.second;
+    WebFrame* web_frame = GetWebFrameFromRoutingIdForFrameOrProxy(it.first);
+    if (!web_frame)
+      continue;
+
+    web_frame_to_content_id.push_back(
+        std::make_pair(web_frame, WebString::fromUTF8(content_id)));
+  }
+
+  WebData data;
+  bool success = true;
+
+  // Generate MHTML header if needed.
+  if (IsMainFrame()) {
+    data =
+        WebPageSerializer::generateMHTMLHeader(mhtml_boundary, GetWebFrame());
+    if (file.WriteAtCurrentPos(data.data(), data.size()) < 0) {
+      success = false;
+    }
+  }
+
+  // Generate MHTML parts.
+  if (success) {
+    data = WebPageSerializer::generateMHTMLParts(
+        mhtml_boundary, GetWebFrame(), false, web_frame_to_content_id);
+    // TODO(jcivelli): write the chunks in deferred tasks to give a chance to
+    //                 the message loop to process other events.
+    if (file.WriteAtCurrentPos(data.data(), data.size()) < 0) {
+      success = false;
+    }
+  }
+
+  // Generate MHTML footer if needed.
+  if (success && is_last_frame) {
+    data = WebPageSerializer::generateMHTMLFooter(mhtml_boundary);
+    if (file.WriteAtCurrentPos(data.data(), data.size()) < 0) {
+      success = false;
+    }
+  }
+
+  // Cleanup and notify the browser process about completion.
+  file.Close();  // Need to flush file contents before sending IPC response.
+  Send(new FrameHostMsg_SerializeAsMHTMLResponse(routing_id_, job_id, success));
+}
+
 void RenderFrameImpl::OpenURL(const GURL& url,
                               const Referrer& referrer,
                               WebNavigationPolicy policy,
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 8e42c48b..ab782145 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -12,6 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/id_map.h"
+#include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -25,6 +26,7 @@
 #include "content/renderer/render_frame_proxy.h"
 #include "content/renderer/renderer_webcookiejar_impl.h"
 #include "ipc/ipc_message.h"
+#include "ipc/ipc_platform_file.h"
 #include "media/blink/webmediaplayer_delegate.h"
 #include "media/blink/webmediaplayer_params.h"
 #include "mojo/application/public/interfaces/service_provider.mojom.h"
@@ -84,7 +86,9 @@
 namespace media {
 class CdmFactory;
 class MediaPermission;
+class MediaServiceProvider;
 class RendererWebMediaPlayerDelegate;
+class UrlIndex;
 class WebEncryptedMediaClientImpl;
 }
 
@@ -375,10 +379,11 @@
   void RegisterPeripheralPlugin(
       const url::Origin& content_origin,
       const base::Closure& unthrottle_callback) override;
-  RenderFrame::PeripheralContentStatus GetPeripheralContentStatus(
-      const url::Origin& main_frame_origin,
-      const url::Origin& content_origin,
-      const gfx::Size& unobscured_size) const override;
+  bool ShouldThrottleContent(const url::Origin& main_frame_origin,
+                             const url::Origin& content_origin,
+                             int width,
+                             int height,
+                             bool* cross_origin_main_content) const override;
   void WhitelistContentOrigin(const url::Origin& content_origin) override;
 #endif
   bool IsFTPDirectoryListing() override;
@@ -773,6 +778,12 @@
   void OnGetSavableResourceLinks();
   void OnGetSerializedHtmlWithLocalLinks(
       const std::map<GURL, base::FilePath>& url_to_local_path);
+  void OnSerializeAsMHTML(
+      int job_id,
+      IPC::PlatformFileForTransit file_for_transit,
+      const std::string& mhtml_boundary_marker,
+      const std::map<int, std::string>& frame_routing_id_to_content_id,
+      bool is_last_frame);
 
   // Requests that the browser process navigates to |url|. If
   // |is_history_navigation_in_new_child| is true, the browser process should
@@ -1053,6 +1064,9 @@
   // The CDM factory attached to this frame, lazily initialized.
   scoped_ptr<media::CdmFactory> cdm_factory_;
 
+  // Media resource cache, lazily initialized.
+  linked_ptr<media::UrlIndex> url_index_;
+
 #if defined(VIDEO_HOLE)
   // Whether or not this RenderFrameImpl contains a media player. Used to
   // register as an observer for video-hole-specific events.
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 3c92c5de4..87773de 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -388,17 +388,15 @@
 
 class RenderViewImplScaleFactorTest : public RenderViewImplBlinkSettingsTest {
  public:
-  void DoSetUp() override {
-    RenderViewImplBlinkSettingsTest::DoSetUp();
-
+  void SetDeviceScaleFactor(float dsf) {
     ViewMsg_Resize_Params params;
-    params.screen_info.deviceScaleFactor = 2.f;
+    params.screen_info.deviceScaleFactor = dsf;
     params.new_size = gfx::Size(100, 100);
     params.physical_backing_size = gfx::Size(200, 200);
     params.visible_viewport_size = params.new_size;
     params.needs_resize_ack = false;
     view()->OnResize(params);
-    ASSERT_EQ(2.f, view()->device_scale_factor_);
+    ASSERT_EQ(dsf, view()->device_scale_factor_);
   }
 };
 
@@ -1887,6 +1885,7 @@
   view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0);
   view()->GetCompositionCharacterBounds(&bounds);
   ASSERT_EQ(ascii_composition.size(), bounds.size());
+
   for (size_t i = 0; i < bounds.size(); ++i)
     EXPECT_LT(0, bounds[i].width());
   view()->OnImeConfirmComposition(
@@ -2550,6 +2549,7 @@
 
 TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithoutZoomForDSF) {
   DoSetUp();
+  SetDeviceScaleFactor(2.f);
   blink::WebRect rect(20, 10, 200, 100);
   view()->convertViewportToWindow(&rect);
   EXPECT_EQ(20, rect.x);
@@ -2562,15 +2562,113 @@
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableUseZoomForDSF);
   DoSetUp();
+  SetDeviceScaleFactor(1.f);
+  {
+    blink::WebRect rect(20, 10, 200, 100);
+    view()->convertViewportToWindow(&rect);
+    EXPECT_EQ(20, rect.x);
+    EXPECT_EQ(10, rect.y);
+    EXPECT_EQ(200, rect.width);
+    EXPECT_EQ(100, rect.height);
+  }
 
-  blink::WebRect rect(20, 10, 200, 100);
-  view()->convertViewportToWindow(&rect);
-  EXPECT_EQ(10, rect.x);
-  EXPECT_EQ(5, rect.y);
-  EXPECT_EQ(100, rect.width);
-  EXPECT_EQ(50, rect.height);
+  SetDeviceScaleFactor(2.f);
+  {
+    blink::WebRect rect(20, 10, 200, 100);
+    view()->convertViewportToWindow(&rect);
+    EXPECT_EQ(10, rect.x);
+    EXPECT_EQ(5, rect.y);
+    EXPECT_EQ(100, rect.width);
+    EXPECT_EQ(50, rect.height);
+  }
 }
 
+#if defined(OS_MACOSX) || defined(USE_AURA)
+TEST_F(RenderViewImplScaleFactorTest, GetCompositionCharacterBoundsTest) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableUseZoomForDSF);
+  DoSetUp();
+  SetDeviceScaleFactor(1.f);
+#if defined(OS_WIN)
+  // http://crbug.com/508747
+  if (base::win::GetVersion() >= base::win::VERSION_WIN10)
+    return;
+#endif
+
+  LoadHTML("<textarea id=\"test\"></textarea>");
+  ExecuteJavaScriptForTests("document.getElementById('test').focus();");
+
+  const base::string16 empty_string;
+  const std::vector<blink::WebCompositionUnderline> empty_underline;
+  std::vector<gfx::Rect> bounds_at_1x;
+  view()->OnSetFocus(true);
+
+  // ASCII composition
+  const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo");
+  view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0);
+  view()->GetCompositionCharacterBounds(&bounds_at_1x);
+  ASSERT_EQ(ascii_composition.size(), bounds_at_1x.size());
+
+  SetDeviceScaleFactor(2.f);
+  std::vector<gfx::Rect> bounds_at_2x;
+  view()->GetCompositionCharacterBounds(&bounds_at_2x);
+  ASSERT_EQ(bounds_at_1x.size(), bounds_at_2x.size());
+  for (size_t i = 0; i < bounds_at_1x.size(); i++) {
+    const gfx::Rect& b1 = bounds_at_1x[i];
+    const gfx::Rect& b2 = bounds_at_2x[i];
+    gfx::Vector2d origin_diff = b1.origin() - b2.origin();
+
+    // The bounds may not be exactly same because the font metrics are different
+    // at 1x and 2x. Just make sure that the difference is small.
+    EXPECT_LT(origin_diff.x(), 2);
+    EXPECT_LT(origin_diff.y(), 2);
+    EXPECT_LT(std::abs(b1.width() - b2.width()), 3);
+    EXPECT_LT(std::abs(b1.height() - b2.height()), 2);
+  }
+}
+#endif
+
+#if !defined(OS_ANDROID)
+// No extensions/autoresize on Android.
+namespace {
+
+// Don't use text as it text will change the size in DIP at different
+// scale factor.
+const char kAutoResizeTestPage[] =
+    "<div style='width=20px; height=20px'></div>";
+
+}  // namespace
+
+TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithZoomForDSF) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableUseZoomForDSF);
+  DoSetUp();
+  view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
+  LoadHTML(kAutoResizeTestPage);
+  gfx::Size size_at_1x = view()->size();
+  ASSERT_FALSE(size_at_1x.IsEmpty());
+
+  SetDeviceScaleFactor(2.f);
+  LoadHTML(kAutoResizeTestPage);
+  gfx::Size size_at_2x = view()->size();
+  EXPECT_EQ(size_at_1x, size_at_2x);
+}
+
+TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithoutZoomForDSF) {
+  DoSetUp();
+  view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
+  LoadHTML(kAutoResizeTestPage);
+  gfx::Size size_at_1x = view()->size();
+  ASSERT_FALSE(size_at_1x.IsEmpty());
+
+  SetDeviceScaleFactor(2.f);
+  LoadHTML(kAutoResizeTestPage);
+  gfx::Size size_at_2x = view()->size();
+  EXPECT_EQ(size_at_1x, size_at_2x);
+}
+
+#endif
+
 TEST_F(DevToolsAgentTest, DevToolsResumeOnClose) {
   Attach();
   EXPECT_FALSE(IsPaused());
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index b9fce4d..6b6b146c 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -85,7 +85,6 @@
 #include "content/renderer/internal_document_state_data.h"
 #include "content/renderer/media/audio_device_factory.h"
 #include "content/renderer/media/video_capture_impl_manager.h"
-#include "content/renderer/mhtml_generator.h"
 #include "content/renderer/navigation_state_impl.h"
 #include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_frame_proxy.h"
@@ -779,7 +778,6 @@
     OnEnableAutoResize(params.min_size, params.max_size);
   }
 
-  new MHTMLGenerator(this);
 #if defined(OS_MACOSX)
   new TextInputClientObserver(this);
 #endif  // defined(OS_MACOSX)
@@ -2659,8 +2657,15 @@
   DCHECK(disable_scrollbars_size_limit_.IsEmpty());
   if (!webview())
     return;
+
   auto_resize_mode_ = true;
-  webview()->enableAutoResizeMode(min_size, max_size);
+  if (IsUseZoomForDSFEnabled()) {
+    webview()->enableAutoResizeMode(
+        gfx::ScaleToCeiledSize(min_size, device_scale_factor_),
+        gfx::ScaleToCeiledSize(max_size, device_scale_factor_));
+  } else {
+    webview()->enableAutoResizeMode(min_size, max_size);
+  }
 }
 
 void RenderViewImpl::OnDisableAutoResize(const gfx::Size& new_size) {
@@ -3245,7 +3250,8 @@
     // Current Pepper IME API does not handle selection bounds. So we simply
     // use the caret position as an empty range for now. It will be updated
     // after Pepper API equips features related to surrounding text retrieval.
-    gfx::Rect caret = focused_pepper_plugin_->GetCaretBounds();
+    blink::WebRect caret(focused_pepper_plugin_->GetCaretBounds());
+    convertViewportToWindow(&caret);
     *start = caret;
     *end = caret;
     return;
@@ -3260,9 +3266,9 @@
 }
 
 void RenderViewImpl::GetCompositionCharacterBounds(
-    std::vector<gfx::Rect>* bounds) {
-  DCHECK(bounds);
-  bounds->clear();
+    std::vector<gfx::Rect>* bounds_in_window) {
+  DCHECK(bounds_in_window);
+  bounds_in_window->clear();
 
 #if defined(ENABLE_PLUGINS)
   if (focused_pepper_plugin_) {
@@ -3283,15 +3289,16 @@
   if (!frame)
     return;
 
-  bounds->reserve(character_count);
+  bounds_in_window->reserve(character_count);
   blink::WebRect webrect;
   for (size_t i = 0; i < character_count; ++i) {
     if (!frame->firstRectForCharacterRange(start_offset + i, 1, webrect)) {
       DLOG(ERROR) << "Could not retrieve character rectangle at " << i;
-      bounds->clear();
+      bounds_in_window->clear();
       return;
     }
-    bounds->push_back(webrect);
+    convertViewportToWindow(&webrect);
+    bounds_in_window->push_back(webrect);
   }
 }
 
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 9a9d986..12ee60e3 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -490,7 +490,7 @@
   void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) override;
   void FocusChangeComplete() override;
   void GetCompositionCharacterBounds(
-      std::vector<gfx::Rect>* character_bounds) override;
+      std::vector<gfx::Rect>* character_bounds_in_window) override;
   void GetCompositionRange(gfx::Range* range) override;
   bool CanComposeInline() override;
   void DidCommitCompositorFrame() override;
@@ -564,6 +564,8 @@
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, PaintAfterSwapOut);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
                            ConverViewportToScreenWithZoomForDSF);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
+                           GetCompositionCharacterBoundsTest);
 
   typedef std::map<GURL, double> HostZoomLevels;
 
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index cb094441..0ae4993 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1425,15 +1425,17 @@
 // WebWidgetClient
 
 void RenderWidget::didAutoResize(const WebSize& new_size) {
-  // TODO(oshima): support UseZoomForDSFEnabled()
-  if (size_.width() != new_size.width || size_.height() != new_size.height) {
-    size_ = new_size;
+  WebRect new_size_in_window(0, 0, new_size.width, new_size.height);
+  convertViewportToWindow(&new_size_in_window);
+  if (size_.width() != new_size_in_window.width ||
+      size_.height() != new_size_in_window.height) {
+    size_ = gfx::Size(new_size_in_window.width, new_size_in_window.height);
 
     if (resizing_mode_selector_->is_synchronous_mode()) {
-      WebRect new_pos(rootWindowRect().x,
-                      rootWindowRect().y,
-                      new_size.width,
-                      new_size.height);
+      gfx::Rect new_pos(rootWindowRect().x,
+                        rootWindowRect().y,
+                        size_.width(),
+                        size_.height());
       view_screen_rect_ = new_pos;
       window_screen_rect_ = new_pos;
     }
@@ -1712,9 +1714,8 @@
   Send(new ViewHostMsg_SetTooltipText(routing_id_, text, hint));
 }
 
-void RenderWidget::setWindowRect(const WebRect& rect) {
-  // TODO(oshima): Scale back to DIP coordinates.
-  WebRect window_rect = rect;
+void RenderWidget::setWindowRect(const WebRect& rect_in_screen) {
+  WebRect window_rect = rect_in_screen;
   if (popup_origin_scale_for_emulation_) {
     float scale = popup_origin_scale_for_emulation_;
     window_rect.x = popup_screen_origin_for_emulation_.x() +
@@ -2103,16 +2104,10 @@
   WebRect focus_webrect;
   WebRect anchor_webrect;
   webwidget_->selectionBounds(focus_webrect, anchor_webrect);
-  if (IsUseZoomForDSFEnabled()) {
-    float inverse_scale = 1.f / device_scale_factor_;
-    gfx::RectF focus_rect(focus_webrect);
-    *focus = gfx::ToEnclosingRect(gfx::ScaleRect(focus_rect, inverse_scale));
-    gfx::RectF anchor_rect(anchor_webrect);
-    *anchor = gfx::ToEnclosingRect(gfx::ScaleRect(anchor_rect, inverse_scale));
-  } else {
-    *focus = focus_webrect;
-    *anchor = anchor_webrect;
-  }
+  convertViewportToWindow(&focus_webrect);
+  convertViewportToWindow(&anchor_webrect);
+  *focus = focus_webrect;
+  *anchor = anchor_webrect;
 }
 
 void RenderWidget::UpdateSelectionBounds() {
diff --git a/content/renderer/web_frame_utils.cc b/content/renderer/web_frame_utils.cc
index 6cc52aac..ee721478 100644
--- a/content/renderer/web_frame_utils.cc
+++ b/content/renderer/web_frame_utils.cc
@@ -8,6 +8,8 @@
 #include "content/renderer/render_frame_proxy.h"
 #include "ipc/ipc_message.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebRemoteFrame.h"
 
 namespace content {
 
@@ -19,4 +21,16 @@
   return RenderFrameImpl::FromWebFrame(web_frame)->GetRoutingID();
 }
 
+blink::WebFrame* GetWebFrameFromRoutingIdForFrameOrProxy(int routing_id) {
+  auto* render_frame = RenderFrameImpl::FromRoutingID(routing_id);
+  if (render_frame)
+    return render_frame->GetWebFrame();
+
+  auto* render_frame_proxy = RenderFrameProxy::FromRoutingID(routing_id);
+  if (render_frame_proxy)
+    return render_frame_proxy->web_frame();
+
+  return nullptr;
+}
+
 }  // namespace content
diff --git a/content/renderer/web_frame_utils.h b/content/renderer/web_frame_utils.h
index 73d188a..798fb03a 100644
--- a/content/renderer/web_frame_utils.h
+++ b/content/renderer/web_frame_utils.h
@@ -15,6 +15,10 @@
 // associated with |web_frame|.
 int GetRoutingIdForFrameOrProxy(blink::WebFrame* web_frame);
 
+// Returns either a WebLocalFrame or WebRemoteFrame based on |routing_id|.
+// Returns nullptr if |routing_id| doesn't properly map to a frame.
+blink::WebFrame* GetWebFrameFromRoutingIdForFrameOrProxy(int routing_id);
+
 }  // namespace content
 
 #endif  // CONTENT_RENDERER_WEB_FRAME_UTILS_H_
diff --git a/content/test/dwrite_font_fake_sender_win.cc b/content/test/dwrite_font_fake_sender_win.cc
new file mode 100644
index 0000000..83203af
--- /dev/null
+++ b/content/test/dwrite_font_fake_sender_win.cc
@@ -0,0 +1,174 @@
+// Copyright 2015 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/test/dwrite_font_fake_sender_win.h"
+
+#include <shlobj.h>
+
+#include "content/common/dwrite_font_proxy_messages.h"
+
+namespace content {
+
+void AddFamily(const base::string16& font_path,
+               const base::string16& family_name,
+               const base::string16& base_family_name,
+               FakeFontCollection* collection) {
+  collection->AddFont(family_name)
+      .AddFamilyName(L"en-us", family_name)
+      .AddFilePath(font_path + L"\\" + base_family_name + L".ttf")
+      .AddFilePath(font_path + L"\\" + base_family_name + L"bd.ttf")
+      .AddFilePath(font_path + L"\\" + base_family_name + L"bi.ttf")
+      .AddFilePath(font_path + L"\\" + base_family_name + L"i.ttf");
+}
+
+IPC::Sender* CreateFakeCollectionSender() {
+  std::vector<base::char16> font_path_chars;
+  font_path_chars.resize(MAX_PATH);
+  SHGetSpecialFolderPath(nullptr /* hwndOwner - reserved */,
+                         font_path_chars.data(), CSIDL_FONTS,
+                         FALSE /* fCreate */);
+  base::string16 font_path(font_path_chars.data());
+  scoped_refptr<FakeFontCollection> fake_collection = new FakeFontCollection();
+  AddFamily(font_path, L"Arial", L"arial", fake_collection.get());
+  AddFamily(font_path, L"Courier New", L"cour", fake_collection.get());
+  AddFamily(font_path, L"Times New Roman", L"times", fake_collection.get());
+  return fake_collection->GetSender();
+}
+
+FakeFont::FakeFont(const base::string16& name) : font_name_(name) {}
+
+FakeFont::~FakeFont() = default;
+
+FakeFontCollection::FakeFontCollection() = default;
+
+FakeFont& FakeFontCollection::AddFont(const base::string16& font_name) {
+  fonts_.emplace_back(font_name);
+  return fonts_.back();
+}
+
+size_t FakeFontCollection::MessageCount() {
+  return messages_.size();
+}
+
+IPC::Message* FakeFontCollection::GetMessage(size_t index) {
+  return messages_[index].get();
+}
+
+IPC::Sender* FakeFontCollection::GetSender() {
+  return new FakeSender(this, false /* track_messages */);
+}
+
+IPC::Sender* FakeFontCollection::GetTrackingSender() {
+  return new FakeSender(this, true /* track_messages */);
+}
+
+FakeFontCollection::ReplySender::ReplySender(FakeFontCollection* collection)
+    : collection_(collection) {}
+
+FakeFontCollection::ReplySender::~ReplySender() = default;
+
+scoped_ptr<IPC::Message>& FakeFontCollection::ReplySender::OnMessageReceived(
+    const IPC::Message& msg) {
+  reply_.reset();
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(ReplySender, msg)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_FindFamily, OnFindFamily)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyCount, OnGetFamilyCount)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFamilyNames, OnGetFamilyNames)
+    IPC_MESSAGE_HANDLER(DWriteFontProxyMsg_GetFontFiles, OnGetFontFiles)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return reply_;
+}
+
+bool FakeFontCollection::ReplySender::Send(IPC::Message* msg) {
+  reply_.reset(msg);
+  return true;
+}
+
+void FakeFontCollection::ReplySender::OnFindFamily(
+    const base::string16& family_name,
+    uint32_t* index) {
+  collection_->OnFindFamily(family_name, index);
+}
+
+void FakeFontCollection::ReplySender::OnGetFamilyCount(uint32_t* count) {
+  collection_->OnGetFamilyCount(count);
+}
+
+void FakeFontCollection::ReplySender::OnGetFamilyNames(
+    uint32_t family_index,
+    std::vector<DWriteStringPair>* family_names) {
+  collection_->OnGetFamilyNames(family_index, family_names);
+}
+
+void FakeFontCollection::ReplySender::OnGetFontFiles(
+    uint32_t family_index,
+    std::vector<base::string16>* file_paths) {
+  collection_->OnGetFontFiles(family_index, file_paths);
+}
+
+FakeFontCollection::FakeSender::FakeSender(FakeFontCollection* collection,
+                                           bool track_messages)
+    : track_messages_(track_messages), collection_(collection) {}
+
+FakeFontCollection::FakeSender::~FakeSender() = default;
+
+bool FakeFontCollection::FakeSender::Send(IPC::Message* message) {
+  std::unique_ptr<IPC::Message> incoming_message;
+  if (track_messages_)
+    collection_->messages_.emplace_back(message);
+  else
+    incoming_message.reset(message);  // Ensure message is deleted.
+  std::unique_ptr<ReplySender> sender = collection_->GetReplySender();
+  scoped_ptr<IPC::Message> reply;
+  reply.swap(sender->OnMessageReceived(*message));
+
+  IPC::SyncMessage* sync_message = reinterpret_cast<IPC::SyncMessage*>(message);
+  scoped_ptr<IPC::MessageReplyDeserializer> serializer(
+      sync_message->GetReplyDeserializer());
+  serializer->SerializeOutputParameters(*(reply.get()));
+  return true;
+}
+
+void FakeFontCollection::OnFindFamily(const base::string16& family_name,
+                                      uint32_t* index) {
+  for (size_t n = 0; n < fonts_.size(); n++) {
+    if (_wcsicmp(family_name.data(), fonts_[n].font_name_.data()) == 0) {
+      *index = n;
+      return;
+    }
+  }
+  *index = UINT32_MAX;
+}
+
+void FakeFontCollection::OnGetFamilyCount(uint32_t* count) {
+  *count = fonts_.size();
+}
+
+void FakeFontCollection::OnGetFamilyNames(
+    uint32_t family_index,
+    std::vector<DWriteStringPair>* family_names) {
+  if (family_index >= fonts_.size())
+    return;
+  *family_names = fonts_[family_index].family_names_;
+}
+
+void FakeFontCollection::OnGetFontFiles(
+    uint32_t family_index,
+    std::vector<base::string16>* file_paths) {
+  if (family_index >= fonts_.size())
+    return;
+  *file_paths = fonts_[family_index].file_paths_;
+}
+
+std::unique_ptr<FakeFontCollection::ReplySender>
+FakeFontCollection::GetReplySender() {
+  return std::unique_ptr<FakeFontCollection::ReplySender>(
+      new FakeFontCollection::ReplySender(this));
+}
+
+FakeFontCollection::~FakeFontCollection() = default;
+
+}  // namespace content
diff --git a/content/test/dwrite_font_fake_sender_win.h b/content/test/dwrite_font_fake_sender_win.h
new file mode 100644
index 0000000..d6f438a
--- /dev/null
+++ b/content/test/dwrite_font_fake_sender_win.h
@@ -0,0 +1,160 @@
+// Copyright (c) 2015 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_TEST_DWRITE_FONT_FAKE_SENDER_WIN_H_
+#define CONTENT_TEST_DWRITE_FONT_FAKE_SENDER_WIN_H_
+
+#include <wrl.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string16.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sender.h"
+
+namespace content {
+
+class FakeFontCollection;
+
+// Creates a new FakeFontCollection, seeded with some basic data, and returns a
+// Sender that can be used to interact with the collection.
+IPC::Sender* CreateFakeCollectionSender();
+
+// Helper class for describing a font object. Use FakeFontCollection instead.
+class FakeFont {
+ public:
+  explicit FakeFont(const base::string16& name);
+
+  ~FakeFont();
+
+  FakeFont& AddFilePath(const base::string16& file_path) {
+    file_paths_.push_back(file_path);
+    return *this;
+  }
+
+  FakeFont& AddFamilyName(const base::string16& locale,
+                          const base::string16& family_name) {
+    family_names_.emplace_back(locale, family_name);
+    return *this;
+  }
+
+ private:
+  friend FakeFontCollection;
+  base::string16 font_name_;
+  std::vector<base::string16> file_paths_;
+  std::vector<std::pair<base::string16, base::string16>> family_names_;
+
+  DISALLOW_ASSIGN(FakeFont);
+};
+
+// Implements a font collection that supports interaction through sending IPC
+// messages from dwrite_font_proxy_messages.h.
+// Usage:
+//   Create a new FakeFontCollection.
+//   Call AddFont() to add fonts.
+//     For each font, call methods on the font to configure the font.
+//     Note: the indices of the fonts will correspond to the order they were
+//         added. The collection will not sort or reorder fonts in any way.
+//   Call GetSender()/GetTrackingSender() to obtain an IPC::Sender.
+//   Call Send() with DWriteFontProxyMsg_* to interact with the collection.
+//   Call MessageCount()/GetMessage() to inspect the messages that were sent.
+//
+// The internal code flow for GetSender()/Send() is as follows:
+//   GetSender() returns a new FakeSender, pointing back to the collection.
+//   FakeSender::Send() will create a new ReplySender and call
+//       ReplySender::OnMessageReceived()
+//   ReplySender::OnMessageReceived() contains the message map, which will
+//       internally call ReplySender::On*() and ReplySender::Send()
+//   ReplySender::Send() will save the reply message, to be used later.
+//   FakeSender::Send() will retrieve the reply message and save the output.
+class FakeFontCollection : public base::RefCounted<FakeFontCollection> {
+ public:
+  FakeFontCollection();
+
+  FakeFont& AddFont(const base::string16& font_name);
+
+  size_t MessageCount();
+
+  IPC::Message* GetMessage(size_t index);
+
+  IPC::Sender* GetSender();
+
+  // Like GetSender(), but will keep track of all sent messages for inspection.
+  IPC::Sender* GetTrackingSender();
+
+ protected:
+  // This class handles sending the reply message back to the "renderer"
+  class ReplySender : public IPC::Sender {
+   public:
+    explicit ReplySender(FakeFontCollection* collection);
+
+    ~ReplySender() override;
+
+    scoped_ptr<IPC::Message>& OnMessageReceived(const IPC::Message& msg);
+
+    bool Send(IPC::Message* msg) override;
+
+   private:
+    void OnFindFamily(const base::string16& family_name, uint32_t* index);
+
+    void OnGetFamilyCount(uint32_t* count);
+
+    void OnGetFamilyNames(
+        uint32_t family_index,
+        std::vector<std::pair<base::string16, base::string16>>* family_names);
+    void OnGetFontFiles(uint32 family_index,
+                        std::vector<base::string16>* file_paths_);
+
+   private:
+    scoped_refptr<FakeFontCollection> collection_;
+    scoped_ptr<IPC::Message> reply_;
+
+    DISALLOW_COPY_AND_ASSIGN(ReplySender);
+  };
+
+  // This class can be used by the "renderer" to send messages to the "browser"
+  class FakeSender : public IPC::Sender {
+   public:
+    FakeSender(FakeFontCollection* collection, bool track_messages);
+
+    ~FakeSender() override;
+
+    bool Send(IPC::Message* message) override;
+
+   private:
+    bool track_messages_;
+    scoped_refptr<FakeFontCollection> collection_;
+
+    DISALLOW_COPY_AND_ASSIGN(FakeSender);
+  };
+
+  void OnFindFamily(const base::string16& family_name, uint32_t* index);
+
+  void OnGetFamilyCount(uint32_t* count);
+
+  void OnGetFamilyNames(
+      uint32_t family_index,
+      std::vector<std::pair<base::string16, base::string16>>* family_names);
+
+  void OnGetFontFiles(uint32 family_index,
+                      std::vector<base::string16>* file_paths);
+
+  std::unique_ptr<ReplySender> GetReplySender();
+
+ private:
+  friend class base::RefCounted<FakeFontCollection>;
+  ~FakeFontCollection();
+
+  std::vector<FakeFont> fonts_;
+  std::vector<std::unique_ptr<IPC::Message>> messages_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeFontCollection);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_TEST_DWRITE_FONT_FAKE_SENDER_WIN_H_
diff --git a/content/test/gpu/gpu_tests/trace_test.py b/content/test/gpu/gpu_tests/trace_test.py
index d569b46..35b1192 100644
--- a/content/test/gpu/gpu_tests/trace_test.py
+++ b/content/test/gpu/gpu_tests/trace_test.py
@@ -23,16 +23,6 @@
   domAutomationController.setAutomationId = function(id) {}
 
   domAutomationController.send = function(msg) {
-    // Issue a read pixel to synchronize the gpu process to ensure
-    // the asynchronous category enabling is finished.
-    var canvas = document.createElement("canvas")
-    canvas.width = 1;
-    canvas.height = 1;
-    var gl = canvas.getContext("webgl");
-    gl.clear(gl.COLOR_BUFFER_BIT);
-    var id = new Uint8Array(4);
-    gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, id);
-
     domAutomationController._finished = true;
   }
 
diff --git a/content/test/gpu/gpu_tests/trace_test_expectations.py b/content/test/gpu/gpu_tests/trace_test_expectations.py
index 764dbce5..a1f9d01 100644
--- a/content/test/gpu/gpu_tests/trace_test_expectations.py
+++ b/content/test/gpu/gpu_tests/trace_test_expectations.py
@@ -11,7 +11,7 @@
     # Sample Usage:
     # self.Fail('TraceTest.Canvas2DRedBox',
     #     ['mac', 'amd', ('nvidia', 0x1234)], bug=123)
-    pass
+    self.Skip('*', bug=512622)
 
 class DeviceTraceTestExpectations(GpuTestExpectations):
   def SetExpectations(self):
diff --git a/extensions/browser/value_store/leveldb_value_store.cc b/extensions/browser/value_store/leveldb_value_store.cc
index 1c42ca5..6ae15c40 100644
--- a/extensions/browser/value_store/leveldb_value_store.cc
+++ b/extensions/browser/value_store/leveldb_value_store.cc
@@ -83,6 +83,8 @@
   open_options_.paranoid_checks = true;
   open_options_.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
 
+  read_options_.verify_checksums = true;
+
   // Used in lieu of UMA_HISTOGRAM_ENUMERATION because the histogram name is
   // not a constant.
   open_histogram_ = base::LinearHistogram::FactoryGet(
@@ -135,7 +137,7 @@
     return MakeReadResult(status);
 
   scoped_ptr<base::Value> setting;
-  status.Merge(ReadFromDb(leveldb::ReadOptions(), key, &setting));
+  status.Merge(ReadFromDb(key, &setting));
   if (!status.ok())
     return MakeReadResult(status);
 
@@ -153,17 +155,12 @@
   if (!status.ok())
     return MakeReadResult(status);
 
-  leveldb::ReadOptions options;
   scoped_ptr<base::DictionaryValue> settings(new base::DictionaryValue());
 
-  // All interaction with the db is done on the same thread, so snapshotting
-  // isn't strictly necessary.  This is just defensive.
-  ScopedSnapshot snapshot(db_.get());
-  options.snapshot = snapshot.get();
   for (std::vector<std::string>::const_iterator it = keys.begin();
       it != keys.end(); ++it) {
     scoped_ptr<base::Value> setting;
-    status.Merge(ReadFromDb(options, *it, &setting));
+    status.Merge(ReadFromDb(*it, &setting));
     if (!status.ok())
       return MakeReadResult(status);
     if (setting)
@@ -277,7 +274,7 @@
   for (std::vector<std::string>::const_iterator it = keys.begin();
       it != keys.end(); ++it) {
     scoped_ptr<base::Value> old_value;
-    status.Merge(ReadFromDb(leveldb::ReadOptions(), *it, &old_value));
+    status.Merge(ReadFromDb(*it, &old_value));
     if (!status.ok())
       return MakeWriteResult(status);
 
@@ -469,14 +466,13 @@
 }
 
 ValueStore::Status LeveldbValueStore::ReadFromDb(
-    leveldb::ReadOptions options,
     const std::string& key,
     scoped_ptr<base::Value>* setting) {
   DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(setting);
 
   std::string value_as_json;
-  leveldb::Status s = db_->Get(options, key, &value_as_json);
+  leveldb::Status s = db_->Get(read_options_, key, &value_as_json);
 
   if (s.IsNotFound()) {
     // Despite there being no value, it was still a success. Check this first
@@ -505,7 +501,7 @@
 
   if (!(options & NO_GENERATE_CHANGES)) {
     scoped_ptr<base::Value> old_value;
-    Status status = ReadFromDb(leveldb::ReadOptions(), key, &old_value);
+    Status status = ReadFromDb(key, &old_value);
     if (!status.ok())
       return status;
     if (!old_value || !old_value->Equals(&value)) {
diff --git a/extensions/browser/value_store/leveldb_value_store.h b/extensions/browser/value_store/leveldb_value_store.h
index 6b34e8a..300672ee 100644
--- a/extensions/browser/value_store/leveldb_value_store.h
+++ b/extensions/browser/value_store/leveldb_value_store.h
@@ -74,8 +74,7 @@
   ValueStore::Status EnsureDbIsOpen();
 
   // Reads a setting from the database.
-  ValueStore::Status ReadFromDb(leveldb::ReadOptions options,
-                                const std::string& key,
+  ValueStore::Status ReadFromDb(const std::string& key,
                                 // Will be reset() with the result, if any.
                                 scoped_ptr<base::Value>* setting);
 
@@ -106,6 +105,7 @@
   // The location of the leveldb backend.
   const base::FilePath db_path_;
   leveldb::Options open_options_;
+  leveldb::ReadOptions read_options_;
 
   // leveldb backend.
   scoped_ptr<leveldb::DB> db_;
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index 829ef00..0f8af6e 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -89,28 +89,6 @@
     sources += chromeos_sources
   }
 
-  # TODO(GYP): Enable this when //components/nacl GN is done. See
-  # http://crbug.com/430602
-  if (false) {
-    if (enable_nacl) {
-      if (is_linux) {
-        deps += [ "//components/nacl:nacl_helper" ]
-      }
-      deps += [
-        "//components/nacl",
-        "//components/nacl:browser",
-        "//components/nacl:common",
-        "//components/nacl:renderer",
-        "//components/nacl:switches",
-      ]
-      nacl_sources =
-          rebase_path(app_shell_gypi_values.app_shell_lib_sources_nacl,
-                      ".",
-                      "//extensions/shell")
-      sources += nacl_sources
-    }
-  }
-
   if (enable_nacl) {
     sources += [
       "browser/shell_nacl_browser_delegate.cc",
@@ -118,16 +96,15 @@
     ]
 
     deps += [
-      "//components/nacl",
-      "//components/nacl:nacl_browser",
-      "//components/nacl:nacl_common",
-      "//components/nacl:nacl_renderer",
-      "//components/nacl:nacl_switches",
+      "//components/nacl/browser",
+      "//components/nacl/common",
+      "//components/nacl/loader",
+      "//components/nacl/renderer",
       "//components/nacl/renderer/plugin:nacl_trusted_plugin",
     ]
 
     if (is_linux) {
-      deps += [ "//components/nacl:nacl_helper" ]
+      deps += [ "//components/nacl/loader:nacl_helper" ]
     }
   }
 
diff --git "a/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json" "b/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json"
index 5440881..0b4031ac 100644
--- "a/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json"
+++ "b/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json"
@@ -7,9 +7,13 @@
   ],
   "xcode version": "7.0",
   "GYP_DEFINES": {
+    "OS": "ios",
     "chromium_ios_signing": "0",
-    "target_subarch": "both"
+    "gomadir": "$(goma_dir)",
+    "target_subarch": "both",
+    "use_goma": "1"
   },
+  "mb_type": "gyp",
   "compiler": "ninja",
   "configuration": "Release",
   "sdk": "iphoneos9.0",
diff --git a/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json b/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json
index 8f3e195..7cb285e 100644
--- a/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json
+++ b/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json
@@ -7,9 +7,13 @@
   ],
   "xcode version": "7.0",
   "GYP_DEFINES": {
+    "OS": "ios",
     "chromium_ios_signing": "0",
-    "target_subarch": "both"
+    "gomadir": "$(goma_dir)",
+    "target_subarch": "both",
+    "use_goma": "1"
   },
+  "mb_type": "gyp",
   "compiler": "ninja",
   "configuration": "Debug",
   "sdk": "iphonesimulator9.0",
diff --git a/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json b/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json
index 5440881..0b4031ac 100644
--- a/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json
+++ b/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json
@@ -7,9 +7,13 @@
   ],
   "xcode version": "7.0",
   "GYP_DEFINES": {
+    "OS": "ios",
     "chromium_ios_signing": "0",
-    "target_subarch": "both"
+    "gomadir": "$(goma_dir)",
+    "target_subarch": "both",
+    "use_goma": "1"
   },
+  "mb_type": "gyp",
   "compiler": "ninja",
   "configuration": "Release",
   "sdk": "iphoneos9.0",
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 5f77d57..7d76e91 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -218,6 +218,73 @@
       <message name="IDS_IOS_GENERATED_PASSWORD_PROMPT_TITLE" desc="The text of the button that accepts the generated password. [Length: 20em] [iOS only]">
         Password Generated by Chrome
       </message>
+
+      <!-- Safe Browsing -->
+      <!-- - harmful download interstitials -->
+      <message name="IDS_IOS_HARMFUL_V3_EXPLANATION_PARAGRAPH" desc="The explanation of why Safe Browsing has blocked the page.">
+        Google Safe Browsing recently <ph name="BEGIN_LINK">&lt;a href="#" id="help-link"&gt;</ph>found harmful programs<ph name="END_LINK">&lt;/a&gt;</ph> on <ph name="SITE">$1<ex>example.com</ex></ph>.
+      </message>
+      <message name="IDS_IOS_HARMFUL_V3_HEADING" desc="The large heading at the top of the social engineering interstitial.">
+        The site ahead contains harmful programs
+      </message>
+      <message name="IDS_IOS_HARMFUL_V3_PRIMARY_PARAGRAPH" desc="Mobile: The primary explanatory paragraph for the social engineering interstitial.">
+        Attackers on <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="SITE">$1<ex>example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> might attempt to trick you into installing programs that harm your browsing experience (for example, by changing your homepage or showing extra ads on sites you visit).
+      </message>
+      <message name="IDS_IOS_HARMFUL_V3_PROCEED_PARAGRAPH" desc="The paragraph that lets the user skip the warning.">
+        If you understand the risks to your security, you may <ph name="BEGIN_LINK">&lt;a href="#" id="proceed-link"&gt;</ph>visit this site<ph name="END_LINK">&lt;/a&gt;</ph> before the harmful programs have been removed.
+      </message>
+      <!-- - malware interstitials -->
+      <message name="IDS_IOS_MALWARE_V3_EXPLANATION_PARAGRAPH" desc="The explanation of why Safe Browsing has blocked the page.">
+        Google Safe Browsing recently <ph name="BEGIN_LINK">&lt;a href="#" id="help-link"&gt;</ph>detected malware<ph name="END_LINK">&lt;/a&gt;</ph> on <ph name="SITE">$1<ex>example.com</ex></ph>. Websites that are normally safe are sometimes infected with malware.
+      </message>
+      <message name="IDS_IOS_MALWARE_V3_EXPLANATION_PARAGRAPH_SUBRESOURCE" desc="The explanation of why Safe Browsing has blocked the page.">
+        Google Safe Browsing recently <ph name="BEGIN_LINK">&lt;a href="#" id="help-link"&gt;</ph>detected malware<ph name="END_LINK">&lt;/a&gt;</ph> on <ph name="SITE">$1<ex>example.com</ex></ph>. Websites that are normally safe are sometimes infected with malware. The malicious content comes from <ph name="SUBRESOURCE_HOST">$2<ex>evil.com</ex></ph>, a known malware distributor.
+      </message>
+      <message name="IDS_IOS_MALWARE_V3_HEADING" desc="The large heading at the top of the malware interstitial.">
+        The site ahead contains malware
+      </message>
+      <message name="IDS_IOS_MALWARE_V3_PRIMARY_PARAGRAPH" desc="Mobile: The primary explanatory paragraph for the malware interstitial.">
+        Attackers currently on <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="SITE">$1<ex>example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> might attempt to install dangerous apps on your device that steal or delete your information (for example, photos, passwords, messages, and credit cards).
+      </message>
+      <message name="IDS_IOS_MALWARE_V3_PROCEED_PARAGRAPH" desc="The paragraph that lets the user skip the warning.">
+        If you understand the risks to your security, you may <ph name="BEGIN_LINK">&lt;a href="#" id="proceed-link"&gt;</ph>visit this unsafe site<ph name="END_LINK">&lt;/a&gt;</ph> before the dangerous programs have been removed.
+      </message>
+      <!-- - phishing interstitials -->
+      <message name="IDS_IOS_PHISHING_V3_EXPLANATION_PARAGRAPH" desc="The explanation of why Safe Browsing has blocked the page.">
+      Google Safe Browsing recently detected phishing on <ph name="SITE">$1<ex>example.com</ex></ph>. <ph name="BEGIN_LINK">&lt;a href="#" id="help-link"&gt;</ph>Phishing sites<ph name="END_LINK">&lt;/a&gt;</ph> pretend to be other websites to trick you.
+      </message>
+      <message name="IDS_IOS_PHISHING_V3_HEADING" desc="The large heading at the top of the phishing interstitial.">
+        Phishing attack ahead
+      </message>
+      <message name="IDS_IOS_PHISHING_V3_PRIMARY_PARAGRAPH" desc="The primary explanatory paragraph for the malware interstitial.">
+        Attackers on <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="SITE">$1<ex>example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> might try to trick you to steal your information (for example, passwords, messages, or credit cards).
+      </message>
+      <message name="IDS_IOS_PHISHING_V3_PROCEED_PARAGRAPH" desc="The paragraph that lets the user skip the warning.">
+        If you understand the risks to your security, you may <ph name="BEGIN_LINK">&lt;a href="#" id="proceed-link"&gt;</ph>visit this unsafe site<ph name="END_LINK">&lt;/a&gt;</ph>.
+      </message>
+      <message name="IDS_IOS_PHISHING_V4_HEADING" desc="The large heading at the top of the phishing interstitial.">
+        Deceptive site ahead
+      </message>
+      <message name="IDS_IOS_PHISHING_V4_PRIMARY_PARAGRAPH" desc="The primary explanatory paragraph for the malware interstitial.">
+        Attackers on <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="SITE">$1<ex>example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> may trick you into doing something dangerous like installing software or revealing your personal information (for example, passwords, phone numbers, or credit cards).
+      </message>
+      <message name="IDS_IOS_PHISHING_V4_PROCEED_AND_REPORT_PARAGRAPH" desc="The paragraph that lets the user skip the warning.">
+        You can <ph name="BEGIN_ERROR_LINK">&lt;a href="#" id="report-error-link"&gt;</ph>report a detection problem<ph name="END_ERROR_LINK">&lt;/a&gt;</ph> or, if you understand the risks to your security, <ph name="BEGIN_LINK">&lt;a href="#" id="proceed-link"&gt;</ph>visit this unsafe site<ph name="END_LINK">&lt;/a&gt;</ph>.
+      </message>
+      <!-- - shared strings -->
+      <message name="IDS_IOS_SAFEBROWSING_OVERRIDABLE_SAFETY_BUTTON" desc="The text for the button that takes the user back to the previous page.">
+        Back to safety
+      </message>
+      <message name="IDS_IOS_SAFEBROWSING_V3_CLOSE_DETAILS_BUTTON" desc="The text for the button that hides the details.">
+        Hide details
+      </message>
+      <message name="IDS_IOS_SAFEBROWSING_V3_OPEN_DETAILS_BUTTON" desc="The text for the button that expands the details.">
+        Details
+      </message>
+      <message name="IDS_IOS_SAFEBROWSING_V3_TITLE" desc="The tab title for the Safe Browsing interstitials.">
+        Security error
+      </message>
+
     </messages>
   </release>
 </grit>
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index e096b28..2f51f237 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -195,6 +195,8 @@
     "install_time_util.mm",
     "installation_notifier.h",
     "installation_notifier.mm",
+    "interstitials/ios_chrome_metrics_helper.cc",
+    "interstitials/ios_chrome_metrics_helper.h",
     "invalidation/ios_chrome_profile_invalidation_provider_factory.cc",
     "invalidation/ios_chrome_profile_invalidation_provider_factory.h",
     "ios_chrome_field_trials.cc",
@@ -330,6 +332,8 @@
     "suggestions/suggestions_service_factory.mm",
     "sync/glue/sync_start_util.cc",
     "sync/glue/sync_start_util.h",
+    "sync/ios_chrome_profile_sync_service_factory.cc",
+    "sync/ios_chrome_profile_sync_service_factory.h",
     "sync/ios_chrome_sync_client.cc",
     "sync/ios_chrome_sync_client.h",
     "sync/ios_chrome_synced_tab_delegate.cc",
@@ -511,6 +515,7 @@
     "//components/resources",
     "//components/search",
     "//components/search_engines",
+    "//components/security_interstitials/core",
     "//components/sessions",
     "//components/signin/core/browser",
     "//components/signin/core/common",
@@ -649,16 +654,23 @@
     "signin/fake_oauth2_token_service_builder.h",
     "signin/fake_signin_manager_builder.cc",
     "signin/fake_signin_manager_builder.h",
+    "sync/ios_chrome_profile_sync_test_util.cc",
+    "sync/ios_chrome_profile_sync_test_util.h",
     "sync/sync_setup_service_mock.cc",
     "sync/sync_setup_service_mock.h",
   ]
 
   deps = [
+    "//base",
+    "//components/browser_sync/browser",
     "//components/signin/core/browser",
     "//components/signin/ios/browser",
+    "//components/sync_driver",
     "//ios/chrome/browser",
+    "//ios/chrome/common",
     "//ios/chrome/test",
     "//ios/public/provider/chrome/browser",
+    "//ios/web",
     "//testing/gmock",
     "//testing/gtest",
     "//ui/base",
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 20716e4..d18a618 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -48,8 +48,8 @@
   "+components/rlz",
   "+components/search",
   "+components/search_engines",
+  "+components/security_interstitials",
   "+components/sessions",
-  "-components/sessions/content",
   "+components/signin/core/browser",
   "+components/signin/core/common",
   "+components/signin/ios/browser",
@@ -83,6 +83,7 @@
 
   # Those depend on //content; exclude them.
   "-components/metrics/gpu",
+  "-components/sessions/content",
 
   # For tests.
   "+ios/chrome/test",
diff --git a/ios/chrome/browser/browser_state/bookmark_model_loaded_observer.cc b/ios/chrome/browser/browser_state/bookmark_model_loaded_observer.cc
new file mode 100644
index 0000000..21ec9c4
--- /dev/null
+++ b/ios/chrome/browser/browser_state/bookmark_model_loaded_observer.cc
@@ -0,0 +1,29 @@
+// Copyright 2015 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 "ios/chrome/browser/browser_state/bookmark_model_loaded_observer.h"
+
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "ios/public/provider/chrome/browser/keyed_service_provider.h"
+
+BookmarkModelLoadedObserver::BookmarkModelLoadedObserver(
+    ios::ChromeBrowserState* browser_state)
+    : browser_state_(browser_state) {}
+
+void BookmarkModelLoadedObserver::BookmarkModelChanged() {}
+
+void BookmarkModelLoadedObserver::BookmarkModelLoaded(
+    bookmarks::BookmarkModel* model,
+    bool ids_reassigned) {
+  // Causes lazy-load if sync is enabled.
+  ios::GetKeyedServiceProvider()->GetSyncServiceForBrowserState(browser_state_);
+  model->RemoveObserver(this);
+  delete this;
+}
+
+void BookmarkModelLoadedObserver::BookmarkModelBeingDeleted(
+    bookmarks::BookmarkModel* model) {
+  model->RemoveObserver(this);
+  delete this;
+}
diff --git a/ios/chrome/browser/browser_state/bookmark_model_loaded_observer.h b/ios/chrome/browser/browser_state/bookmark_model_loaded_observer.h
new file mode 100644
index 0000000..18e49645
--- /dev/null
+++ b/ios/chrome/browser/browser_state/bookmark_model_loaded_observer.h
@@ -0,0 +1,31 @@
+// Copyright 2015 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 IOS_CHROME_BROWSER_BROWSER_STATE_BOOKMARK_MODEL_LOADED_OBSERVER_H_
+#define IOS_CHROME_BROWSER_BROWSER_STATE_BOOKMARK_MODEL_LOADED_OBSERVER_H_
+
+#include "base/macros.h"
+#include "components/bookmarks/browser/base_bookmark_model_observer.h"
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+class BookmarkModelLoadedObserver
+    : public bookmarks::BaseBookmarkModelObserver {
+ public:
+  explicit BookmarkModelLoadedObserver(ios::ChromeBrowserState* browser_state);
+
+ private:
+  void BookmarkModelChanged() override;
+  void BookmarkModelLoaded(bookmarks::BookmarkModel* model,
+                           bool ids_reassigned) override;
+  void BookmarkModelBeingDeleted(bookmarks::BookmarkModel* model) override;
+
+  ios::ChromeBrowserState* browser_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkModelLoadedObserver);
+};
+
+#endif  // IOS_CHROME_BROWSER_BROWSER_STATE_BOOKMARK_MODEL_LOADED_OBSERVER_H_
diff --git a/ios/chrome/browser/interstitials/ios_chrome_metrics_helper.cc b/ios/chrome/browser/interstitials/ios_chrome_metrics_helper.cc
new file mode 100644
index 0000000..88ffb69
--- /dev/null
+++ b/ios/chrome/browser/interstitials/ios_chrome_metrics_helper.cc
@@ -0,0 +1,36 @@
+// Copyright 2015 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 "ios/chrome/browser/interstitials/ios_chrome_metrics_helper.h"
+
+#include "components/history/core/browser/history_service.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/rappor/rappor_service.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/history/history_service_factory.h"
+#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/web/public/web_state/web_state.h"
+
+IOSChromeMetricsHelper::IOSChromeMetricsHelper(
+    web::WebState* web_state,
+    const GURL& request_url,
+    const security_interstitials::MetricsHelper::ReportDetails report_details)
+    : security_interstitials::MetricsHelper(
+          request_url,
+          report_details,
+          ios::HistoryServiceFactory::GetForBrowserState(
+              ios::ChromeBrowserState::FromBrowserState(
+                  web_state->GetBrowserState()),
+              ServiceAccessType::EXPLICIT_ACCESS),
+          GetApplicationContext()->GetRapporService()) {}
+
+IOSChromeMetricsHelper::~IOSChromeMetricsHelper() {}
+
+void IOSChromeMetricsHelper::RecordExtraUserDecisionMetrics(
+    security_interstitials::MetricsHelper::Decision decision) {}
+
+void IOSChromeMetricsHelper::RecordExtraUserInteractionMetrics(
+    security_interstitials::MetricsHelper::Interaction interaction) {}
+
+void IOSChromeMetricsHelper::RecordExtraShutdownMetrics() {}
diff --git a/ios/chrome/browser/interstitials/ios_chrome_metrics_helper.h b/ios/chrome/browser/interstitials/ios_chrome_metrics_helper.h
new file mode 100644
index 0000000..3bde9147
--- /dev/null
+++ b/ios/chrome/browser/interstitials/ios_chrome_metrics_helper.h
@@ -0,0 +1,42 @@
+// Copyright 2015 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 IOS_CHROME_BROWSER_INTERSTITIALS_IOS_CHROME_METRICS_HELPER_H_
+#define IOS_CHROME_BROWSER_INTERSTITIALS_IOS_CHROME_METRICS_HELPER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/security_interstitials/core/metrics_helper.h"
+#include "url/gurl.h"
+
+namespace web {
+class WebState;
+}
+
+// This class provides a concrete implementation for Chrome on iOS to the
+// security_interstitials::MetricsHelper class. Together, they record UMA,
+// Rappor, and experience sampling metrics.
+class IOSChromeMetricsHelper : public security_interstitials::MetricsHelper {
+ public:
+  IOSChromeMetricsHelper(
+      web::WebState* web_state,
+      const GURL& request_url,
+      const security_interstitials::MetricsHelper::ReportDetails
+          report_details);
+  ~IOSChromeMetricsHelper() override;
+
+ protected:
+  // security_interstitials::MetricsHelper implementation.
+  void RecordExtraUserDecisionMetrics(
+      security_interstitials::MetricsHelper::Decision decision) override;
+  void RecordExtraUserInteractionMetrics(
+      security_interstitials::MetricsHelper::Interaction interaction) override;
+  void RecordExtraShutdownMetrics() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(IOSChromeMetricsHelper);
+};
+
+#endif  // IOS_CHROME_BROWSER_INTERSTITIALS_IOS_CHROME_METRICS_HELPER_H_
diff --git a/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.cc b/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.cc
index 13f3b32d..4a0aa50 100644
--- a/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.cc
+++ b/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.cc
@@ -56,7 +56,6 @@
 scoped_ptr<syncable_prefs::PrefServiceSyncable> CreateBrowserStatePrefs(
     const base::FilePath& browser_state_path,
     base::SequencedTaskRunner* pref_io_task_runner,
-    TrackedPreferenceValidationDelegate* validation_delegate,
     const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry) {
   // chrome_prefs::CreateProfilePrefs uses ProfilePrefStoreManager to create
   // the preference store however since Chrome on iOS does not need to track
diff --git a/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.h b/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.h
index 7e4b610b..c5a8d36 100644
--- a/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.h
+++ b/ios/chrome/browser/prefs/ios_chrome_pref_service_factory.h
@@ -11,7 +11,6 @@
 class PrefRegistry;
 class PrefService;
 class PrefStore;
-class TrackedPreferenceValidationDelegate;
 
 namespace base {
 class FilePath;
@@ -43,7 +42,6 @@
 scoped_ptr<syncable_prefs::PrefServiceSyncable> CreateBrowserStatePrefs(
     const base::FilePath& browser_state_path,
     base::SequencedTaskRunner* pref_io_task_runner,
-    TrackedPreferenceValidationDelegate* validation_delegate,
     const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry);
 
 // Creates an incognito copy of |pref_service| that shares most prefs but uses
diff --git a/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.cc b/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.cc
new file mode 100644
index 0000000..78d28eb8
--- /dev/null
+++ b/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.cc
@@ -0,0 +1,153 @@
+// Copyright 2015 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 "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
+
+#include <utility>
+
+#include "base/memory/singleton.h"
+#include "base/time/time.h"
+#include "components/browser_sync/browser/profile_sync_service.h"
+#include "components/keyed_service/ios/browser_state_dependency_manager.h"
+#include "components/network_time/network_time_tracker.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "components/sync_driver/signin_manager_wrapper.h"
+#include "components/sync_driver/startup_controller.h"
+#include "components/sync_driver/sync_util.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
+#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "ios/chrome/browser/favicon/favicon_service_factory.h"
+#include "ios/chrome/browser/history/history_service_factory.h"
+#include "ios/chrome/browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
+#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
+#include "ios/chrome/browser/services/gcm/ios_chrome_gcm_profile_service_factory.h"
+#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
+#include "ios/chrome/browser/signin/about_signin_internals_factory.h"
+#include "ios/chrome/browser/signin/oauth2_token_service_factory.h"
+#include "ios/chrome/browser/signin/signin_client_factory.h"
+#include "ios/chrome/browser/signin/signin_manager_factory.h"
+#include "ios/chrome/browser/sync/ios_chrome_sync_client.h"
+#include "ios/chrome/browser/web_data_service_factory.h"
+#include "ios/chrome/common/channel_info.h"
+#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/web/public/web_thread.h"
+#include "url/gurl.h"
+
+namespace {
+
+void UpdateNetworkTimeOnUIThread(base::Time network_time,
+                                 base::TimeDelta resolution,
+                                 base::TimeDelta latency,
+                                 base::TimeTicks post_time) {
+  GetApplicationContext()->GetNetworkTimeTracker()->UpdateNetworkTime(
+      network_time, resolution, latency, post_time);
+}
+
+void UpdateNetworkTime(const base::Time& network_time,
+                       const base::TimeDelta& resolution,
+                       const base::TimeDelta& latency) {
+  web::WebThread::PostTask(
+      web::WebThread::UI, FROM_HERE,
+      base::Bind(&UpdateNetworkTimeOnUIThread, network_time, resolution,
+                 latency, base::TimeTicks::Now()));
+}
+
+}  // namespace
+
+// static
+IOSChromeProfileSyncServiceFactory*
+IOSChromeProfileSyncServiceFactory::GetInstance() {
+  return base::Singleton<IOSChromeProfileSyncServiceFactory>::get();
+}
+
+// static
+ProfileSyncService* IOSChromeProfileSyncServiceFactory::GetForBrowserState(
+    ios::ChromeBrowserState* browser_state) {
+  if (!ProfileSyncService::IsSyncAllowedByFlag())
+    return nullptr;
+
+  return static_cast<ProfileSyncService*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, true));
+}
+
+// static
+ProfileSyncService*
+IOSChromeProfileSyncServiceFactory::GetForBrowserStateIfExists(
+    ios::ChromeBrowserState* browser_state) {
+  if (!ProfileSyncService::IsSyncAllowedByFlag())
+    return nullptr;
+
+  return static_cast<ProfileSyncService*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, false));
+}
+
+IOSChromeProfileSyncServiceFactory::IOSChromeProfileSyncServiceFactory()
+    : BrowserStateKeyedServiceFactory(
+          "ProfileSyncService",
+          BrowserStateDependencyManager::GetInstance()) {
+  // The ProfileSyncService depends on various SyncableServices being around
+  // when it is shut down.  Specify those dependencies here to build the proper
+  // destruction order.
+  DependsOn(ios::AboutSigninInternalsFactory::GetInstance());
+  DependsOn(PersonalDataManagerFactory::GetInstance());
+  DependsOn(ios::BookmarkModelFactory::GetInstance());
+  DependsOn(SigninClientFactory::GetInstance());
+  DependsOn(ios::HistoryServiceFactory::GetInstance());
+  DependsOn(IOSChromeProfileInvalidationProviderFactory::GetInstance());
+  DependsOn(OAuth2TokenServiceFactory::GetInstance());
+  DependsOn(IOSChromePasswordStoreFactory::GetInstance());
+  DependsOn(ios::SigninManagerFactory::GetInstance());
+  DependsOn(ios::TemplateURLServiceFactory::GetInstance());
+  DependsOn(ios::WebDataServiceFactory::GetInstance());
+  DependsOn(ios::FaviconServiceFactory::GetInstance());
+}
+
+IOSChromeProfileSyncServiceFactory::~IOSChromeProfileSyncServiceFactory() {}
+
+scoped_ptr<KeyedService>
+IOSChromeProfileSyncServiceFactory::BuildServiceInstanceFor(
+    web::BrowserState* context) const {
+  ios::ChromeBrowserState* browser_state =
+      ios::ChromeBrowserState::FromBrowserState(context);
+
+  SigninManagerBase* signin =
+      ios::SigninManagerFactory::GetForBrowserState(browser_state);
+
+  // Always create the GCMProfileService instance such that we can listen to
+  // the profile notifications and purge the GCM store when the profile is
+  // being signed out.
+  IOSChromeGCMProfileServiceFactory::GetForBrowserState(browser_state);
+
+  // TODO(crbug.com/171406): Change AboutSigninInternalsFactory to load on
+  // startup once bug has been fixed.
+  ios::AboutSigninInternalsFactory::GetForBrowserState(browser_state);
+
+  ProfileSyncService::InitParams init_params;
+  init_params.signin_wrapper =
+      make_scoped_ptr(new SigninManagerWrapper(signin));
+  init_params.oauth2_token_service =
+      OAuth2TokenServiceFactory::GetForBrowserState(browser_state);
+  init_params.start_behavior = browser_sync::MANUAL_START;
+  init_params.sync_client =
+      make_scoped_ptr(new IOSChromeSyncClient(browser_state));
+  init_params.network_time_update_callback = base::Bind(&UpdateNetworkTime);
+  init_params.base_directory = browser_state->GetStatePath();
+  init_params.url_request_context = browser_state->GetRequestContext();
+  init_params.debug_identifier = browser_state->GetDebugName();
+  init_params.channel = ::GetChannel();
+  init_params.db_thread =
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::DB);
+  init_params.file_thread =
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE);
+  init_params.blocking_pool = web::WebThread::GetBlockingPool();
+
+  auto pss = make_scoped_ptr(new ProfileSyncService(std::move(init_params)));
+
+  // Will also initialize the sync client.
+  pss->Initialize();
+  return std::move(pss);
+}
diff --git a/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h b/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h
new file mode 100644
index 0000000..3b66d08
--- /dev/null
+++ b/ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h
@@ -0,0 +1,47 @@
+// Copyright 2015 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 IOS_CHROME_BROWSER_SYNC_IOS_CHROME_PROFILE_SYNC_SERVICE_FACTORY_H_
+#define IOS_CHROME_BROWSER_SYNC_IOS_CHROME_PROFILE_SYNC_SERVICE_FACTORY_H_
+
+#include "base/macros.h"
+#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+class ProfileSyncService;
+
+// Singleton that owns all ProfileSyncService and associates them with
+// ios::ChromeBrowserState.
+class IOSChromeProfileSyncServiceFactory
+    : public BrowserStateKeyedServiceFactory {
+ public:
+  static ProfileSyncService* GetForBrowserState(
+      ios::ChromeBrowserState* browser_state);
+
+  static ProfileSyncService* GetForBrowserStateIfExists(
+      ios::ChromeBrowserState* browser_state);
+
+  static IOSChromeProfileSyncServiceFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<
+      IOSChromeProfileSyncServiceFactory>;
+
+  IOSChromeProfileSyncServiceFactory();
+  ~IOSChromeProfileSyncServiceFactory() override;
+
+  // BrowserContextKeyedServiceFactory:
+  scoped_ptr<KeyedService> BuildServiceInstanceFor(
+      web::BrowserState* context) const override;
+};
+
+#endif  // IOS_CHROME_BROWSER_SYNC_IOS_CHROME_PROFILE_SYNC_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
new file mode 100644
index 0000000..556651f
--- /dev/null
+++ b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
@@ -0,0 +1,61 @@
+// Copyright 2015 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 "ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.h"
+
+#include "base/bind.h"
+#include "base/time/time.h"
+#include "components/browser_sync/browser/profile_sync_service_mock.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "components/sync_driver/signin_manager_wrapper.h"
+#include "ios/chrome/browser/signin/oauth2_token_service_factory.h"
+#include "ios/chrome/browser/signin/signin_manager_factory.h"
+#include "ios/chrome/browser/sync/ios_chrome_sync_client.h"
+#include "ios/chrome/common/channel_info.h"
+#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/web/public/web_thread.h"
+
+namespace {
+
+void EmptyNetworkTimeUpdate(const base::Time&,
+                            const base::TimeDelta&,
+                            const base::TimeDelta&) {}
+
+}  // namespace
+
+ProfileSyncService::InitParams CreateProfileSyncServiceParamsForTest(
+    scoped_ptr<sync_driver::SyncClient> sync_client,
+    ios::ChromeBrowserState* browser_state) {
+  ProfileSyncService::InitParams init_params;
+
+  init_params.signin_wrapper = make_scoped_ptr(new SigninManagerWrapper(
+      ios::SigninManagerFactory::GetForBrowserState(browser_state)));
+  init_params.oauth2_token_service =
+      OAuth2TokenServiceFactory::GetForBrowserState(browser_state);
+  init_params.start_behavior = browser_sync::MANUAL_START;
+  init_params.sync_client =
+      sync_client ? std::move(sync_client)
+                  : make_scoped_ptr(new IOSChromeSyncClient(browser_state));
+  init_params.network_time_update_callback =
+      base::Bind(&EmptyNetworkTimeUpdate);
+  init_params.base_directory = browser_state->GetStatePath();
+  init_params.url_request_context = browser_state->GetRequestContext();
+  init_params.debug_identifier = browser_state->GetDebugName();
+  init_params.channel = ::GetChannel();
+  init_params.db_thread =
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::DB);
+  init_params.file_thread =
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE);
+  init_params.blocking_pool = web::WebThread::GetBlockingPool();
+
+  return init_params;
+}
+
+scoped_ptr<KeyedService> BuildMockProfileSyncService(
+    web::BrowserState* context) {
+  return make_scoped_ptr(
+      new ProfileSyncServiceMock(CreateProfileSyncServiceParamsForTest(
+          nullptr, ios::ChromeBrowserState::FromBrowserState(context))));
+}
diff --git a/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.h b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.h
new file mode 100644
index 0000000..4968ff81
--- /dev/null
+++ b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.h
@@ -0,0 +1,34 @@
+// Copyright 2015 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 IOS_CHROME_BROWSER_SYNC_IOS_CHROME_PROFILE_SYNC_TEST_UTIL_H_
+#define IOS_CHROME_BROWSER_SYNC_IOS_CHROME_PROFILE_SYNC_TEST_UTIL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "components/browser_sync/browser/profile_sync_service.h"
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+namespace sync_driver {
+class SyncClient;
+}
+
+namespace web {
+class BrowserState;
+}
+
+// Helper method for constructing ProfileSyncService mocks. If |sync_client|
+// is null, a fresh one is created.
+ProfileSyncService::InitParams CreateProfileSyncServiceParamsForTest(
+    scoped_ptr<sync_driver::SyncClient> sync_client,
+    ios::ChromeBrowserState* browser_state);
+
+// Helper routine to be used in conjunction with
+// BrowserStateKeyedServiceFactory::SetTestingFactory().
+scoped_ptr<KeyedService> BuildMockProfileSyncService(
+    web::BrowserState* context);
+
+#endif  // IOS_CHROME_BROWSER_SYNC_IOS_CHROME_PROFILE_SYNC_TEST_UTIL_H_
diff --git a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
index 1aefa98..1c22a77 100644
--- a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
@@ -143,7 +143,7 @@
     content::RenderFrameHost* rfh,
     const std::vector<FormStructure*>& forms) {
   if (password_generation_manager_) {
-    password_generation_manager_->DetectAccountCreationForms(forms);
+    password_generation_manager_->DetectFormsEligibleForGeneration(forms);
   }
 }
 
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp
index 5f744bb..df44d510 100644
--- a/ios/chrome/ios_chrome.gyp
+++ b/ios/chrome/ios_chrome.gyp
@@ -89,6 +89,7 @@
         '../../components/components.gyp:rappor',
         '../../components/components.gyp:search',
         '../../components/components.gyp:search_engines',
+        '../../components/components.gyp:security_interstitials_core',
         '../../components/components.gyp:sessions_ios',
         '../../components/components.gyp:signin_core_browser',
         '../../components/components.gyp:signin_core_common',
@@ -185,6 +186,8 @@
         'browser/bookmarks/bookmarks_utils.h',
         'browser/bookmarks/startup_task_runner_service_factory.cc',
         'browser/bookmarks/startup_task_runner_service_factory.h',
+        'browser/browser_state/bookmark_model_loaded_observer.cc',
+        'browser/browser_state/bookmark_model_loaded_observer.h',
         'browser/browser_state/browser_state_info_cache.cc',
         'browser/browser_state/browser_state_info_cache.h',
         'browser/browser_state/browser_state_info_cache_observer.h',
@@ -321,6 +324,8 @@
         'browser/install_time_util.mm',
         'browser/installation_notifier.h',
         'browser/installation_notifier.mm',
+        'browser/interstitials/ios_chrome_metrics_helper.cc',
+        'browser/interstitials/ios_chrome_metrics_helper.h',
         'browser/invalidation/ios_chrome_profile_invalidation_provider_factory.cc',
         'browser/invalidation/ios_chrome_profile_invalidation_provider_factory.h',
         'browser/ios_chrome_field_trials.cc',
@@ -473,6 +478,8 @@
         'browser/suggestions/suggestions_service_factory.mm',
         'browser/sync/glue/sync_start_util.cc',
         'browser/sync/glue/sync_start_util.h',
+        'browser/sync/ios_chrome_profile_sync_service_factory.cc',
+        'browser/sync/ios_chrome_profile_sync_service_factory.h',
         'browser/sync/ios_chrome_sync_client.cc',
         'browser/sync/ios_chrome_sync_client.h',
         'browser/sync/ios_chrome_synced_tab_delegate.cc',
diff --git a/ios/chrome/ios_chrome_tests.gyp b/ios/chrome/ios_chrome_tests.gyp
index 3fca9b9..4c1e1cb 100644
--- a/ios/chrome/ios_chrome_tests.gyp
+++ b/ios/chrome/ios_chrome_tests.gyp
@@ -112,6 +112,8 @@
         'browser/signin/fake_oauth2_token_service_builder.h',
         'browser/signin/fake_signin_manager_builder.cc',
         'browser/signin/fake_signin_manager_builder.h',
+        'browser/sync/ios_chrome_profile_sync_test_util.cc',
+        'browser/sync/ios_chrome_profile_sync_test_util.h',
         'browser/sync/sync_setup_service_mock.cc',
         'browser/sync/sync_setup_service_mock.h',
         'test/block_cleanup_test.h',
diff --git a/ios/web/navigation/navigation_manager_impl.h b/ios/web/navigation/navigation_manager_impl.h
index 3ac47d2..1f88237 100644
--- a/ios/web/navigation/navigation_manager_impl.h
+++ b/ios/web/navigation/navigation_manager_impl.h
@@ -69,11 +69,6 @@
   void OnNavigationItemChanged();
   void OnNavigationItemCommitted();
 
-  // Returns the transient item if any. This is an item which is removed and
-  // discarded if any navigation occurs. Note that the returned item is owned
-  // by the navigation manager and may be deleted at any time.
-  NavigationItem* GetTransientItem() const;
-
   // Temporary accessors and content/ class pass-throughs.
   // TODO(stuartmorgan): Re-evaluate this list once the refactorings have
   // settled down.
@@ -106,6 +101,7 @@
   NavigationItem* GetVisibleItem() const override;
   NavigationItem* GetLastCommittedItem() const override;
   NavigationItem* GetPendingItem() const override;
+  NavigationItem* GetTransientItem() const override;
   void DiscardNonCommittedItems() override;
   void LoadIfNecessary() override;
   void AddTransientURLRewriter(
diff --git a/ios/web/navigation/navigation_manager_impl.mm b/ios/web/navigation/navigation_manager_impl.mm
index db2c22b..50dcad4b 100644
--- a/ios/web/navigation/navigation_manager_impl.mm
+++ b/ios/web/navigation/navigation_manager_impl.mm
@@ -134,10 +134,19 @@
   return [entry navigationItem];
 }
 
+NavigationItem* NavigationManagerImpl::GetLastCommittedItem() const {
+  CRWSessionEntry* entry = [session_controller_ lastCommittedEntry];
+  return [entry navigationItem];
+}
+
 NavigationItem* NavigationManagerImpl::GetPendingItem() const {
   return [[session_controller_ pendingEntry] navigationItem];
 }
 
+NavigationItem* NavigationManagerImpl::GetTransientItem() const {
+  return [[session_controller_ transientEntry] navigationItem];
+}
+
 void NavigationManagerImpl::DiscardNonCommittedItems() {
   [session_controller_ discardNonCommittedEntries];
 }
@@ -146,15 +155,6 @@
   // Nothing to do; iOS loads lazily.
 }
 
-NavigationItem* NavigationManagerImpl::GetTransientItem() const {
-  return [[session_controller_ transientEntry] navigationItem];
-}
-
-NavigationItem* NavigationManagerImpl::GetLastCommittedItem() const {
-  CRWSessionEntry* entry = [session_controller_ lastCommittedEntry];
-  return [entry navigationItem];
-}
-
 int NavigationManagerImpl::GetLastCommittedEntryIndex() const {
   if (![[session_controller_ entries] count])
     return -1;
diff --git a/ios/web/public/navigation_manager.h b/ios/web/public/navigation_manager.h
index 1798197d..71b6551f 100644
--- a/ios/web/public/navigation_manager.h
+++ b/ios/web/public/navigation_manager.h
@@ -42,6 +42,11 @@
   // currently in progress, or null if there is none.
   virtual NavigationItem* GetPendingItem() const = 0;
 
+  // Returns the transient item if any. This is an item which is removed and
+  // discarded if any navigation occurs. Note that the returned item is owned
+  // by the navigation manager and may be deleted at any time.
+  virtual NavigationItem* GetTransientItem() const = 0;
+
   // Removes the transient and pending NavigationItems.
   virtual void DiscardNonCommittedItems() = 0;
 
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 65f731e..b0942bd 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -134,6 +134,7 @@
   ArcInstanceHostMsgStart,
   DistillerMsgStart,
   StartupMetricMsgStart,
+  DWriteFontProxyMsgStart,
   LastIPCMsgStart  // Must come last.
 };
 
diff --git a/media/BUILD.gn b/media/BUILD.gn
index d53cb64..1c2a73f 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -396,15 +396,6 @@
       "//media/base/android:video_capture_jni_headers",
     ]
 
-    # Only 64 bit builds are using android-21 NDK library, check common.gypi
-    if (current_cpu == "arm64" || current_cpu == "x64" ||
-        current_cpu == "mips64el") {
-      sources += [
-        "base/android/ndk_media_codec_bridge.cc",
-        "base/android/ndk_media_codec_bridge.h",
-      ]
-      libs += [ "-lmediandk" ]
-    }
     allow_circular_includes_from = [ "//media/base/android" ]
   }
 
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc
index 4db77c05..fce679cc 100644
--- a/media/audio/win/core_audio_util_win.cc
+++ b/media/audio/win/core_audio_util_win.cc
@@ -146,6 +146,10 @@
   return device_id;
 }
 
+static bool IsDefaultDeviceId(const std::string& device_id) {
+  return device_id.empty() || device_id == AudioManagerBase::kDefaultDeviceId;
+}
+
 static bool IsDeviceActive(IMMDevice* device) {
   DWORD state = DEVICE_STATE_DISABLED;
   return SUCCEEDED(device->GetState(&state)) && (state & DEVICE_STATE_ACTIVE);
@@ -438,8 +442,7 @@
     return AudioManagerBase::kCommunicationsDeviceId;
 
   ScopedComPtr<IMMDevice> input_device;
-  if (input_device_id.empty() ||
-      input_device_id == AudioManagerBase::kDefaultDeviceId) {
+  if (IsDefaultDeviceId(input_device_id)) {
     input_device = CreateDefaultDevice(eCapture, eConsole);
   } else {
     input_device = CreateDevice(input_device_id);
@@ -547,7 +550,7 @@
 
 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient(
     const std::string& device_id, EDataFlow data_flow, ERole role) {
-  if (device_id.empty())
+  if (IsDefaultDeviceId(device_id))
     return CreateDefaultClient(data_flow, role);
 
   ScopedComPtr<IMMDevice> device(CreateDevice(device_id));
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index 75c6717c..c51ee6b 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -31,8 +31,6 @@
     "media_codec_decoder.h",
     "media_codec_player.cc",
     "media_codec_player.h",
-    "media_codec_util.cc",
-    "media_codec_util.h",
     "media_codec_video_decoder.cc",
     "media_codec_video_decoder.h",
     "media_decoder_job.cc",
@@ -60,8 +58,6 @@
     "media_task_runner.h",
     "media_url_interceptor.h",
     "provision_fetcher.h",
-    "sdk_media_codec_bridge.cc",
-    "sdk_media_codec_bridge.h",
     "video_decoder_job.cc",
     "video_decoder_job.h",
     "webaudio_media_codec_bridge.cc",
@@ -85,12 +81,12 @@
   testonly = true
   sources = [
     "access_unit_queue_unittest.cc",
+    "media_codec_bridge_unittest.cc",
     "media_codec_decoder_unittest.cc",
     "media_codec_player_unittest.cc",
     "media_drm_bridge_unittest.cc",
     "media_player_bridge_unittest.cc",
     "media_source_player_unittest.cc",
-    "sdk_media_codec_bridge_unittest.cc",
     "test_data_factory.cc",
     "test_data_factory.h",
     "test_statistics.h",
@@ -110,7 +106,6 @@
     "java/src/org/chromium/media/AudioManagerAndroid.java",
     "java/src/org/chromium/media/AudioRecordInput.java",
     "java/src/org/chromium/media/MediaCodecBridge.java",
-    "java/src/org/chromium/media/MediaCodecUtil.java",
     "java/src/org/chromium/media/MediaDrmBridge.java",
     "java/src/org/chromium/media/MediaPlayerBridge.java",
     "java/src/org/chromium/media/MediaPlayerListener.java",
diff --git a/media/base/android/audio_decoder_job.cc b/media/base/android/audio_decoder_job.cc
index 3cf2c5f9a..66c6a60 100644
--- a/media/base/android/audio_decoder_job.cc
+++ b/media/base/android/audio_decoder_job.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/threading/thread.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/audio_timestamp_helper.h"
 #include "media/base/timestamp_constants.h"
 
@@ -161,12 +161,10 @@
   if (!media_codec_bridge_)
     return STATUS_FAILURE;
 
-  if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
-           ->ConfigureAndStart(audio_codec_, config_sampling_rate_,
-                               num_channels_, &audio_extra_data_[0],
-                               audio_extra_data_.size(), audio_codec_delay_ns_,
-                               audio_seek_preroll_ns_, true,
-                               GetMediaCrypto())) {
+  if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))->Start(
+      audio_codec_, config_sampling_rate_, num_channels_, &audio_extra_data_[0],
+      audio_extra_data_.size(), audio_codec_delay_ns_, audio_seek_preroll_ns_,
+      true, GetMediaCrypto())) {
     media_codec_bridge_.reset();
     return STATUS_FAILURE;
   }
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
index 3a62582..72c3964 100644
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -22,6 +22,9 @@
 import org.chromium.base.annotations.JNINamespace;
 
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * A wrapper of the MediaCodec class to facilitate exception capturing and
@@ -44,6 +47,10 @@
     private static final int MEDIA_CODEC_ABORT = 8;
     private static final int MEDIA_CODEC_ERROR = 9;
 
+    // Codec direction.  Keep this in sync with media_codec_bridge.h.
+    private static final int MEDIA_CODEC_DECODER = 0;
+    private static final int MEDIA_CODEC_ENCODER = 1;
+
     // Max adaptive playback size to be supplied to the decoder.
     private static final int MAX_ADAPTIVE_PLAYBACK_WIDTH = 1920;
     private static final int MAX_ADAPTIVE_PLAYBACK_HEIGHT = 1080;
@@ -93,6 +100,37 @@
         }
     }
 
+    /**
+     * This class represents supported android codec information.
+     */
+    private static class CodecInfo {
+        private final String mCodecType;  // e.g. "video/x-vnd.on2.vp8".
+        private final String mCodecName;  // e.g. "OMX.google.vp8.decoder".
+        private final int mDirection;
+
+        private CodecInfo(String codecType, String codecName,
+                          int direction) {
+            mCodecType = codecType;
+            mCodecName = codecName;
+            mDirection = direction;
+        }
+
+        @CalledByNative("CodecInfo")
+        private String codecType() {
+            return mCodecType;
+        }
+
+        @CalledByNative("CodecInfo")
+        private String codecName() {
+            return mCodecName;
+        }
+
+        @CalledByNative("CodecInfo")
+        private int direction() {
+            return mDirection;
+        }
+    }
+
     private static class DequeueOutputResult {
         private final int mStatus;
         private final int mIndex;
@@ -142,6 +180,105 @@
         }
     }
 
+    /**
+     * Get a list of supported android codec mimes.
+     */
+    @SuppressWarnings("deprecation")
+    @CalledByNative
+    private static CodecInfo[] getCodecsInfo() {
+        // Return the first (highest-priority) codec for each MIME type.
+        Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>();
+        Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>();
+        int count = MediaCodecList.getCodecCount();
+        for (int i = 0; i < count; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+            int direction =
+                    info.isEncoder() ? MEDIA_CODEC_ENCODER : MEDIA_CODEC_DECODER;
+            String codecString = info.getName();
+            String[] supportedTypes = info.getSupportedTypes();
+            for (int j = 0; j < supportedTypes.length; ++j) {
+                Map<String, CodecInfo> map = info.isEncoder() ? encoderInfoMap : decoderInfoMap;
+                if (!map.containsKey(supportedTypes[j])) {
+                    map.put(supportedTypes[j], new CodecInfo(
+                            supportedTypes[j], codecString, direction));
+                }
+            }
+        }
+        ArrayList<CodecInfo> codecInfos = new ArrayList<CodecInfo>(
+                decoderInfoMap.size() + encoderInfoMap.size());
+        codecInfos.addAll(encoderInfoMap.values());
+        codecInfos.addAll(decoderInfoMap.values());
+        return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
+    }
+
+    /**
+     * Get a name of default android codec.
+     */
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+    @SuppressWarnings("deprecation")
+    @CalledByNative
+    private static String getDefaultCodecName(String mime, int direction) {
+        String codecName = "";
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            try {
+                MediaCodec mediaCodec = null;
+                if (direction == MEDIA_CODEC_ENCODER) {
+                    mediaCodec = MediaCodec.createEncoderByType(mime);
+                } else {
+                    mediaCodec = MediaCodec.createDecoderByType(mime);
+                }
+                codecName = mediaCodec.getName();
+                mediaCodec.release();
+            } catch (Exception e) {
+                Log.w(TAG, "getDefaultCodecName: Failed to create MediaCodec: %s, direction: %d",
+                        mime, direction, e);
+            }
+        }
+        return codecName;
+    }
+
+    /**
+     * Get a list of encoder supported color formats for specified mime type.
+     */
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @SuppressWarnings("deprecation")
+    @CalledByNative
+    private static int[] getEncoderColorFormatsForMime(String mime) {
+        MediaCodecInfo[] codecs = null;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
+            codecs = mediaCodecList.getCodecInfos();
+        } else {
+            int count = MediaCodecList.getCodecCount();
+            if (count <= 0) {
+                return null;
+            }
+            codecs = new MediaCodecInfo[count];
+            for (int i = 0; i < count; ++i) {
+                MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+                codecs[i] = info;
+            }
+        }
+
+        for (int i = 0; i < codecs.length; i++) {
+            if (!codecs[i].isEncoder()) {
+                continue;
+            }
+
+            String[] supportedTypes = codecs[i].getSupportedTypes();
+            for (int j = 0; j < supportedTypes.length; ++j) {
+                if (!supportedTypes[j].equalsIgnoreCase(mime)) {
+                    continue;
+                }
+
+                MediaCodecInfo.CodecCapabilities capabilities =
+                        codecs[i].getCapabilitiesForType(mime);
+                return capabilities.colorFormats;
+            }
+        }
+        return null;
+    }
+
     @SuppressWarnings("deprecation")
     private static String getDecoderNameForMime(String mime) {
         int count = MediaCodecList.getCodecCount();
@@ -184,9 +321,8 @@
         boolean adaptivePlaybackSupported = false;
         try {
             // |isSecure| only applies to video decoders.
-            if (mime.startsWith("video") && isSecure
-                    && direction == MediaCodecUtil.MEDIA_CODEC_DECODER) {
-                String decoderName = MediaCodecUtil.getDecoderNameForMime(mime);
+            if (mime.startsWith("video") && isSecure && direction == MEDIA_CODEC_DECODER) {
+                String decoderName = getDecoderNameForMime(mime);
                 if (decoderName == null) {
                     return null;
                 }
@@ -200,7 +336,7 @@
                 }
                 mediaCodec = MediaCodec.createByCodecName(decoderName + ".secure");
             } else {
-                if (direction == MediaCodecUtil.MEDIA_CODEC_ENCODER) {
+                if (direction == MEDIA_CODEC_ENCODER) {
                     mediaCodec = MediaCodec.createEncoderByType(mime);
                 } else {
                     mediaCodec = MediaCodec.createDecoderByType(mime);
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java
deleted file mode 100644
index b498b29..0000000
--- a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2015 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.media;
-
-import android.annotation.TargetApi;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
-import android.os.Build;
-
-import org.chromium.base.Log;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A collection of MediaCodec utility functions.
- */
-@JNINamespace("media")
-class MediaCodecUtil {
-    private static final String TAG = "MediaCodecUtil";
-
-    // Codec direction.  Keep this in sync with media_codec_bridge.h.
-    static final int MEDIA_CODEC_DECODER = 0;
-    static final int MEDIA_CODEC_ENCODER = 1;
-
-    /**
-     * This class represents supported android codec information.
-     */
-    private static class CodecInfo {
-        private final String mCodecType; // e.g. "video/x-vnd.on2.vp8".
-        private final String mCodecName; // e.g. "OMX.google.vp8.decoder".
-        private final int mDirection;
-
-        private CodecInfo(String codecType, String codecName, int direction) {
-            mCodecType = codecType;
-            mCodecName = codecName;
-            mDirection = direction;
-        }
-
-        @CalledByNative("CodecInfo")
-        private String codecType() {
-            return mCodecType;
-        }
-
-        @CalledByNative("CodecInfo")
-        private String codecName() {
-            return mCodecName;
-        }
-
-        @CalledByNative("CodecInfo")
-        private int direction() {
-            return mDirection;
-        }
-    }
-
-    /**
-     * @return a list of supported android codec information.
-     */
-    @SuppressWarnings("deprecation")
-    @CalledByNative
-    private static CodecInfo[] getCodecsInfo() {
-        // Return the first (highest-priority) codec for each MIME type.
-        Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>();
-        Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>();
-        int count = MediaCodecList.getCodecCount();
-        for (int i = 0; i < count; ++i) {
-            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-            int direction = info.isEncoder() ? MEDIA_CODEC_ENCODER : MEDIA_CODEC_DECODER;
-            String codecString = info.getName();
-            String[] supportedTypes = info.getSupportedTypes();
-            for (int j = 0; j < supportedTypes.length; ++j) {
-                Map<String, CodecInfo> map = info.isEncoder() ? encoderInfoMap : decoderInfoMap;
-                if (!map.containsKey(supportedTypes[j])) {
-                    map.put(supportedTypes[j],
-                            new CodecInfo(supportedTypes[j], codecString, direction));
-                }
-            }
-        }
-        ArrayList<CodecInfo> codecInfos =
-                new ArrayList<CodecInfo>(decoderInfoMap.size() + encoderInfoMap.size());
-        codecInfos.addAll(encoderInfoMap.values());
-        codecInfos.addAll(decoderInfoMap.values());
-        return codecInfos.toArray(new CodecInfo[codecInfos.size()]);
-    }
-
-    /**
-     * Get a name of default android codec.
-     * @param mime MIME type of the media.
-     * @param direction Whether this is encoder or decoder.
-     * @return name of the codec.
-     */
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
-    @SuppressWarnings("deprecation")
-    @CalledByNative
-    private static String getDefaultCodecName(String mime, int direction) {
-        String codecName = "";
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-            try {
-                MediaCodec mediaCodec = null;
-                if (direction == MEDIA_CODEC_ENCODER) {
-                    mediaCodec = MediaCodec.createEncoderByType(mime);
-                } else {
-                    mediaCodec = MediaCodec.createDecoderByType(mime);
-                }
-                codecName = mediaCodec.getName();
-                mediaCodec.release();
-            } catch (Exception e) {
-                Log.w(TAG, "getDefaultCodecName: Failed to create MediaCodec: %s, direction: %d",
-                        mime, direction, e);
-            }
-        }
-        return codecName;
-    }
-
-    /**
-     * Get a list of encoder supported color formats for specified MIME type.
-     * @param mime MIME type of the media format.
-     * @return a list of encoder supported color formats.
-     */
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    @SuppressWarnings("deprecation")
-    @CalledByNative
-    private static int[] getEncoderColorFormatsForMime(String mime) {
-        MediaCodecInfo[] codecs = null;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
-            codecs = mediaCodecList.getCodecInfos();
-        } else {
-            int count = MediaCodecList.getCodecCount();
-            if (count <= 0) {
-                return null;
-            }
-            codecs = new MediaCodecInfo[count];
-            for (int i = 0; i < count; ++i) {
-                MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-                codecs[i] = info;
-            }
-        }
-
-        for (int i = 0; i < codecs.length; i++) {
-            if (!codecs[i].isEncoder()) {
-                continue;
-            }
-
-            String[] supportedTypes = codecs[i].getSupportedTypes();
-            for (int j = 0; j < supportedTypes.length; ++j) {
-                if (!supportedTypes[j].equalsIgnoreCase(mime)) {
-                    continue;
-                }
-
-                MediaCodecInfo.CodecCapabilities capabilities =
-                        codecs[i].getCapabilitiesForType(mime);
-                return capabilities.colorFormats;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Get decoder name for the input MIME type.
-     * @param mime MIME type of the media.
-     * @return name of the decoder.
-     */
-    @SuppressWarnings("deprecation")
-    protected static String getDecoderNameForMime(String mime) {
-        int count = MediaCodecList.getCodecCount();
-        for (int i = 0; i < count; ++i) {
-            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-            if (info.isEncoder()) {
-                continue;
-            }
-
-            String[] supportedTypes = info.getSupportedTypes();
-            for (int j = 0; j < supportedTypes.length; ++j) {
-                if (supportedTypes[j].equalsIgnoreCase(mime)) {
-                    return info.getName();
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Check if a given MIME type can be decoded.
-     * @param mime MIME type of the media.
-     * @param secure Whether secure decoder is required.
-     * @return true if system is able to decode, or false otherwise.
-     */
-    @CalledByNative
-    private static boolean canDecode(String mime, boolean isSecure) {
-        // Creation of ".secure" codecs sometimes crash instead of throwing exceptions
-        // on pre-JBMR2 devices.
-        if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
-            return false;
-        }
-        MediaCodec mediaCodec = null;
-        try {
-            // |isSecure| only applies to video decoders.
-            if (mime.startsWith("video") && isSecure) {
-                String decoderName = getDecoderNameForMime(mime);
-                if (decoderName == null) return false;
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-                    // To work around an issue that we cannot get the codec info from the secure
-                    // decoder, create an insecure decoder first so that we can query its codec
-                    // info. http://b/15587335.
-                    MediaCodec insecureCodec = MediaCodec.createByCodecName(decoderName);
-                    insecureCodec.release();
-                }
-                mediaCodec = MediaCodec.createByCodecName(decoderName + ".secure");
-            } else {
-                mediaCodec = MediaCodec.createDecoderByType(mime);
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Failed to create MediaCodec: %s, isSecure: %s", mime, isSecure, e);
-        }
-
-        if (mediaCodec == null) return false;
-        try {
-            mediaCodec.release();
-        } catch (IllegalStateException e) {
-            Log.e(TAG, "Cannot release media codec", e);
-        }
-        return true;
-    }
-}
diff --git a/media/base/android/media_codec_audio_decoder.cc b/media/base/android/media_codec_audio_decoder.cc
index f68a07e..4b8a076 100644
--- a/media/base/android/media_codec_audio_decoder.cc
+++ b/media/base/android/media_codec_audio_decoder.cc
@@ -6,8 +6,8 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_statistics.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/audio_timestamp_helper.h"
 #include "media/base/demuxer_stream.h"
 
@@ -144,11 +144,16 @@
     return kConfigFailure;
 
   if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
-           ->ConfigureAndStart(
-               configs_.audio_codec, configs_.audio_sampling_rate,
-               configs_.audio_channels, &configs_.audio_extra_data[0],
-               configs_.audio_extra_data.size(), configs_.audio_codec_delay_ns,
-               configs_.audio_seek_preroll_ns, true, media_crypto)) {
+           ->Start(
+               configs_.audio_codec,
+               configs_.audio_sampling_rate,
+               configs_.audio_channels,
+               &configs_.audio_extra_data[0],
+               configs_.audio_extra_data.size(),
+               configs_.audio_codec_delay_ns,
+               configs_.audio_seek_preroll_ns,
+               true,
+               media_crypto)) {
     DVLOG(0) << class_name() << "::" << __FUNCTION__
              << " failed: cannot start audio codec";
 
diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc
index 6ca7e48..9acec214 100644
--- a/media/base/android/media_codec_bridge.cc
+++ b/media/base/android/media_codec_bridge.cc
@@ -5,13 +5,20 @@
 #include "media/base/android/media_codec_bridge.h"
 
 #include <algorithm>
+#include <limits>
 
 #include "base/android/build_info.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
+#include "base/basictypes.h"
+#include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "jni/MediaCodecBridge_jni.h"
+#include "media/base/bit_reader.h"
 #include "media/base/decrypt_config.h"
 
 using base::android::AttachCurrentThread;
@@ -20,11 +27,321 @@
 using base::android::JavaIntArrayToIntVector;
 using base::android::ScopedJavaLocalRef;
 
+#define RETURN_ON_ERROR(condition)                          \
+  do {                                                           \
+    if (!(condition)) {                                          \
+      LOG(ERROR) << "Unable to parse AAC header: " #condition; \
+      return false;                                              \
+    }                                                            \
+  } while (0)
+
 namespace media {
 
-MediaCodecBridge::MediaCodecBridge() {}
+enum {
+  kBufferFlagSyncFrame = 1,    // BUFFER_FLAG_SYNC_FRAME
+  kBufferFlagEndOfStream = 4,  // BUFFER_FLAG_END_OF_STREAM
+  kConfigureFlagEncode = 1,    // CONFIGURE_FLAG_ENCODE
+};
 
-MediaCodecBridge::~MediaCodecBridge() {}
+static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
+  switch (codec) {
+    case kCodecMP3:
+      return "audio/mpeg";
+    case kCodecVorbis:
+      return "audio/vorbis";
+    case kCodecOpus:
+      return "audio/opus";
+    case kCodecAAC:
+      return "audio/mp4a-latm";
+    default:
+      return std::string();
+  }
+}
+
+static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
+  switch (codec) {
+    case kCodecH264:
+      return "video/avc";
+    case kCodecHEVC:
+      return "video/hevc";
+    case kCodecVP8:
+      return "video/x-vnd.on2.vp8";
+    case kCodecVP9:
+      return "video/x-vnd.on2.vp9";
+    default:
+      return std::string();
+  }
+}
+
+static const std::string CodecTypeToAndroidMimeType(const std::string& codec) {
+  // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"?
+  if (codec == "avc1")
+    return "video/avc";
+  if (codec == "hvc1")
+    return "video/hevc";
+  if (codec == "mp4a")
+    return "audio/mp4a-latm";
+  if (codec == "vp8" || codec == "vp8.0")
+    return "video/x-vnd.on2.vp8";
+  if (codec == "vp9" || codec == "vp9.0")
+    return "video/x-vnd.on2.vp9";
+  if (codec == "vorbis")
+    return "audio/vorbis";
+  if (codec == "opus")
+    return "audio/opus";
+  return std::string();
+}
+
+// TODO(qinmin): using a map to help all the conversions in this class.
+static const std::string AndroidMimeTypeToCodecType(const std::string& mime) {
+  if (mime == "video/mp4v-es")
+    return "mp4v";
+  if (mime == "video/avc")
+    return "avc1";
+  if (mime == "video/hevc")
+    return "hvc1";
+  if (mime == "video/x-vnd.on2.vp8")
+    return "vp8";
+  if (mime == "video/x-vnd.on2.vp9")
+    return "vp9";
+  if (mime == "audio/mp4a-latm")
+    return "mp4a";
+  if (mime == "audio/mpeg")
+    return "mp3";
+  if (mime == "audio/vorbis")
+    return "vorbis";
+  if (mime == "audio/opus")
+    return "opus";
+  return std::string();
+}
+
+static ScopedJavaLocalRef<jintArray>
+ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) {
+  ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
+  env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
+  return j_array;
+}
+
+// static
+bool MediaCodecBridge::IsAvailable() {
+  // MediaCodec is only available on JB and greater.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() < 16)
+    return false;
+  // Blacklist some devices on Jellybean as for MediaCodec support is buggy.
+  // http://crbug.com/365494.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) {
+    std::string model(base::android::BuildInfo::GetInstance()->model());
+    return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000";
+  }
+  return true;
+}
+
+// static
+bool MediaCodecBridge::SupportsSetParameters() {
+  // MediaCodec.setParameters() is only available starting with K.
+  return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
+}
+
+// static
+bool MediaCodecBridge::SupportsGetName() {
+  // MediaCodec.getName() is only available on JB MR2 and greater.
+  return base::android::BuildInfo::GetInstance()->sdk_int() >= 18;
+}
+
+// static
+std::vector<MediaCodecBridge::CodecsInfo> MediaCodecBridge::GetCodecsInfo() {
+  std::vector<CodecsInfo> codecs_info;
+  if (!IsAvailable())
+    return codecs_info;
+
+  JNIEnv* env = AttachCurrentThread();
+  std::string mime_type;
+  ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
+      Java_MediaCodecBridge_getCodecsInfo(env);
+  jsize len = env->GetArrayLength(j_codec_info_array.obj());
+  for (jsize i = 0; i < len; ++i) {
+    ScopedJavaLocalRef<jobject> j_info(
+        env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
+    ScopedJavaLocalRef<jstring> j_codec_type =
+        Java_CodecInfo_codecType(env, j_info.obj());
+    ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
+    ScopedJavaLocalRef<jstring> j_codec_name =
+        Java_CodecInfo_codecName(env, j_info.obj());
+    CodecsInfo info;
+    info.codecs = AndroidMimeTypeToCodecType(mime_type);
+    ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
+    info.direction = static_cast<MediaCodecDirection>(
+        Java_CodecInfo_direction(env, j_info.obj()));
+    codecs_info.push_back(info);
+  }
+  return codecs_info;
+}
+
+// static
+std::string MediaCodecBridge::GetDefaultCodecName(
+    const std::string& mime_type,
+    MediaCodecDirection direction) {
+  if (!IsAvailable())
+    return std::string();
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
+  ScopedJavaLocalRef<jstring> j_codec_name =
+      Java_MediaCodecBridge_getDefaultCodecName(env, j_mime.obj(), direction);
+  return ConvertJavaStringToUTF8(env, j_codec_name.obj());
+}
+
+// static
+std::set<int> MediaCodecBridge::GetEncoderColorFormats(
+    const std::string& mime_type) {
+  std::set<int> color_formats;
+  if (!IsAvailable())
+    return color_formats;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
+  ScopedJavaLocalRef<jintArray> j_color_format_array =
+      Java_MediaCodecBridge_getEncoderColorFormatsForMime(env, j_mime.obj());
+
+  if (j_color_format_array.obj()) {
+    std::vector<int> formats;
+    JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats);
+    color_formats = std::set<int>(formats.begin(), formats.end());
+  }
+
+  return color_formats;
+}
+
+// static
+bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) {
+  if (!IsAvailable())
+    return false;
+
+  JNIEnv* env = AttachCurrentThread();
+  std::string mime = CodecTypeToAndroidMimeType(codec);
+  if (mime.empty())
+    return false;
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  ScopedJavaLocalRef<jobject> j_media_codec_bridge =
+      Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, false);
+  if (!j_media_codec_bridge.is_null()) {
+    Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj());
+    return true;
+  }
+  return false;
+}
+
+// static
+bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type,
+                                            MediaCodecDirection direction) {
+  if (!IsAvailable())
+    return true;
+
+  std::string codec_name;
+  if (SupportsGetName()) {
+    codec_name = GetDefaultCodecName(mime_type, direction);
+  } else {
+    std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
+    std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info =
+        MediaCodecBridge::GetCodecsInfo();
+    for (size_t i = 0; i < codecs_info.size(); ++i) {
+      if (codecs_info[i].codecs == codec_type &&
+          codecs_info[i].direction == direction) {
+        codec_name = codecs_info[i].name;
+        break;
+      }
+    }
+  }
+  DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type <<
+      " : " << codec_name;
+  // It would be nice if MediaCodecInfo externalized some notion of
+  // HW-acceleration but it doesn't. Android Media guidance is that the
+  // "OMX.google" prefix is always used for SW decoders, so that's what we
+  // use. "OMX.SEC.*" codec is Samsung software implementation - report it
+  // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek
+  // devices while HW decoder video freezes and distortions are
+  // investigated - http://crbug.com/446974.
+  if (codec_name.length() > 0) {
+    return (base::StartsWith(codec_name, "OMX.google.",
+                             base::CompareCase::SENSITIVE) ||
+            base::StartsWith(codec_name, "OMX.SEC.",
+                             base::CompareCase::SENSITIVE) ||
+            base::StartsWith(codec_name, "OMX.MTK.",
+                             base::CompareCase::SENSITIVE) ||
+            base::StartsWith(codec_name, "OMX.Exynos.",
+                             base::CompareCase::SENSITIVE));
+  }
+  return true;
+}
+
+MediaCodecBridge::MediaCodecBridge(const std::string& mime,
+                                   bool is_secure,
+                                   MediaCodecDirection direction) {
+  JNIEnv* env = AttachCurrentThread();
+  CHECK(env);
+  DCHECK(!mime.empty());
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  j_media_codec_.Reset(
+      Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction));
+}
+
+MediaCodecBridge::~MediaCodecBridge() {
+  JNIEnv* env = AttachCurrentThread();
+  CHECK(env);
+  if (j_media_codec_.obj())
+    Java_MediaCodecBridge_release(env, j_media_codec_.obj());
+}
+
+bool MediaCodecBridge::StartInternal() {
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_start(env, j_media_codec_.obj());
+}
+
+MediaCodecStatus MediaCodecBridge::Reset() {
+  JNIEnv* env = AttachCurrentThread();
+  return static_cast<MediaCodecStatus>(
+      Java_MediaCodecBridge_flush(env, j_media_codec_.obj()));
+}
+
+void MediaCodecBridge::Stop() {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_stop(env, j_media_codec_.obj());
+}
+
+void MediaCodecBridge::GetOutputFormat(int* width, int* height) {
+  JNIEnv* env = AttachCurrentThread();
+
+  *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj());
+  *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj());
+}
+
+int MediaCodecBridge::GetOutputSamplingRate() {
+  JNIEnv* env = AttachCurrentThread();
+
+  return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj());
+}
+
+MediaCodecStatus MediaCodecBridge::QueueInputBuffer(
+    int index,
+    const uint8* data,
+    size_t data_size,
+    const base::TimeDelta& presentation_time) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
+  if (data_size >
+      base::checked_cast<size_t>(std::numeric_limits<int32_t>::max()))
+    return MEDIA_CODEC_ERROR;
+  if (data && !FillInputBuffer(index, data, data_size))
+    return MEDIA_CODEC_ERROR;
+  JNIEnv* env = AttachCurrentThread();
+  return static_cast<MediaCodecStatus>(
+      Java_MediaCodecBridge_queueInputBuffer(env,
+                                             j_media_codec_.obj(),
+                                             index,
+                                             0,
+                                             data_size,
+                                             presentation_time.InMicroseconds(),
+                                             0));
+}
 
 MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
     int index,
@@ -34,25 +351,205 @@
     const std::string& iv,
     const std::vector<SubsampleEntry>& subsamples,
     const base::TimeDelta& presentation_time) {
-  const std::vector<char> key_vec(key_id.begin(), key_id.end());
-  const std::vector<char> iv_vec(iv.begin(), iv.end());
-  return QueueSecureInputBuffer(index, data, data_size, key_vec, iv_vec,
-                                subsamples.empty() ? nullptr : &subsamples[0],
-                                subsamples.size(), presentation_time);
+  return QueueSecureInputBuffer(
+      index, data, data_size, reinterpret_cast<const uint8_t*>(key_id.data()),
+      key_id.size(), reinterpret_cast<const uint8_t*>(iv.data()), iv.size(),
+      subsamples.empty() ? nullptr : &subsamples[0], subsamples.size(),
+      presentation_time);
+}
+
+// TODO(timav): Combine this and above methods together keeping only the first
+// interface after we switch to Spitzer pipeline.
+MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
+    int index,
+    const uint8* data,
+    size_t data_size,
+    const uint8* key_id,
+    int key_id_size,
+    const uint8* iv,
+    int iv_size,
+    const SubsampleEntry* subsamples,
+    int subsamples_size,
+    const base::TimeDelta& presentation_time) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
+  if (data_size >
+      base::checked_cast<size_t>(std::numeric_limits<int32_t>::max()))
+    return MEDIA_CODEC_ERROR;
+  if (data && !FillInputBuffer(index, data, data_size))
+    return MEDIA_CODEC_ERROR;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jbyteArray> j_key_id =
+      base::android::ToJavaByteArray(env, key_id, key_id_size);
+  ScopedJavaLocalRef<jbyteArray> j_iv =
+      base::android::ToJavaByteArray(env, iv, iv_size);
+
+  // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
+  // to indicate that all data is encrypted. But it doesn't specify what
+  // |cypher_array| and |subsamples_size| should be in that case. Passing
+  // one subsample here just to be on the safe side.
+  int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
+
+  scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
+  scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
+
+  if (subsamples_size == 0) {
+    DCHECK(!subsamples);
+    native_clear_array[0] = 0;
+    native_cypher_array[0] = data_size;
+  } else {
+    DCHECK_GT(subsamples_size, 0);
+    DCHECK(subsamples);
+    for (int i = 0; i < subsamples_size; ++i) {
+      DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max());
+      if (subsamples[i].cypher_bytes >
+          static_cast<uint32>(std::numeric_limits<jint>::max())) {
+        return MEDIA_CODEC_ERROR;
+      }
+
+      native_clear_array[i] = subsamples[i].clear_bytes;
+      native_cypher_array[i] = subsamples[i].cypher_bytes;
+    }
+  }
+
+  ScopedJavaLocalRef<jintArray> clear_array =
+      ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size);
+  ScopedJavaLocalRef<jintArray> cypher_array =
+      ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size);
+
+  return static_cast<MediaCodecStatus>(
+      Java_MediaCodecBridge_queueSecureInputBuffer(
+          env,
+          j_media_codec_.obj(),
+          index,
+          0,
+          j_iv.obj(),
+          j_key_id.obj(),
+          clear_array.obj(),
+          cypher_array.obj(),
+          new_subsamples_size,
+          presentation_time.InMicroseconds()));
+}
+
+void MediaCodecBridge::QueueEOS(int input_buffer_index) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index;
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_queueInputBuffer(env,
+                                         j_media_codec_.obj(),
+                                         input_buffer_index,
+                                         0,
+                                         0,
+                                         0,
+                                         kBufferFlagEndOfStream);
+}
+
+MediaCodecStatus MediaCodecBridge::DequeueInputBuffer(
+    const base::TimeDelta& timeout,
+    int* index) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
+      env, j_media_codec_.obj(), timeout.InMicroseconds());
+  *index = Java_DequeueInputResult_index(env, result.obj());
+  MediaCodecStatus status = static_cast<MediaCodecStatus>(
+      Java_DequeueInputResult_status(env, result.obj()));
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
+           << ", index: " << *index;
+  return status;
+}
+
+MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer(
+    const base::TimeDelta& timeout,
+    int* index,
+    size_t* offset,
+    size_t* size,
+    base::TimeDelta* presentation_time,
+    bool* end_of_stream,
+    bool* key_frame) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> result =
+      Java_MediaCodecBridge_dequeueOutputBuffer(
+          env, j_media_codec_.obj(), timeout.InMicroseconds());
+  *index = Java_DequeueOutputResult_index(env, result.obj());
+  *offset = base::checked_cast<size_t>(
+      Java_DequeueOutputResult_offset(env, result.obj()));
+  *size = base::checked_cast<size_t>(
+      Java_DequeueOutputResult_numBytes(env, result.obj()));
+  if (presentation_time) {
+    *presentation_time = base::TimeDelta::FromMicroseconds(
+        Java_DequeueOutputResult_presentationTimeMicroseconds(env,
+                                                              result.obj()));
+  }
+  int flags = Java_DequeueOutputResult_flags(env, result.obj());
+  if (end_of_stream)
+    *end_of_stream = flags & kBufferFlagEndOfStream;
+  if (key_frame)
+    *key_frame = flags & kBufferFlagSyncFrame;
+  MediaCodecStatus status = static_cast<MediaCodecStatus>(
+      Java_DequeueOutputResult_status(env, result.obj()));
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
+           << ", index: " << *index << ", offset: " << *offset
+           << ", size: " << *size << ", flags: " << flags;
+  return status;
+}
+
+void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
+  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index;
+  JNIEnv* env = AttachCurrentThread();
+  CHECK(env);
+
+  Java_MediaCodecBridge_releaseOutputBuffer(
+      env, j_media_codec_.obj(), index, render);
 }
 
 int MediaCodecBridge::GetOutputBuffersCount() {
-  return 0;
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj());
 }
 
 size_t MediaCodecBridge::GetOutputBuffersCapacity() {
-  return 0;
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_getOutputBuffersCapacity(env,
+                                                        j_media_codec_.obj());
+}
+
+void MediaCodecBridge::GetInputBuffer(int input_buffer_index,
+                                      uint8** data,
+                                      size_t* capacity) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
+      env, j_media_codec_.obj(), input_buffer_index));
+  *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj()));
+  *capacity = base::checked_cast<size_t>(
+      env->GetDirectBufferCapacity(j_buffer.obj()));
+}
+
+bool MediaCodecBridge::CopyFromOutputBuffer(int index,
+                                            size_t offset,
+                                            void* dst,
+                                            int dst_size) {
+  void* src_data = nullptr;
+  int src_capacity = GetOutputBufferAddress(index, offset, &src_data);
+  if (src_capacity < dst_size)
+    return false;
+  memcpy(dst, src_data, dst_size);
+  return true;
+}
+
+int MediaCodecBridge::GetOutputBufferAddress(int index,
+                                             size_t offset,
+                                             void** addr) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> j_buffer(
+      Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
+  *addr = reinterpret_cast<uint8*>(
+      env->GetDirectBufferAddress(j_buffer.obj())) + offset;
+  return env->GetDirectBufferCapacity(j_buffer.obj()) - offset;
 }
 
 bool MediaCodecBridge::FillInputBuffer(int index,
                                        const uint8_t* data,
                                        size_t size) {
-  uint8_t* dst = nullptr;
+  uint8* dst = NULL;
   size_t capacity = 0;
   GetInputBuffer(index, &dst, &capacity);
   CHECK(dst);
@@ -67,4 +564,334 @@
   return true;
 }
 
+AudioCodecBridge::AudioCodecBridge(const std::string& mime)
+    // Audio codec doesn't care about security level and there is no need for
+    // audio encoding yet.
+    : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {}
+
+bool AudioCodecBridge::Start(const AudioCodec& codec,
+                             int sample_rate,
+                             int channel_count,
+                             const uint8* extra_data,
+                             size_t extra_data_size,
+                             int64 codec_delay_ns,
+                             int64 seek_preroll_ns,
+                             bool play_audio,
+                             jobject media_crypto) {
+  JNIEnv* env = AttachCurrentThread();
+
+  if (!media_codec())
+    return false;
+
+  std::string codec_string = AudioCodecToAndroidMimeType(codec);
+  if (codec_string.empty())
+    return false;
+
+  ScopedJavaLocalRef<jstring> j_mime =
+      ConvertUTF8ToJavaString(env, codec_string);
+  ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
+      env, j_mime.obj(), sample_rate, channel_count));
+  DCHECK(!j_format.is_null());
+
+  if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size,
+                            codec_delay_ns, seek_preroll_ns)) {
+    return false;
+  }
+
+  if (!Java_MediaCodecBridge_configureAudio(
+           env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) {
+    return false;
+  }
+
+  return StartInternal();
+}
+
+bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
+                                            const AudioCodec& codec,
+                                            const uint8* extra_data,
+                                            size_t extra_data_size,
+                                            int64 codec_delay_ns,
+                                            int64 seek_preroll_ns) {
+  if (extra_data_size == 0 && codec != kCodecOpus)
+    return true;
+
+  JNIEnv* env = AttachCurrentThread();
+  switch (codec) {
+    case kCodecVorbis: {
+      if (extra_data[0] != 2) {
+        LOG(ERROR) << "Invalid number of vorbis headers before the codec "
+                   << "header: " << extra_data[0];
+        return false;
+      }
+
+      size_t header_length[2];
+      // |total_length| keeps track of the total number of bytes before the last
+      // header.
+      size_t total_length = 1;
+      const uint8* current_pos = extra_data;
+      // Calculate the length of the first 2 headers.
+      for (int i = 0; i < 2; ++i) {
+        header_length[i] = 0;
+        while (total_length < extra_data_size) {
+          size_t size = *(++current_pos);
+          total_length += 1 + size;
+          if (total_length > 0x80000000) {
+            LOG(ERROR) << "Vorbis header size too large";
+            return false;
+          }
+          header_length[i] += size;
+          if (size < 0xFF)
+            break;
+        }
+        if (total_length >= extra_data_size) {
+          LOG(ERROR) << "Invalid vorbis header size in the extra data";
+          return false;
+        }
+      }
+      current_pos++;
+      // The first header is identification header.
+      ScopedJavaLocalRef<jbyteArray> first_header =
+          base::android::ToJavaByteArray(env, current_pos, header_length[0]);
+      Java_MediaCodecBridge_setCodecSpecificData(
+          env, j_format, 0, first_header.obj());
+      // The last header is codec header.
+      ScopedJavaLocalRef<jbyteArray> last_header =
+          base::android::ToJavaByteArray(
+              env, extra_data + total_length, extra_data_size - total_length);
+      Java_MediaCodecBridge_setCodecSpecificData(
+          env, j_format, 1, last_header.obj());
+      break;
+    }
+    case kCodecAAC: {
+      media::BitReader reader(extra_data, extra_data_size);
+
+      // The following code is copied from aac.cc
+      // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
+      uint8 profile = 0;
+      uint8 frequency_index = 0;
+      uint8 channel_config = 0;
+      RETURN_ON_ERROR(reader.ReadBits(5, &profile));
+      RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
+
+      if (0xf == frequency_index)
+        RETURN_ON_ERROR(reader.SkipBits(24));
+      RETURN_ON_ERROR(reader.ReadBits(4, &channel_config));
+
+      if (profile == 5 || profile == 29) {
+        // Read extension config.
+        RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
+        if (frequency_index == 0xf)
+          RETURN_ON_ERROR(reader.SkipBits(24));
+        RETURN_ON_ERROR(reader.ReadBits(5, &profile));
+      }
+
+      if (profile < 1 || profile > 4 || frequency_index == 0xf ||
+          channel_config > 7) {
+        LOG(ERROR) << "Invalid AAC header";
+        return false;
+      }
+      const size_t kCsdLength = 2;
+      uint8 csd[kCsdLength];
+      csd[0] = profile << 3 | frequency_index >> 1;
+      csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
+      ScopedJavaLocalRef<jbyteArray> byte_array =
+          base::android::ToJavaByteArray(env, csd, kCsdLength);
+      Java_MediaCodecBridge_setCodecSpecificData(
+          env, j_format, 0, byte_array.obj());
+
+      // TODO(qinmin): pass an extra variable to this function to determine
+      // whether we need to call this.
+      Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
+      break;
+    }
+    case kCodecOpus: {
+      if (!extra_data || extra_data_size == 0 ||
+          codec_delay_ns < 0 || seek_preroll_ns < 0) {
+        LOG(ERROR) << "Invalid Opus Header";
+        return false;
+      }
+
+      // csd0 - Opus Header
+      ScopedJavaLocalRef<jbyteArray> csd0 =
+          base::android::ToJavaByteArray(env, extra_data, extra_data_size);
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj());
+
+      // csd1 - Codec Delay
+      ScopedJavaLocalRef<jbyteArray> csd1 =
+          base::android::ToJavaByteArray(
+              env, reinterpret_cast<const uint8*>(&codec_delay_ns),
+              sizeof(int64_t));
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj());
+
+      // csd2 - Seek Preroll
+      ScopedJavaLocalRef<jbyteArray> csd2 =
+          base::android::ToJavaByteArray(
+              env, reinterpret_cast<const uint8*>(&seek_preroll_ns),
+              sizeof(int64_t));
+      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj());
+      break;
+    }
+    default:
+      LOG(ERROR) << "Invalid header encountered for codec: "
+                 << AudioCodecToAndroidMimeType(codec);
+      return false;
+  }
+  return true;
+}
+
+int64 AudioCodecBridge::PlayOutputBuffer(int index,
+                                         size_t size,
+                                         size_t offset,
+                                         bool postpone) {
+  DCHECK_LE(0, index);
+  int numBytes = base::checked_cast<int>(size);
+
+  void* buffer = nullptr;
+  int capacity = GetOutputBufferAddress(index, offset, &buffer);
+  numBytes = std::min(capacity, numBytes);
+  CHECK_GE(numBytes, 0);
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray(
+          env, static_cast<uint8*>(buffer), numBytes);
+  return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(),
+                                                byte_array.obj(), postpone);
+}
+
+void AudioCodecBridge::SetVolume(double volume) {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_setVolume(env, media_codec(), volume);
+}
+
+// static
+AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
+  if (!MediaCodecBridge::IsAvailable())
+    return NULL;
+
+  const std::string mime = AudioCodecToAndroidMimeType(codec);
+  return mime.empty() ? NULL : new AudioCodecBridge(mime);
+}
+
+// static
+bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
+  return MediaCodecBridge::IsKnownUnaccelerated(
+      AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
+}
+
+// static
+bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
+                                            MediaCodecDirection direction) {
+  return MediaCodecBridge::IsKnownUnaccelerated(
+      VideoCodecToAndroidMimeType(codec), direction);
+}
+
+// static
+VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec,
+                                                  bool is_secure,
+                                                  const gfx::Size& size,
+                                                  jobject surface,
+                                                  jobject media_crypto) {
+  if (!MediaCodecBridge::IsAvailable())
+    return NULL;
+
+  const std::string mime = VideoCodecToAndroidMimeType(codec);
+  if (mime.empty())
+    return NULL;
+
+  scoped_ptr<VideoCodecBridge> bridge(
+      new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER));
+  if (!bridge->media_codec())
+    return NULL;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  ScopedJavaLocalRef<jobject> j_format(
+      Java_MediaCodecBridge_createVideoDecoderFormat(
+          env, j_mime.obj(), size.width(), size.height()));
+  DCHECK(!j_format.is_null());
+  if (!Java_MediaCodecBridge_configureVideo(env,
+                                            bridge->media_codec(),
+                                            j_format.obj(),
+                                            surface,
+                                            media_crypto,
+                                            0)) {
+    return NULL;
+  }
+
+  return bridge->StartInternal() ? bridge.release() : NULL;
+}
+
+// static
+VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
+                                                  const gfx::Size& size,
+                                                  int bit_rate,
+                                                  int frame_rate,
+                                                  int i_frame_interval,
+                                                  int color_format) {
+  if (!MediaCodecBridge::IsAvailable())
+    return NULL;
+
+  const std::string mime = VideoCodecToAndroidMimeType(codec);
+  if (mime.empty())
+    return NULL;
+
+  scoped_ptr<VideoCodecBridge> bridge(
+      new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER));
+  if (!bridge->media_codec())
+    return NULL;
+
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
+  ScopedJavaLocalRef<jobject> j_format(
+      Java_MediaCodecBridge_createVideoEncoderFormat(env,
+                                                     j_mime.obj(),
+                                                     size.width(),
+                                                     size.height(),
+                                                     bit_rate,
+                                                     frame_rate,
+                                                     i_frame_interval,
+                                                     color_format));
+  DCHECK(!j_format.is_null());
+  if (!Java_MediaCodecBridge_configureVideo(env,
+                                            bridge->media_codec(),
+                                            j_format.obj(),
+                                            NULL,
+                                            NULL,
+                                            kConfigureFlagEncode)) {
+    return NULL;
+  }
+
+  return bridge->StartInternal() ? bridge.release() : NULL;
+}
+
+VideoCodecBridge::VideoCodecBridge(const std::string& mime,
+                                   bool is_secure,
+                                   MediaCodecDirection direction)
+    : MediaCodecBridge(mime, is_secure, direction),
+      adaptive_playback_supported_for_testing_(-1) {}
+
+void VideoCodecBridge::SetVideoBitrate(int bps) {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps);
+}
+
+void VideoCodecBridge::RequestKeyFrameSoon() {
+  JNIEnv* env = AttachCurrentThread();
+  Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
+}
+
+bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) {
+  if (adaptive_playback_supported_for_testing_ == 0)
+    return false;
+  else if (adaptive_playback_supported_for_testing_ > 0)
+    return true;
+  JNIEnv* env = AttachCurrentThread();
+  return Java_MediaCodecBridge_isAdaptivePlaybackSupported(
+      env, media_codec(), width, height);
+}
+
+bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
 }  // namespace media
diff --git a/media/base/android/media_codec_bridge.h b/media/base/android/media_codec_bridge.h
index 02a29f9..45361c88b 100644
--- a/media/base/android/media_codec_bridge.h
+++ b/media/base/android/media_codec_bridge.h
@@ -5,16 +5,15 @@
 #ifndef MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_
 #define MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_
 
-#include <stdint.h>
-
+#include <jni.h>
 #include <set>
 #include <string>
-#include <vector>
 
-#include "base/compiler_specific.h"
+#include "base/android/scoped_java_ref.h"
 #include "base/time/time.h"
-#include "media/base/android/media_codec_util.h"
-#include "media/base/media_export.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/video_decoder_config.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace media {
 
@@ -35,12 +34,59 @@
   MEDIA_CODEC_ERROR
 };
 
-// Interface for wrapping different Android MediaCodec implementations. For
-// more information on Android MediaCodec, check
+// Codec direction.  Keep this in sync with MediaCodecBridge.java.
+enum MediaCodecDirection {
+  MEDIA_CODEC_DECODER,
+  MEDIA_CODEC_ENCODER,
+};
+
+// This class serves as a bridge for native code to call java functions inside
+// Android MediaCodec class. For more information on Android MediaCodec, check
 // http://developer.android.com/reference/android/media/MediaCodec.html
 // Note: MediaCodec is only available on JB and greater.
+// Use AudioCodecBridge or VideoCodecBridge to create an instance of this
+// object.
+//
+// TODO(fischman,xhwang): replace this (and the enums that go with it) with
+// chromium's JNI auto-generation hotness.
 class MEDIA_EXPORT MediaCodecBridge {
  public:
+  // Returns true if MediaCodec is available on the device.
+  // All other static methods check IsAvailable() internally. There's no need
+  // to check IsAvailable() explicitly before calling them.
+  static bool IsAvailable();
+
+  // Returns true if MediaCodec.setParameters() is available on the device.
+  static bool SupportsSetParameters();
+
+  // Returns true if MediaCodec.getName() is available on the device.
+  static bool SupportsGetName();
+
+  // Returns whether MediaCodecBridge has a decoder that |is_secure| and can
+  // decode |codec| type.
+  static bool CanDecode(const std::string& codec, bool is_secure);
+
+  // Represents supported codecs on android.
+  // TODO(qinmin): Currently the codecs string only contains one codec. Do we
+  // need to support codecs separated by comma. (e.g. "vp8" -> "vp8, vp8.0")?
+  struct CodecsInfo {
+    std::string codecs;  // E.g. "vp8" or "avc1".
+    std::string name;    // E.g. "OMX.google.vp8.decoder".
+    MediaCodecDirection direction;
+  };
+
+  // Get a list of supported codecs.
+  static std::vector<CodecsInfo> GetCodecsInfo();
+
+  // Get default codec name for |mime_type|.
+  static std::string GetDefaultCodecName(const std::string& mime_type,
+                                         MediaCodecDirection direction);
+
+  // Get a list of encoder supported color formats for |mime_type|.
+  // The mapping of color format name and its value refers to
+  // MediaCodecInfo.CodecCapabilities.
+  static std::set<int> GetEncoderColorFormats(const std::string& mime_type);
+
   virtual ~MediaCodecBridge();
 
   // Resets both input and output, all indices previously returned in calls to
@@ -49,36 +95,31 @@
   // words, there will be no outputs until new input is provided.
   // Returns MEDIA_CODEC_ERROR if an unexpected error happens, or Media_CODEC_OK
   // otherwise.
-  virtual MediaCodecStatus Reset() = 0;
-
-  // Calls start() against the media codec instance. Returns whether media
-  // codec was successfully started.
-  virtual bool Start() = 0;
+  MediaCodecStatus Reset();
 
   // Finishes the decode/encode session. The instance remains active
   // and ready to be StartAudio/Video()ed again. HOWEVER, due to the buggy
   // vendor's implementation , b/8125974, Stop() -> StartAudio/Video() may not
   // work on some devices. For reliability, Stop() -> delete and recreate new
   // instance -> StartAudio/Video() is recommended.
-  virtual void Stop() = 0;
+  void Stop();
 
   // Used for getting output format. This is valid after DequeueInputBuffer()
   // returns a format change by returning INFO_OUTPUT_FORMAT_CHANGED
-  virtual void GetOutputFormat(int* width, int* height) = 0;
+  void GetOutputFormat(int* width, int* height);
 
   // Used for checking for new sampling rate after DequeueInputBuffer() returns
   // INFO_OUTPUT_FORMAT_CHANGED
-  virtual int GetOutputSamplingRate() = 0;
+  int GetOutputSamplingRate();
 
   // Submits a byte array to the given input buffer. Call this after getting an
-  // available buffer from DequeueInputBuffer(). If |data| is NULL, assume the
+  // available buffer from DequeueInputBuffer().  If |data| is NULL, assume the
   // input buffer has already been populated (but still obey |size|).
   // |data_size| must be less than kint32max (because Java).
-  virtual MediaCodecStatus QueueInputBuffer(
-      int index,
-      const uint8_t* data,
-      size_t data_size,
-      const base::TimeDelta& presentation_time) = 0;
+  MediaCodecStatus QueueInputBuffer(int index,
+                                    const uint8* data,
+                                    size_t data_size,
+                                    const base::TimeDelta& presentation_time);
 
   // Similar to the above call, but submits a buffer that is encrypted.  Note:
   // NULL |subsamples| indicates the whole buffer is encrypted.  If |data| is
@@ -97,18 +138,20 @@
   // and MediaCodecPlayer.
   // TODO(timav): remove this method and keep only the one above after we
   // switch to the Spitzer pipeline.
-  virtual MediaCodecStatus QueueSecureInputBuffer(
+  MediaCodecStatus QueueSecureInputBuffer(
       int index,
       const uint8_t* data,
       size_t data_size,
-      const std::vector<char>& key_id,
-      const std::vector<char>& iv,
+      const uint8* key_id,
+      int key_id_size,
+      const uint8* iv,
+      int iv_size,
       const SubsampleEntry* subsamples,
       int subsamples_size,
-      const base::TimeDelta& presentation_time) = 0;
+      const base::TimeDelta& presentation_time);
 
   // Submits an empty buffer with a EOS (END OF STREAM) flag.
-  virtual void QueueEOS(int input_buffer_index) = 0;
+  void QueueEOS(int input_buffer_index);
 
   // Returns:
   // MEDIA_CODEC_OK if an input buffer is ready to be filled with valid data,
@@ -116,8 +159,8 @@
   // MEDIA_CODEC_ERROR if unexpected error happens.
   // Note: Never use infinite timeout as this would block the decoder thread and
   // prevent the decoder job from being released.
-  virtual MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
-                                              int* index) = 0;
+  MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
+                                      int* index);
 
   // Dequeues an output buffer, block at most timeout_us microseconds.
   // Returns the status of this operation. If OK is returned, the output
@@ -128,51 +171,159 @@
   // prevent the decoder job from being released.
   // TODO(xhwang): Can we drop |end_of_stream| and return
   // MEDIA_CODEC_OUTPUT_END_OF_STREAM?
-  virtual MediaCodecStatus DequeueOutputBuffer(
-      const base::TimeDelta& timeout,
-      int* index,
-      size_t* offset,
-      size_t* size,
-      base::TimeDelta* presentation_time,
-      bool* end_of_stream,
-      bool* key_frame) = 0;
+  MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout,
+                                       int* index,
+                                       size_t* offset,
+                                       size_t* size,
+                                       base::TimeDelta* presentation_time,
+                                       bool* end_of_stream,
+                                       bool* key_frame);
 
   // Returns the buffer to the codec. If you previously specified a surface when
   // configuring this video decoder you can optionally render the buffer.
-  virtual void ReleaseOutputBuffer(int index, bool render) = 0;
+  void ReleaseOutputBuffer(int index, bool render);
 
   // Returns the number of output buffers used by the codec.
   // TODO(qinmin): this call is deprecated in Lollipop.
-  virtual int GetOutputBuffersCount();
+  int GetOutputBuffersCount();
 
   // Returns the capacity of each output buffer used by the codec.
   // TODO(qinmin): this call is deprecated in Lollipop.
-  virtual size_t GetOutputBuffersCapacity();
+  size_t GetOutputBuffersCapacity();
 
   // Returns an input buffer's base pointer and capacity.
-  virtual void GetInputBuffer(int input_buffer_index,
-                              uint8_t** data,
-                              size_t* capacity) = 0;
+  void GetInputBuffer(int input_buffer_index, uint8** data, size_t* capacity);
 
   // Copy |dst_size| bytes from output buffer |index|'s |offset| onwards into
   // |*dst|.
-  virtual bool CopyFromOutputBuffer(int index,
-                                    size_t offset,
-                                    void* dst,
-                                    int dst_size) = 0;
+  bool CopyFromOutputBuffer(int index, size_t offset, void* dst, int dst_size);
+
+  static bool RegisterMediaCodecBridge(JNIEnv* env);
 
  protected:
-  MediaCodecBridge();
+  // Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a
+  // software codec instead of a hardware one).
+  static bool IsKnownUnaccelerated(const std::string& mime_type,
+                                   MediaCodecDirection direction);
 
+  MediaCodecBridge(const std::string& mime,
+                   bool is_secure,
+                   MediaCodecDirection direction);
+
+  // Calls start() against the media codec instance. Used in StartXXX() after
+  // configuring media codec. Returns whether media codec was successfully
+  // started.
+  bool StartInternal() WARN_UNUSED_RESULT;
+
+  // Called to get the buffer address given the output buffer index and offset.
+  // This function returns the size of the output and |addr| is the pointer to
+  // the address to read.
+  int GetOutputBufferAddress(int index, size_t offset, void** addr);
+
+  jobject media_codec() { return j_media_codec_.obj(); }
+  MediaCodecDirection direction_;
+
+ private:
   // Fills a particular input buffer; returns false if |data_size| exceeds the
   // input buffer's capacity (and doesn't touch the input buffer in that case).
   bool FillInputBuffer(int index,
                        const uint8_t* data,
                        size_t data_size) WARN_UNUSED_RESULT;
 
+  // Java MediaCodec instance.
+  base::android::ScopedJavaGlobalRef<jobject> j_media_codec_;
+
   DISALLOW_COPY_AND_ASSIGN(MediaCodecBridge);
 };
 
+class AudioCodecBridge : public MediaCodecBridge {
+ public:
+  // Returns an AudioCodecBridge instance if |codec| is supported, or a NULL
+  // pointer otherwise.
+  static AudioCodecBridge* Create(const AudioCodec& codec);
+
+  // See MediaCodecBridge::IsKnownUnaccelerated().
+  static bool IsKnownUnaccelerated(const AudioCodec& codec);
+
+  // Start the audio codec bridge.
+  bool Start(const AudioCodec& codec, int sample_rate, int channel_count,
+             const uint8* extra_data, size_t extra_data_size,
+             int64 codec_delay_ns, int64 seek_preroll_ns,
+             bool play_audio, jobject media_crypto) WARN_UNUSED_RESULT;
+
+  // Plays the output buffer right away or save for later playback if |postpone|
+  // is set to true. This call must be called after DequeueOutputBuffer() and
+  // before ReleaseOutputBuffer. The data is extracted from the output buffers
+  // using |index|, |size| and |offset|. Returns the playback head position
+  // expressed in frames.
+  // When |postpone| is set to true, the next PlayOutputBuffer() should have
+  // postpone == false, and it will play two buffers: the postponed one and
+  // the one identified by |index|.
+  int64 PlayOutputBuffer(int index,
+                         size_t size,
+                         size_t offset,
+                         bool postpone = false);
+
+  // Set the volume of the audio output.
+  void SetVolume(double volume);
+
+ private:
+  explicit AudioCodecBridge(const std::string& mime);
+
+  // Configure the java MediaFormat object with the extra codec data passed in.
+  bool ConfigureMediaFormat(jobject j_format, const AudioCodec& codec,
+                            const uint8* extra_data, size_t extra_data_size,
+                            int64 codec_delay_ns, int64 seek_preroll_ns);
+};
+
+class MEDIA_EXPORT VideoCodecBridge : public MediaCodecBridge {
+ public:
+  // See MediaCodecBridge::IsKnownUnaccelerated().
+  static bool IsKnownUnaccelerated(const VideoCodec& codec,
+                                   MediaCodecDirection direction);
+
+  // Create, start, and return a VideoCodecBridge decoder or NULL on failure.
+  static VideoCodecBridge* CreateDecoder(
+      const VideoCodec& codec,  // e.g. media::kCodecVP8
+      bool is_secure,
+      const gfx::Size& size,  // Output frame size.
+      jobject surface,        // Output surface, optional.
+      jobject media_crypto);  // MediaCrypto object, optional.
+
+  // Create, start, and return a VideoCodecBridge encoder or NULL on failure.
+  static VideoCodecBridge* CreateEncoder(
+      const VideoCodec& codec,  // e.g. media::kCodecVP8
+      const gfx::Size& size,    // input frame size
+      int bit_rate,             // bits/second
+      int frame_rate,           // frames/second
+      int i_frame_interval,     // count
+      int color_format);        // MediaCodecInfo.CodecCapabilities.
+
+  void SetVideoBitrate(int bps);
+  void RequestKeyFrameSoon();
+
+  // Returns whether adaptive playback is supported for this object given
+  // the new size.
+  bool IsAdaptivePlaybackSupported(int width, int height);
+
+  // Test-only method to set the return value of IsAdaptivePlaybackSupported().
+  // Without this function, the return value of that function will be device
+  // dependent. If |adaptive_playback_supported| is equal to 0, the return value
+  // will be false. If |adaptive_playback_supported| is larger than 0, the
+  // return value will be true.
+  void set_adaptive_playback_supported_for_testing(
+      int adaptive_playback_supported) {
+    adaptive_playback_supported_for_testing_ = adaptive_playback_supported;
+  }
+
+ private:
+  VideoCodecBridge(const std::string& mime,
+                   bool is_secure,
+                   MediaCodecDirection direction);
+
+  int adaptive_playback_supported_for_testing_;
+};
+
 }  // namespace media
 
 #endif  // MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/media_codec_bridge_unittest.cc b/media/base/android/media_codec_bridge_unittest.cc
new file mode 100644
index 0000000..f1c04711
--- /dev/null
+++ b/media/base/android/media_codec_bridge_unittest.cc
@@ -0,0 +1,319 @@
+// Copyright (c) 2013 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 <string>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/test_data_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace {
+
+// The first frame of
+// http://www.html5rocks.com/en/tutorials/audio/quick/test.mp3
+unsigned char test_mp3[] = {
+  0xff, 0xfb, 0xd2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x7e, 0x40,
+  0xc0, 0x19, 0x4a, 0x80, 0x0d, 0x60, 0x48, 0x1b, 0x40, 0xf7, 0xbd, 0xb9,
+  0xd9, 0x40, 0x6f, 0x82, 0x01, 0x8b, 0x17, 0xa0, 0x80, 0xc5, 0x01, 0xad,
+  0x9a, 0xd3, 0x00, 0x12, 0xc0, 0x72, 0x93, 0x67, 0xd0, 0x03, 0x6f, 0xa4,
+  0xc0, 0xc3, 0x23, 0xee, 0x9b, 0xc0, 0xcc, 0x02, 0xa0, 0xa1, 0x30, 0x0c,
+  0x52, 0x2d, 0xfd, 0x6e, 0x08, 0x83, 0x60, 0x40, 0x46, 0x06, 0x4b, 0x20,
+  0x82, 0x82, 0x7f, 0xd4, 0x81, 0xe7, 0x00, 0x64, 0x20, 0x18, 0xec, 0xc2,
+  0x06, 0x57, 0x0f, 0x81, 0x93, 0x0b, 0x00, 0x66, 0xe3, 0xb7, 0xe8, 0x32,
+  0x6e, 0xf0, 0x32, 0xb0, 0x58, 0x0c, 0x7c, 0x3a, 0x03, 0x22, 0x14, 0x80,
+  0xc9, 0x01, 0x80, 0x30, 0x20, 0x14, 0x0c, 0x96, 0x73, 0xfe, 0x9f, 0x6c,
+  0x0c, 0xd2, 0x25, 0x0f, 0xdc, 0x0c, 0x32, 0x43, 0x03, 0x27, 0x87, 0xc0,
+  0xc2, 0xc0, 0x20, 0xfc, 0x42, 0xc5, 0xff, 0xff, 0xd4, 0x80, 0x01, 0x01,
+  0x80, 0xc3, 0x81, 0x01, 0x95, 0x03, 0x28, 0x82, 0xc0, 0xc3, 0x01, 0xa1,
+  0x06, 0x81, 0x87, 0xc2, 0x40, 0x64, 0xc1, 0xf0, 0x12, 0x02, 0xff, 0xf6,
+  0x5b, 0x9f, 0x44, 0xdc, 0xdd, 0x0b, 0x38, 0x59, 0xe0, 0x31, 0x71, 0x60,
+  0x0c, 0xb4, 0x22, 0x03, 0x3b, 0x96, 0x40, 0xc8, 0x63, 0x90, 0x0a, 0x23,
+  0x81, 0x9e, 0x4c, 0x20, 0x65, 0xb3, 0x18, 0x19, 0x6c, 0x42, 0x06, 0x36,
+  0x1d, 0x01, 0x90, 0x87, 0xdf, 0xff, 0xd0, 0x65, 0xa6, 0xea, 0x66, 0xfd,
+  0x40, 0x0c, 0x48, 0x03, 0x1a, 0x09, 0x01, 0x21, 0x98, 0x19, 0x2c, 0x36,
+  0x06, 0x43, 0x21, 0x81, 0x92, 0xca, 0x60, 0x64, 0x70, 0xb8, 0x19, 0x20,
+  0x6c, 0x02, 0x83, 0x80, 0xcb, 0x60, 0x65, 0x32, 0x28, 0x18, 0x64, 0x24,
+  0x06, 0x3a, 0x0c, 0x00, 0xe1, 0x00, 0x18, 0xd0, 0x35, 0xff, 0xff, 0xff,
+  0xe8, 0x32, 0xef, 0xb2, 0x90, 0x65, 0xbb, 0xdd, 0x94, 0x82, 0x0b, 0x4c,
+  0xfa, 0x25, 0xf3, 0x74, 0x13, 0x0f, 0xf8, 0x19, 0x28, 0x84, 0x06, 0x36,
+  0x11, 0x01, 0x20, 0x80, 0x18, 0xb4, 0x52, 0x0e, 0x15, 0x00, 0x30, 0x50,
+  0x0c, 0x84, 0x32, 0x03, 0x11, 0x04, 0x03, 0x48, 0x04, 0x00, 0x00, 0x31,
+  0x21, 0x00, 0x0c, 0x84, 0x18, 0x03, 0x07, 0x85, 0x40, 0xc6, 0xa5, 0x70,
+  0x32, 0xb8, 0x7c, 0x0c, 0x54, 0x04, 0x00, 0xd0, 0x08, 0x59, 0x58, 0x18,
+  0x20, 0x14, 0x06, 0x30, 0x30, 0x01, 0x9b, 0x86, 0x00, 0x6b, 0x54, 0xa8,
+  0x19, 0x8c, 0x2a, 0x06, 0x16, 0x09, 0x01, 0xa0, 0xd0, 0xa0, 0x69, 0x74,
+  0xb8, 0x19, 0xc4, 0x4a, 0xa3, 0xda, 0x9d, 0x1e, 0x4f, 0x05, 0xc0, 0x5b,
+  0x0b, 0x03, 0xc2, 0x76, 0xa3, 0x4f, 0xb9, 0x16, 0xc2, 0x70, 0x41, 0x07,
+  0xa0, 0x84, 0x16, 0x38, 0x4a, 0xc8, 0xaf, 0xee, 0x7f, 0x93, 0xb5, 0x5c,
+  0x39, 0x1e, 0x29, 0xd9, 0x8c, 0x80, 0xb5, 0x80, 0xe6, 0x85, 0xb2, 0x99,
+  0x68, 0x85, 0x46, 0x91, 0x60, 0xdb, 0x06, 0xfa, 0x38, 0x7a, 0xc7, 0xac,
+  0x85, 0xa8, 0xd3, 0xe6, 0x99, 0x3b, 0x66, 0x43, 0x23, 0x1f, 0x84, 0xe1,
+  0x65, 0x5e, 0xbc, 0x84, 0x18, 0x62, 0xe6, 0x42, 0x0b, 0x82, 0xe4, 0xd3,
+  0x42, 0xd2, 0x05, 0x81, 0x4e, 0xe4, 0x9f, 0x8c, 0xc8, 0x7f, 0xa3, 0xe0,
+  0x8d, 0xf1, 0x0f, 0x38, 0xe5, 0x3f, 0xc4, 0x2c, 0x24, 0x65, 0x8d, 0xb9,
+  0x58, 0xac, 0x39, 0x0e, 0x37, 0x99, 0x2e, 0x85, 0xe0, 0xb7, 0x98, 0x41,
+  0x20, 0x38, 0x1b, 0x95, 0x07, 0xfa, 0xa8, 0x9c, 0x21, 0x0f, 0x13, 0x8c,
+  0xa5, 0xc1, 0x76, 0xae, 0x0b, 0xc1, 0x30, 0x27, 0x08, 0xc1, 0xf6, 0x4d,
+  0xce, 0xb4, 0x41, 0x38, 0x1e, 0x82, 0x10, 0x74, 0x45, 0x91, 0x90, 0xff,
+  0x41, 0x8b, 0x62, 0x1a, 0x71, 0xb6, 0x45, 0x63, 0x8c, 0xce, 0xb8, 0x54,
+  0x1b, 0xe8, 0x5d, 0x9e, 0x35, 0x9d, 0x6c, 0xac, 0xe8, 0x83, 0xa1, 0xe9,
+  0x3f, 0x13, 0x74, 0x11, 0x04, 0x10, 0xf1, 0x37, 0x38, 0xc6, 0x00, 0x60,
+  0x27, 0x48, 0x38, 0x85, 0x92, 0x76, 0xb7, 0xf3, 0xa7, 0x1c, 0x4b, 0xf9,
+  0x3b, 0x5a, 0x88, 0xac, 0x60, 0x1b, 0x85, 0x81, 0x16, 0xab, 0x44, 0x17,
+  0x08, 0x2e, 0x0f, 0xd4, 0xe2, 0xde, 0x49, 0xc9, 0xe1, 0xc0, 0xc0, 0xa0,
+  0x7e, 0x73, 0xa1, 0x67, 0xf8, 0xf5, 0x9f, 0xc4, 0x21, 0x50, 0x4f, 0x05,
+  0x2c, 0xfc, 0x5c, 0xaa, 0x85, 0xb0, 0xfa, 0x67, 0x80, 0x7e, 0x0f, 0xfd,
+  0x92, 0x30, 0xd5, 0xa0, 0xd4, 0x05, 0xdd, 0x06, 0x68, 0x1d, 0x6e, 0x4e,
+  0x8b, 0x79, 0xd6, 0xfc, 0xff, 0x2e, 0x6e, 0x7c, 0xba, 0x03, 0x90, 0xd4,
+  0x25, 0x65, 0x8e, 0xe7, 0x3a, 0xd1, 0xd6, 0xdc, 0xf0, 0xbe, 0x12, 0xc4,
+  0x31, 0x08, 0x16, 0x70, 0x31, 0x85, 0x61, 0x38, 0x27, 0x0a, 0x91, 0x5f,
+  0x03, 0x38, 0xeb, 0x37, 0x13, 0x48, 0x41, 0xbe, 0x7f, 0x04, 0x70, 0x62,
+  0x2b, 0x15, 0x91, 0x67, 0x63, 0x4f, 0xad, 0xa7, 0x1d, 0x3f, 0x44, 0x17,
+  0x02, 0x08, 0x0d, 0xf2, 0xfc, 0x03, 0xa0, 0x74, 0x21, 0x8b, 0x07, 0x3a,
+  0x8d, 0x0f, 0x54, 0x58, 0x94, 0x12, 0xc5, 0x62, 0x18, 0xb9, 0x42, 0xf0,
+  0x6c, 0x73, 0xa0, 0x92, 0xad, 0x27, 0x1c, 0x20, 0x0f, 0xc1, 0xca, 0x44,
+  0x87, 0x47, 0xc5, 0x43, 0x23, 0x01, 0xda, 0x23, 0xe2, 0x89, 0x38, 0x9f,
+  0x1f, 0x8d, 0x8c, 0xc6, 0x95, 0xa3, 0x34, 0x21, 0x21, 0x2d, 0x49, 0xea,
+  0x4b, 0x05, 0x85, 0xf5, 0x58, 0x25, 0x13, 0xcd, 0x51, 0x19, 0x1a, 0x88,
+  0xa6, 0x83, 0xd6, 0xd0, 0xbc, 0x25, 0x19, 0x1c, 0x92, 0x12, 0x44, 0x5d,
+  0x1c, 0x04, 0xf1, 0x99, 0xdf, 0x92, 0x8e, 0x09, 0x85, 0xf3, 0x88, 0x82,
+  0x4c, 0x22, 0x17, 0xc5, 0x25, 0x23, 0xed, 0x78, 0xf5, 0x41, 0xd1, 0xe9,
+  0x8a, 0xb3, 0x52, 0xd1, 0x3d, 0x79, 0x81, 0x4d, 0x31, 0x24, 0xf9, 0x38,
+  0x96, 0xbc, 0xf4, 0x8c, 0x25, 0xe9, 0xf2, 0x73, 0x94, 0x85, 0xc2, 0x61,
+  0x6a, 0x34, 0x68, 0x65, 0x78, 0x87, 0xa6, 0x4f
+};
+
+}  // namespace
+
+namespace media {
+
+// Helper macro to skip the test if MediaCodecBridge isn't available.
+#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
+  do {                                                            \
+    if (!MediaCodecBridge::IsAvailable()) {                       \
+      VLOG(0) << "Could not run test - not supported on device."; \
+      return;                                                     \
+    }                                                             \
+  } while (0)
+
+static const int kPresentationTimeBase = 100;
+
+static inline const base::TimeDelta InfiniteTimeOut() {
+  return base::TimeDelta::FromMicroseconds(-1);
+}
+
+void DecodeMediaFrame(
+    VideoCodecBridge* media_codec, const uint8* data, size_t data_size,
+    const base::TimeDelta input_presentation_timestamp,
+    const base::TimeDelta initial_timestamp_lower_bound) {
+  base::TimeDelta input_pts = input_presentation_timestamp;
+  base::TimeDelta timestamp = initial_timestamp_lower_bound;
+  base::TimeDelta new_timestamp;
+  for (int i = 0; i < 10; ++i) {
+    int input_buf_index = -1;
+    MediaCodecStatus status =
+        media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+    ASSERT_EQ(MEDIA_CODEC_OK, status);
+
+    media_codec->QueueInputBuffer(
+        input_buf_index, data, data_size, input_presentation_timestamp);
+
+    size_t unused_offset = 0;
+    size_t size = 0;
+    bool eos = false;
+    int output_buf_index = -1;
+    status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(),
+                                              &output_buf_index,
+                                              &unused_offset,
+                                              &size,
+                                              &new_timestamp,
+                                              &eos,
+                                              NULL);
+
+    if (status == MEDIA_CODEC_OK && output_buf_index > 0) {
+      media_codec->ReleaseOutputBuffer(output_buf_index, false);
+    }
+    // Output time stamp should not be smaller than old timestamp.
+    ASSERT_TRUE(new_timestamp >= timestamp);
+    input_pts += base::TimeDelta::FromMicroseconds(33000);
+    timestamp = new_timestamp;
+  }
+}
+
+TEST(MediaCodecBridgeTest, Initialize) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::MediaCodecBridge> media_codec;
+  media_codec.reset(VideoCodecBridge::CreateDecoder(
+      kCodecH264, false, gfx::Size(640, 480), NULL, NULL));
+}
+
+TEST(MediaCodecBridgeTest, DoNormal) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::AudioCodecBridge> media_codec;
+  media_codec.reset(AudioCodecBridge::Create(kCodecMP3));
+
+  ASSERT_TRUE(media_codec->Start(
+      kCodecMP3, 44100, 2, NULL, 0, 0, 0, false, NULL));
+
+  int input_buf_index = -1;
+  MediaCodecStatus status =
+      media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+  ASSERT_EQ(MEDIA_CODEC_OK, status);
+  ASSERT_GE(input_buf_index, 0);
+
+  int64 input_pts = kPresentationTimeBase;
+  media_codec->QueueInputBuffer(input_buf_index,
+                                test_mp3,
+                                sizeof(test_mp3),
+                                base::TimeDelta::FromMicroseconds(++input_pts));
+
+  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+  media_codec->QueueInputBuffer(
+      input_buf_index, test_mp3, sizeof(test_mp3),
+      base::TimeDelta::FromMicroseconds(++input_pts));
+
+  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
+  media_codec->QueueEOS(input_buf_index);
+
+  input_pts = kPresentationTimeBase;
+  bool eos = false;
+  while (!eos) {
+    size_t unused_offset = 0;
+    size_t size = 0;
+    base::TimeDelta timestamp;
+    int output_buf_index = -1;
+    status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(),
+                                              &output_buf_index,
+                                              &unused_offset,
+                                              &size,
+                                              &timestamp,
+                                              &eos,
+                                              NULL);
+    switch (status) {
+      case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
+        FAIL();
+        return;
+
+      case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
+        continue;
+
+      case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
+        continue;
+
+      default:
+        break;
+    }
+    ASSERT_GE(output_buf_index, 0);
+    EXPECT_LE(1u, size);
+    if (!eos)
+      EXPECT_EQ(++input_pts, timestamp.InMicroseconds());
+    ASSERT_LE(input_pts, kPresentationTimeBase + 2);
+  }
+  ASSERT_EQ(input_pts, kPresentationTimeBase + 2);
+}
+
+TEST(MediaCodecBridgeTest, InvalidVorbisHeader) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::AudioCodecBridge> media_codec;
+  media_codec.reset(AudioCodecBridge::Create(kCodecVorbis));
+
+  // The first byte of the header is not 0x02.
+  uint8 invalid_first_byte[] = { 0x00, 0xff, 0xff, 0xff, 0xff };
+  EXPECT_FALSE(media_codec->Start(
+      kCodecVorbis, 44100, 2, invalid_first_byte, sizeof(invalid_first_byte),
+      0, 0, false, NULL));
+
+  // Size of the header does not match with the data we passed in.
+  uint8 invalid_size[] = { 0x02, 0x01, 0xff, 0x01, 0xff };
+  EXPECT_FALSE(media_codec->Start(
+      kCodecVorbis, 44100, 2, invalid_size, sizeof(invalid_size),
+      0, 0, false, NULL));
+
+  // Size of the header is too large.
+  size_t large_size = 8 * 1024 * 1024 + 2;
+  uint8* very_large_header = new uint8[large_size];
+  very_large_header[0] = 0x02;
+  for (size_t i = 1; i < large_size - 1; ++i)
+    very_large_header[i] = 0xff;
+  very_large_header[large_size - 1] = 0xfe;
+  EXPECT_FALSE(media_codec->Start(
+      kCodecVorbis, 44100, 2, very_large_header, 0x80000000,
+      0, 0, false, NULL));
+  delete[] very_large_header;
+}
+
+TEST(MediaCodecBridgeTest, InvalidOpusHeader) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<media::AudioCodecBridge> media_codec;
+  media_codec.reset(AudioCodecBridge::Create(kCodecOpus));
+  uint8 dummy_extra_data[] = { 0, 0 };
+
+  // Extra Data is NULL.
+  EXPECT_FALSE(media_codec->Start(
+      kCodecOpus, 48000, 2, NULL, 0, -1, 0, false, NULL));
+
+  // Codec Delay is < 0.
+  EXPECT_FALSE(media_codec->Start(
+      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data),
+      -1, 0, false, NULL));
+
+  // Seek Preroll is < 0.
+  EXPECT_FALSE(media_codec->Start(
+      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data),
+      0, -1, false, NULL));
+}
+
+TEST(MediaCodecBridgeTest, PresentationTimestampsDoNotDecrease) {
+  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
+
+  scoped_ptr<VideoCodecBridge> media_codec(VideoCodecBridge::CreateDecoder(
+      kCodecVP8, false, gfx::Size(320, 240), NULL, NULL));
+  EXPECT_TRUE(media_codec.get());
+  scoped_refptr<DecoderBuffer> buffer =
+      ReadTestDataFile("vp8-I-frame-320x240");
+  DecodeMediaFrame(media_codec.get(),
+                   buffer->data(),
+                   buffer->data_size(),
+                   base::TimeDelta(),
+                   base::TimeDelta());
+
+  // Simulate a seek to 10 seconds, and each chunk has 2 I-frames.
+  std::vector<uint8> chunk(buffer->data(),
+                           buffer->data() + buffer->data_size());
+  chunk.insert(chunk.end(), buffer->data(),
+               buffer->data() + buffer->data_size());
+  media_codec->Reset();
+  DecodeMediaFrame(media_codec.get(),
+                   &chunk[0],
+                   chunk.size(),
+                   base::TimeDelta::FromMicroseconds(10000000),
+                   base::TimeDelta::FromMicroseconds(9900000));
+
+  // Simulate a seek to 5 seconds.
+  media_codec->Reset();
+  DecodeMediaFrame(media_codec.get(),
+                   &chunk[0],
+                   chunk.size(),
+                   base::TimeDelta::FromMicroseconds(5000000),
+                   base::TimeDelta::FromMicroseconds(4900000));
+}
+
+TEST(MediaCodecBridgeTest, CreateUnsupportedCodec) {
+  EXPECT_EQ(NULL, AudioCodecBridge::Create(kUnknownAudioCodec));
+  EXPECT_EQ(
+      NULL,
+      VideoCodecBridge::CreateDecoder(
+          kUnknownVideoCodec, false, gfx::Size(320, 240), NULL, NULL));
+}
+
+}  // namespace media
diff --git a/media/base/android/media_codec_decoder.cc b/media/base/android/media_codec_decoder.cc
index 67d7188..cdbaf07 100644
--- a/media/base/android/media_codec_decoder.cc
+++ b/media/base/android/media_codec_decoder.cc
@@ -738,7 +738,9 @@
              << " subsamples size:" << unit->subsamples.size();
 
     status = media_codec_bridge_->QueueSecureInputBuffer(
-        index, &unit->data[0], unit->data.size(), unit->key_id, unit->iv,
+        index, &unit->data[0], unit->data.size(),
+        reinterpret_cast<const uint8_t*>(&unit->key_id[0]), unit->key_id.size(),
+        reinterpret_cast<const uint8_t*>(&unit->iv[0]), unit->iv.size(),
         unit->subsamples.empty() ? nullptr : &unit->subsamples[0],
         unit->subsamples.size(), unit->timestamp);
   }
diff --git a/media/base/android/media_codec_decoder_unittest.cc b/media/base/android/media_codec_decoder_unittest.cc
index 2b14820..322407b 100644
--- a/media/base/android/media_codec_decoder_unittest.cc
+++ b/media/base/android/media_codec_decoder_unittest.cc
@@ -7,10 +7,9 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/timer/timer.h"
 #include "media/base/android/media_codec_audio_decoder.h"
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_codec_video_decoder.h"
 #include "media/base/android/media_statistics.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/test_data_factory.h"
 #include "media/base/android/test_statistics.h"
 #include "media/base/timestamp_constants.h"
@@ -19,6 +18,15 @@
 
 namespace media {
 
+// Helper macro to skip the test if MediaCodecBridge isn't available.
+#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
+  do {                                                            \
+    if (!MediaCodecBridge::IsAvailable()) {                       \
+      VLOG(0) << "Could not run test - not supported on device."; \
+      return;                                                     \
+    }                                                             \
+  } while (0)
+
 namespace {
 
 const base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMilliseconds(200);
diff --git a/media/base/android/media_codec_player_unittest.cc b/media/base/android/media_codec_player_unittest.cc
index 628de1ce..46b95fcb 100644
--- a/media/base/android/media_codec_player_unittest.cc
+++ b/media/base/android/media_codec_player_unittest.cc
@@ -8,11 +8,10 @@
 #include "base/logging.h"
 #include "base/timer/timer.h"
 #include "media/base/android/demuxer_android.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_codec_player.h"
-#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_player_manager.h"
 #include "media/base/android/media_task_runner.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/test_data_factory.h"
 #include "media/base/android/test_statistics.h"
 #include "media/base/timestamp_constants.h"
@@ -21,6 +20,15 @@
 
 namespace media {
 
+// Helper macro to skip the test if MediaCodecBridge isn't available.
+#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
+  do {                                                            \
+    if (!MediaCodecBridge::IsAvailable()) {                       \
+      VLOG(0) << "Could not run test - not supported on device."; \
+      return;                                                     \
+    }                                                             \
+  } while (0)
+
 #define RUN_ON_MEDIA_THREAD(CLASS, METHOD, ...)                               \
   do {                                                                        \
     if (!GetMediaTaskRunner()->BelongsToCurrentThread()) {                    \
diff --git a/media/base/android/media_codec_util.cc b/media/base/android/media_codec_util.cc
deleted file mode 100644
index cb31ef9..0000000
--- a/media/base/android/media_codec_util.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2015 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 "media/base/android/media_codec_util.h"
-
-#include <algorithm>
-
-#include "base/android/build_info.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "jni/MediaCodecUtil_jni.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ConvertJavaStringToUTF8;
-using base::android::ConvertUTF8ToJavaString;
-using base::android::JavaIntArrayToIntVector;
-using base::android::ScopedJavaLocalRef;
-
-namespace media {
-
-// static
-const std::string CodecTypeToAndroidMimeType(const std::string& codec) {
-  // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"?
-  if (codec == "avc1")
-    return "video/avc";
-  if (codec == "hvc1")
-    return "video/hevc";
-  if (codec == "mp4a")
-    return "audio/mp4a-latm";
-  if (codec == "vp8" || codec == "vp8.0")
-    return "video/x-vnd.on2.vp8";
-  if (codec == "vp9" || codec == "vp9.0")
-    return "video/x-vnd.on2.vp9";
-  if (codec == "vorbis")
-    return "audio/vorbis";
-  if (codec == "opus")
-    return "audio/opus";
-  return std::string();
-}
-
-// TODO(qinmin): using a map to help all the conversions in this class.
-const std::string AndroidMimeTypeToCodecType(const std::string& mime) {
-  if (mime == "video/mp4v-es")
-    return "mp4v";
-  if (mime == "video/avc")
-    return "avc1";
-  if (mime == "video/hevc")
-    return "hvc1";
-  if (mime == "video/x-vnd.on2.vp8")
-    return "vp8";
-  if (mime == "video/x-vnd.on2.vp9")
-    return "vp9";
-  if (mime == "audio/mp4a-latm")
-    return "mp4a";
-  if (mime == "audio/mpeg")
-    return "mp3";
-  if (mime == "audio/vorbis")
-    return "vorbis";
-  if (mime == "audio/opus")
-    return "opus";
-  return std::string();
-}
-
-std::string GetDefaultCodecName(const std::string& mime_type,
-                                MediaCodecDirection direction) {
-  if (!MediaCodecUtil::IsMediaCodecAvailable())
-    return std::string();
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
-  ScopedJavaLocalRef<jstring> j_codec_name =
-      Java_MediaCodecUtil_getDefaultCodecName(env, j_mime.obj(), direction);
-  return ConvertJavaStringToUTF8(env, j_codec_name.obj());
-}
-
-bool SupportsGetName() {
-  // MediaCodec.getName() is only available on JB MR2 and greater.
-  return base::android::BuildInfo::GetInstance()->sdk_int() >= 18;
-}
-
-// Represents supported codecs on android.
-// TODO(qinmin): Currently the codecs string only contains one codec. Do we
-// need to support codecs separated by comma. (e.g. "vp8" -> "vp8, vp8.0")?
-struct CodecsInfo {
-  std::string codecs;  // E.g. "vp8" or "avc1".
-  std::string name;    // E.g. "OMX.google.vp8.decoder".
-  MediaCodecDirection direction;
-};
-
-// Get a list of supported codecs.
-std::vector<CodecsInfo> GetCodecsInfo() {
-  std::vector<CodecsInfo> codecs_info;
-  if (!MediaCodecUtil::IsMediaCodecAvailable())
-    return codecs_info;
-
-  JNIEnv* env = AttachCurrentThread();
-  std::string mime_type;
-  ScopedJavaLocalRef<jobjectArray> j_codec_info_array =
-      Java_MediaCodecUtil_getCodecsInfo(env);
-  jsize len = env->GetArrayLength(j_codec_info_array.obj());
-  for (jsize i = 0; i < len; ++i) {
-    ScopedJavaLocalRef<jobject> j_info(
-        env, env->GetObjectArrayElement(j_codec_info_array.obj(), i));
-    ScopedJavaLocalRef<jstring> j_codec_type =
-        Java_CodecInfo_codecType(env, j_info.obj());
-    ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type);
-    ScopedJavaLocalRef<jstring> j_codec_name =
-        Java_CodecInfo_codecName(env, j_info.obj());
-    CodecsInfo info;
-    info.codecs = AndroidMimeTypeToCodecType(mime_type);
-    ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name);
-    info.direction = static_cast<MediaCodecDirection>(
-        Java_CodecInfo_direction(env, j_info.obj()));
-    codecs_info.push_back(info);
-  }
-  return codecs_info;
-}
-
-// static
-bool MediaCodecUtil::IsMediaCodecAvailable() {
-  // MediaCodec is only available on JB and greater.
-  if (base::android::BuildInfo::GetInstance()->sdk_int() < 16)
-    return false;
-  // Blacklist some devices on Jellybean as for MediaCodec support is buggy.
-  // http://crbug.com/365494.
-  if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) {
-    std::string model(base::android::BuildInfo::GetInstance()->model());
-    return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000";
-  }
-  return true;
-}
-
-// static
-bool MediaCodecUtil::SupportsSetParameters() {
-  // MediaCodec.setParameters() is only available starting with K.
-  return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
-}
-
-// static
-std::set<int> MediaCodecUtil::GetEncoderColorFormats(
-    const std::string& mime_type) {
-  std::set<int> color_formats;
-  if (!IsMediaCodecAvailable())
-    return color_formats;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type);
-  ScopedJavaLocalRef<jintArray> j_color_format_array =
-      Java_MediaCodecUtil_getEncoderColorFormatsForMime(env, j_mime.obj());
-
-  if (j_color_format_array.obj()) {
-    std::vector<int> formats;
-    JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats);
-    color_formats = std::set<int>(formats.begin(), formats.end());
-  }
-
-  return color_formats;
-}
-
-// static
-bool MediaCodecUtil::CanDecode(const std::string& codec, bool is_secure) {
-  if (!IsMediaCodecAvailable())
-    return false;
-
-  JNIEnv* env = AttachCurrentThread();
-  std::string mime = CodecTypeToAndroidMimeType(codec);
-  if (mime.empty())
-    return false;
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  return Java_MediaCodecUtil_canDecode(env, j_mime.obj(), is_secure);
-}
-
-// static
-bool MediaCodecUtil::IsKnownUnaccelerated(const std::string& mime_type,
-                                          MediaCodecDirection direction) {
-  if (!IsMediaCodecAvailable())
-    return true;
-
-  std::string codec_name;
-  if (SupportsGetName()) {
-    codec_name = GetDefaultCodecName(mime_type, direction);
-  } else {
-    std::string codec_type = AndroidMimeTypeToCodecType(mime_type);
-    std::vector<CodecsInfo> codecs_info = GetCodecsInfo();
-    for (size_t i = 0; i < codecs_info.size(); ++i) {
-      if (codecs_info[i].codecs == codec_type &&
-          codecs_info[i].direction == direction) {
-        codec_name = codecs_info[i].name;
-        break;
-      }
-    }
-  }
-  DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type << " : "
-           << codec_name;
-  // It would be nice if MediaCodecInfo externalized some notion of
-  // HW-acceleration but it doesn't. Android Media guidance is that the
-  // "OMX.google" prefix is always used for SW decoders, so that's what we
-  // use. "OMX.SEC.*" codec is Samsung software implementation - report it
-  // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek
-  // devices while HW decoder video freezes and distortions are
-  // investigated - http://crbug.com/446974.
-  if (codec_name.length() > 0) {
-    return (base::StartsWith(codec_name, "OMX.google.",
-                             base::CompareCase::SENSITIVE) ||
-            base::StartsWith(codec_name, "OMX.SEC.",
-                             base::CompareCase::SENSITIVE) ||
-            base::StartsWith(codec_name, "OMX.MTK.",
-                             base::CompareCase::SENSITIVE) ||
-            base::StartsWith(codec_name, "OMX.Exynos.",
-                             base::CompareCase::SENSITIVE));
-  }
-  return true;
-}
-
-// static
-bool MediaCodecUtil::RegisterMediaCodecUtil(JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
-}  // namespace media
diff --git a/media/base/android/media_codec_util.h b/media/base/android/media_codec_util.h
deleted file mode 100644
index 604ce5d2..0000000
--- a/media/base/android/media_codec_util.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 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 MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_
-#define MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_
-
-#include <jni.h>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "media/base/media_export.h"
-
-namespace media {
-
-// Helper macro to skip the test if MediaCodecBridge isn't available.
-#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
-  do {                                                            \
-    if (!MediaCodecUtil::IsMediaCodecAvailable()) {               \
-      VLOG(0) << "Could not run test - not supported on device."; \
-      return;                                                     \
-    }                                                             \
-  } while (0)
-
-// Codec direction. Keep this in sync with MediaCodecUtil.java.
-enum MediaCodecDirection {
-  MEDIA_CODEC_DECODER,
-  MEDIA_CODEC_ENCODER,
-};
-
-class MEDIA_EXPORT MediaCodecUtil {
- public:
-  // Returns true if MediaCodec is available on the device.
-  // All other static methods check IsAvailable() internally. There's no need
-  // to check IsAvailable() explicitly before calling them.
-  static bool IsMediaCodecAvailable();
-
-  // Returns true if MediaCodec.setParameters() is available on the device.
-  static bool SupportsSetParameters();
-
-  // Returns whether MediaCodecBridge has a decoder that |is_secure| and can
-  // decode |codec| type.
-  static bool CanDecode(const std::string& codec, bool is_secure);
-
-  // Get a list of encoder supported color formats for |mime_type|.
-  // The mapping of color format name and its value refers to
-  // MediaCodecInfo.CodecCapabilities.
-  static std::set<int> GetEncoderColorFormats(const std::string& mime_type);
-
-  // Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a
-  // software codec instead of a hardware one).
-  static bool IsKnownUnaccelerated(const std::string& mime_type,
-                                   MediaCodecDirection direction);
-
-  static bool RegisterMediaCodecUtil(JNIEnv* env);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_
diff --git a/media/base/android/media_codec_video_decoder.cc b/media/base/android/media_codec_video_decoder.cc
index 928f2e7..f20bbeb 100644
--- a/media/base/android/media_codec_video_decoder.cc
+++ b/media/base/android/media_codec_video_decoder.cc
@@ -6,8 +6,8 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_statistics.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/demuxer_stream.h"
 #include "media/base/timestamp_constants.h"
 
diff --git a/media/base/android/media_decoder_job.cc b/media/base/android/media_decoder_job.cc
index 9e0a216..8689107 100644
--- a/media/base/android/media_decoder_job.cc
+++ b/media/base/android/media_decoder_job.cc
@@ -282,9 +282,13 @@
   }
 
   MediaCodecStatus status = media_codec_bridge_->QueueSecureInputBuffer(
-      input_buf_index, &unit.data[0], unit.data.size(), unit.key_id, unit.iv,
+      input_buf_index,
+      &unit.data[0], unit.data.size(),
+      reinterpret_cast<const uint8*>(&unit.key_id[0]), unit.key_id.size(),
+      reinterpret_cast<const uint8*>(&unit.iv[0]), unit.iv.size(),
       unit.subsamples.empty() ? NULL : &unit.subsamples[0],
-      unit.subsamples.size(), unit.timestamp);
+      unit.subsamples.size(),
+      unit.timestamp);
 
   // In case of MEDIA_CODEC_NO_KEY, we must reuse the |input_buf_index_|.
   // Otherwise MediaDrm will report errors.
diff --git a/media/base/android/media_jni_registrar.cc b/media/base/android/media_jni_registrar.cc
index cc8bc1d..2020469 100644
--- a/media/base/android/media_jni_registrar.cc
+++ b/media/base/android/media_jni_registrar.cc
@@ -10,11 +10,10 @@
 
 #include "media/audio/android/audio_manager_android.h"
 #include "media/audio/android/audio_record_input.h"
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_drm_bridge.h"
 #include "media/base/android/media_player_bridge.h"
 #include "media/base/android/media_player_listener.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/webaudio_media_codec_bridge.h"
 #include "media/capture/video/android/video_capture_device_android.h"
 #include "media/capture/video/android/video_capture_device_factory_android.h"
@@ -22,19 +21,24 @@
 namespace media {
 
 static base::android::RegistrationMethod kMediaRegisteredMethods[] = {
-    {"AudioManagerAndroid", AudioManagerAndroid::RegisterAudioManager},
-    {"AudioRecordInput", AudioRecordInputStream::RegisterAudioRecordInput},
-    {"MediaDrmBridge", MediaDrmBridge::RegisterMediaDrmBridge},
-    {"MediaPlayerBridge", MediaPlayerBridge::RegisterMediaPlayerBridge},
-    {"MediaPlayerListener", MediaPlayerListener::RegisterMediaPlayerListener},
-    {"SdkMediaCodecBridge", SdkMediaCodecBridge::RegisterSdkMediaCodecBridge},
-    {"MediaCodecUtil", MediaCodecUtil::RegisterMediaCodecUtil},
-    {"VideoCaptureDevice",
-     VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice},
-    {"VideoCaptureDeviceFactory",
-     VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory},
-    {"WebAudioMediaCodecBridge",
-     WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge},
+  { "AudioManagerAndroid",
+    AudioManagerAndroid::RegisterAudioManager },
+  { "AudioRecordInput",
+    AudioRecordInputStream::RegisterAudioRecordInput },
+  { "MediaCodecBridge",
+    MediaCodecBridge::RegisterMediaCodecBridge },
+  { "MediaDrmBridge",
+    MediaDrmBridge::RegisterMediaDrmBridge },
+  { "MediaPlayerBridge",
+    MediaPlayerBridge::RegisterMediaPlayerBridge },
+  { "MediaPlayerListener",
+    MediaPlayerListener::RegisterMediaPlayerListener },
+  { "VideoCaptureDevice",
+    VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice },
+  { "VideoCaptureDeviceFactory",
+    VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory },
+  { "WebAudioMediaCodecBridge",
+    WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge },
 };
 
 bool RegisterJni(JNIEnv* env) {
diff --git a/media/base/android/media_source_player_unittest.cc b/media/base/android/media_source_player_unittest.cc
index b7cab6c..fd4a725 100644
--- a/media/base/android/media_source_player_unittest.cc
+++ b/media/base/android/media_source_player_unittest.cc
@@ -9,12 +9,11 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/stringprintf.h"
 #include "media/base/android/audio_decoder_job.h"
-#include "media/base/android/media_codec_util.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_drm_bridge.h"
 #include "media/base/android/media_player_manager.h"
 #include "media/base/android/media_source_player.h"
 #include "media/base/android/media_url_interceptor.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
 #include "media/base/android/video_decoder_job.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/decoder_buffer.h"
@@ -25,6 +24,15 @@
 
 namespace media {
 
+// Helper macro to skip the test if MediaCodecBridge isn't available.
+#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
+  do {                                                            \
+    if (!MediaCodecBridge::IsAvailable()) {                       \
+      VLOG(0) << "Could not run test - not supported on device."; \
+      return;                                                     \
+    }                                                             \
+  } while (0)
+
 const base::TimeDelta kDefaultDuration =
     base::TimeDelta::FromMilliseconds(10000);
 
diff --git a/media/base/android/ndk_media_codec_bridge.cc b/media/base/android/ndk_media_codec_bridge.cc
deleted file mode 100644
index 2ce2a0f..0000000
--- a/media/base/android/ndk_media_codec_bridge.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2015 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 "media/base/android/ndk_media_codec_bridge.h"
-
-#include <media/NdkMediaError.h>
-#include <media/NdkMediaFormat.h>
-
-#include <limits>
-
-#include "base/strings/string_util.h"
-#include "media/base/decrypt_config.h"
-
-namespace {
-const char kMediaFormatKeyCropLeft[] = "crop-left";
-const char kMediaFormatKeyCropRight[] = "crop-right";
-const char kMediaFormatKeyCropBottom[] = "crop-bottom";
-const char kMediaFormatKeyCropTop[] = "crop-top";
-}
-
-namespace media {
-
-// Translate media_status_t to MediaCodecStatus.
-static MediaCodecStatus TranslateMediaCodecStatus(media_status_t status) {
-  switch (status) {
-    case AMEDIA_OK:
-      return MEDIA_CODEC_OK;
-    case AMEDIA_DRM_NEED_KEY:
-      return MEDIA_CODEC_NO_KEY;
-    default:
-      return MEDIA_CODEC_ERROR;
-  }
-}
-
-NdkMediaCodecBridge::~NdkMediaCodecBridge() {}
-
-NdkMediaCodecBridge::NdkMediaCodecBridge(const std::string& mime,
-                                         bool is_secure,
-                                         MediaCodecDirection direction) {
-  if (base::StartsWith(mime, "video", base::CompareCase::SENSITIVE) &&
-      is_secure && direction == MEDIA_CODEC_DECODER) {
-    // TODO(qinmin): get the secure decoder name from java.
-    NOTIMPLEMENTED();
-    return;
-  }
-
-  if (direction == MEDIA_CODEC_DECODER)
-    media_codec_.reset(AMediaCodec_createDecoderByType(mime.c_str()));
-  else
-    media_codec_.reset(AMediaCodec_createEncoderByType(mime.c_str()));
-}
-
-MediaCodecStatus NdkMediaCodecBridge::Reset() {
-  media_status_t status = AMediaCodec_flush(media_codec_.get());
-  return TranslateMediaCodecStatus(status);
-}
-
-bool NdkMediaCodecBridge::Start() {
-  return AMEDIA_OK == AMediaCodec_start(media_codec_.get());
-}
-
-void NdkMediaCodecBridge::Stop() {
-  AMediaCodec_stop(media_codec_.get());
-}
-
-void NdkMediaCodecBridge::GetOutputFormat(int* width, int* height) {
-  AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
-  int left, right, bottom, top;
-  bool has_left = AMediaFormat_getInt32(format, kMediaFormatKeyCropLeft, &left);
-  bool has_right =
-      AMediaFormat_getInt32(format, kMediaFormatKeyCropRight, &right);
-  bool has_bottom =
-      AMediaFormat_getInt32(format, kMediaFormatKeyCropBottom, &bottom);
-  bool has_top = AMediaFormat_getInt32(format, kMediaFormatKeyCropTop, &top);
-  if (has_left && has_right && has_bottom && has_top) {
-    // Use crop size as it is more accurate. right and bottom are inclusive.
-    *width = right - left + 1;
-    *height = top - bottom + 1;
-  } else {
-    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
-    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
-  }
-}
-
-int NdkMediaCodecBridge::GetOutputSamplingRate() {
-  AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
-  int sample_rate = 0;
-  AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sample_rate);
-  DCHECK(sample_rate != 0);
-  return sample_rate;
-}
-
-MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer(
-    int index,
-    const uint8_t* data,
-    size_t data_size,
-    const base::TimeDelta& presentation_time) {
-  if (data_size >
-      base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
-    return MEDIA_CODEC_ERROR;
-  }
-  if (data && !FillInputBuffer(index, data, data_size))
-    return MEDIA_CODEC_ERROR;
-
-  media_status_t status =
-      AMediaCodec_queueInputBuffer(media_codec_.get(), index, 0, data_size,
-                                   presentation_time.InMicroseconds(), 0);
-  return TranslateMediaCodecStatus(status);
-}
-
-MediaCodecStatus NdkMediaCodecBridge::QueueSecureInputBuffer(
-    int index,
-    const uint8_t* data,
-    size_t data_size,
-    const std::vector<char>& key_id,
-    const std::vector<char>& iv,
-    const SubsampleEntry* subsamples,
-    int subsamples_size,
-    const base::TimeDelta& presentation_time) {
-  if (data_size >
-      base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
-    return MEDIA_CODEC_ERROR;
-  }
-  if (key_id.size() > 16 || iv.size())
-    return MEDIA_CODEC_ERROR;
-  if (data && !FillInputBuffer(index, data, data_size))
-    return MEDIA_CODEC_ERROR;
-
-  int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
-  std::vector<size_t> clear_data, encrypted_data;
-  if (subsamples_size == 0) {
-    DCHECK(!subsamples);
-    clear_data.push_back(0);
-    encrypted_data.push_back(data_size);
-  } else {
-    DCHECK_GT(subsamples_size, 0);
-    DCHECK(subsamples);
-    for (int i = 0; i < subsamples_size; ++i) {
-      DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16_t>::max());
-      if (subsamples[i].cypher_bytes >
-          static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
-        return MEDIA_CODEC_ERROR;
-      }
-      clear_data.push_back(subsamples[i].clear_bytes);
-      encrypted_data.push_back(subsamples[i].cypher_bytes);
-    }
-  }
-
-  AMediaCodecCryptoInfo* crypto_info = AMediaCodecCryptoInfo_new(
-      new_subsamples_size,
-      reinterpret_cast<uint8_t*>(const_cast<char*>(key_id.data())),
-      reinterpret_cast<uint8_t*>(const_cast<char*>(iv.data())),
-      AMEDIACODECRYPTOINFO_MODE_AES_CTR, clear_data.data(),
-      encrypted_data.data());
-
-  media_status_t status = AMediaCodec_queueSecureInputBuffer(
-      media_codec_.get(), index, 0, crypto_info,
-      presentation_time.InMicroseconds(), 0);
-  return TranslateMediaCodecStatus(status);
-}
-
-void NdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
-  AMediaCodec_queueInputBuffer(media_codec_.get(), input_buffer_index, 0, 0, 0,
-                               AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
-}
-
-MediaCodecStatus NdkMediaCodecBridge::DequeueInputBuffer(
-    const base::TimeDelta& timeout,
-    int* index) {
-  *index = AMediaCodec_dequeueInputBuffer(media_codec_.get(),
-                                          timeout.InMicroseconds());
-  if (*index >= 0)
-    return MEDIA_CODEC_OK;
-  else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
-    return MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER;
-  else
-    return MEDIA_CODEC_ERROR;
-}
-
-MediaCodecStatus NdkMediaCodecBridge::DequeueOutputBuffer(
-    const base::TimeDelta& timeout,
-    int* index,
-    size_t* offset,
-    size_t* size,
-    base::TimeDelta* presentation_time,
-    bool* end_of_stream,
-    bool* key_frame) {
-  AMediaCodecBufferInfo buffer_info;
-  *index = AMediaCodec_dequeueOutputBuffer(media_codec_.get(), &buffer_info,
-                                           timeout.InMicroseconds());
-  *offset = buffer_info.offset;
-  *size = buffer_info.size;
-  *presentation_time =
-      base::TimeDelta::FromMicroseconds(buffer_info.presentationTimeUs);
-  if (end_of_stream)
-    *end_of_stream = buffer_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
-  if (key_frame)
-    *key_frame = false;  // This is deprecated.
-  if (*index >= 0)
-    return MEDIA_CODEC_OK;
-  else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
-    return MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER;
-  else
-    return MEDIA_CODEC_ERROR;
-}
-
-void NdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
-  AMediaCodec_releaseOutputBuffer(media_codec_.get(), index, render);
-}
-
-void NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
-                                         uint8_t** data,
-                                         size_t* capacity) {
-  *data = AMediaCodec_getInputBuffer(media_codec_.get(), input_buffer_index,
-                                     capacity);
-}
-
-bool NdkMediaCodecBridge::CopyFromOutputBuffer(int index,
-                                               size_t offset,
-                                               void* dst,
-                                               int dst_size) {
-  size_t capacity;
-  uint8_t* src_data =
-      AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity);
-
-  if (capacity < offset || capacity - offset < static_cast<size_t>(dst_size))
-    return false;
-
-  memcpy(dst, src_data + offset, dst_size);
-  return true;
-}
-
-}  // namespace media
diff --git a/media/base/android/ndk_media_codec_bridge.h b/media/base/android/ndk_media_codec_bridge.h
deleted file mode 100644
index d16d6f8..0000000
--- a/media/base/android/ndk_media_codec_bridge.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 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 MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_
-#define MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_
-
-#include <media/NdkMediaCodec.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "media/base/android/media_codec_bridge.h"
-#include "media/base/media_export.h"
-
-namespace media {
-
-class MEDIA_EXPORT NdkMediaCodecBridge : public MediaCodecBridge {
- public:
-  ~NdkMediaCodecBridge() override;
-
-  // MediaCodecBridge implementation.
-  MediaCodecStatus Reset() override;
-  bool Start() override;
-  void Stop() override;
-  void GetOutputFormat(int* width, int* height) override;
-  int GetOutputSamplingRate() override;
-  MediaCodecStatus QueueInputBuffer(
-      int index,
-      const uint8_t* data,
-      size_t data_size,
-      const base::TimeDelta& presentation_time) override;
-  using MediaCodecBridge::QueueSecureInputBuffer;
-  MediaCodecStatus QueueSecureInputBuffer(
-      int index,
-      const uint8_t* data,
-      size_t data_size,
-      const std::vector<char>& key_id,
-      const std::vector<char>& iv,
-      const SubsampleEntry* subsamples,
-      int subsamples_size,
-      const base::TimeDelta& presentation_time) override;
-  void QueueEOS(int input_buffer_index);
-  MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
-                                      int* index) override;
-  MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout,
-                                       int* index,
-                                       size_t* offset,
-                                       size_t* size,
-                                       base::TimeDelta* presentation_time,
-                                       bool* end_of_stream,
-                                       bool* key_frame) override;
-  void ReleaseOutputBuffer(int index, bool render) override;
-  void GetInputBuffer(int input_buffer_index,
-                      uint8_t** data,
-                      size_t* capacity) override;
-  bool CopyFromOutputBuffer(int index,
-                            size_t offset,
-                            void* dst,
-                            int dst_size) override;
-
- protected:
-  NdkMediaCodecBridge(const std::string& mime,
-                      bool is_secure,
-                      MediaCodecDirection direction);
-
- private:
-  struct AMediaCodecDeleter {
-    inline void operator()(AMediaCodec* ptr) const { AMediaCodec_delete(ptr); }
-  };
-
-  scoped_ptr<AMediaCodec, AMediaCodecDeleter> media_codec_;
-
-  DISALLOW_COPY_AND_ASSIGN(NdkMediaCodecBridge);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/sdk_media_codec_bridge.cc b/media/base/android/sdk_media_codec_bridge.cc
deleted file mode 100644
index 0c6e25f..0000000
--- a/media/base/android/sdk_media_codec_bridge.cc
+++ /dev/null
@@ -1,643 +0,0 @@
-// Copyright (c) 2013 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 "media/base/android/sdk_media_codec_bridge.h"
-
-#include <algorithm>
-#include <limits>
-
-#include "base/android/build_info.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_util.h"
-#include "jni/MediaCodecBridge_jni.h"
-#include "media/base/bit_reader.h"
-#include "media/base/decrypt_config.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ConvertJavaStringToUTF8;
-using base::android::ConvertUTF8ToJavaString;
-using base::android::JavaIntArrayToIntVector;
-using base::android::ScopedJavaLocalRef;
-
-#define RETURN_ON_ERROR(condition)                             \
-  do {                                                         \
-    if (!(condition)) {                                        \
-      LOG(ERROR) << "Unable to parse AAC header: " #condition; \
-      return false;                                            \
-    }                                                          \
-  } while (0)
-
-namespace media {
-
-enum {
-  kBufferFlagSyncFrame = 1,    // BUFFER_FLAG_SYNC_FRAME
-  kBufferFlagEndOfStream = 4,  // BUFFER_FLAG_END_OF_STREAM
-  kConfigureFlagEncode = 1,    // CONFIGURE_FLAG_ENCODE
-};
-
-static ScopedJavaLocalRef<jintArray>
-ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) {
-  ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size));
-  env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get());
-  return j_array;
-}
-
-static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) {
-  switch (codec) {
-    case kCodecMP3:
-      return "audio/mpeg";
-    case kCodecVorbis:
-      return "audio/vorbis";
-    case kCodecOpus:
-      return "audio/opus";
-    case kCodecAAC:
-      return "audio/mp4a-latm";
-    default:
-      return std::string();
-  }
-}
-
-static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) {
-  switch (codec) {
-    case kCodecH264:
-      return "video/avc";
-    case kCodecHEVC:
-      return "video/hevc";
-    case kCodecVP8:
-      return "video/x-vnd.on2.vp8";
-    case kCodecVP9:
-      return "video/x-vnd.on2.vp9";
-    default:
-      return std::string();
-  }
-}
-
-SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime,
-                                         bool is_secure,
-                                         MediaCodecDirection direction) {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-  DCHECK(!mime.empty());
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  j_media_codec_.Reset(
-      Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction));
-}
-
-SdkMediaCodecBridge::~SdkMediaCodecBridge() {
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-  if (j_media_codec_.obj())
-    Java_MediaCodecBridge_release(env, j_media_codec_.obj());
-}
-
-MediaCodecStatus SdkMediaCodecBridge::Reset() {
-  JNIEnv* env = AttachCurrentThread();
-  return static_cast<MediaCodecStatus>(
-      Java_MediaCodecBridge_flush(env, j_media_codec_.obj()));
-}
-
-bool SdkMediaCodecBridge::Start() {
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_start(env, j_media_codec_.obj());
-}
-
-void SdkMediaCodecBridge::Stop() {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_stop(env, j_media_codec_.obj());
-}
-
-void SdkMediaCodecBridge::GetOutputFormat(int* width, int* height) {
-  JNIEnv* env = AttachCurrentThread();
-
-  *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj());
-  *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj());
-}
-
-int SdkMediaCodecBridge::GetOutputSamplingRate() {
-  JNIEnv* env = AttachCurrentThread();
-
-  return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj());
-}
-
-MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer(
-    int index,
-    const uint8_t* data,
-    size_t data_size,
-    const base::TimeDelta& presentation_time) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
-  if (data_size >
-      base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
-    return MEDIA_CODEC_ERROR;
-  }
-  if (data && !FillInputBuffer(index, data, data_size))
-    return MEDIA_CODEC_ERROR;
-  JNIEnv* env = AttachCurrentThread();
-  return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer(
-      env, j_media_codec_.obj(), index, 0, data_size,
-      presentation_time.InMicroseconds(), 0));
-}
-
-// TODO(timav): Combine this and above methods together keeping only the first
-// interface after we switch to Spitzer pipeline.
-MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer(
-    int index,
-    const uint8_t* data,
-    size_t data_size,
-    const std::vector<char>& key_id,
-    const std::vector<char>& iv,
-    const SubsampleEntry* subsamples,
-    int subsamples_size,
-    const base::TimeDelta& presentation_time) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size;
-  if (data_size >
-      base::checked_cast<size_t>(std::numeric_limits<int32_t>::max())) {
-    return MEDIA_CODEC_ERROR;
-  }
-  if (data && !FillInputBuffer(index, data, data_size))
-    return MEDIA_CODEC_ERROR;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jbyteArray> j_key_id = base::android::ToJavaByteArray(
-      env, reinterpret_cast<const uint8_t*>(key_id.data()), key_id.size());
-  ScopedJavaLocalRef<jbyteArray> j_iv = base::android::ToJavaByteArray(
-      env, reinterpret_cast<const uint8_t*>(iv.data()), iv.size());
-
-  // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array|
-  // to indicate that all data is encrypted. But it doesn't specify what
-  // |cypher_array| and |subsamples_size| should be in that case. Passing
-  // one subsample here just to be on the safe side.
-  int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size;
-
-  scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]);
-  scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]);
-
-  if (subsamples_size == 0) {
-    DCHECK(!subsamples);
-    native_clear_array[0] = 0;
-    native_cypher_array[0] = data_size;
-  } else {
-    DCHECK_GT(subsamples_size, 0);
-    DCHECK(subsamples);
-    for (int i = 0; i < subsamples_size; ++i) {
-      DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16_t>::max());
-      if (subsamples[i].cypher_bytes >
-          static_cast<uint32_t>(std::numeric_limits<jint>::max())) {
-        return MEDIA_CODEC_ERROR;
-      }
-
-      native_clear_array[i] = subsamples[i].clear_bytes;
-      native_cypher_array[i] = subsamples[i].cypher_bytes;
-    }
-  }
-
-  ScopedJavaLocalRef<jintArray> clear_array =
-      ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size);
-  ScopedJavaLocalRef<jintArray> cypher_array =
-      ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size);
-
-  return static_cast<MediaCodecStatus>(
-      Java_MediaCodecBridge_queueSecureInputBuffer(
-          env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(),
-          clear_array.obj(), cypher_array.obj(), new_subsamples_size,
-          presentation_time.InMicroseconds()));
-}
-
-void SdkMediaCodecBridge::QueueEOS(int input_buffer_index) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index;
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_queueInputBuffer(env, j_media_codec_.obj(),
-                                         input_buffer_index, 0, 0, 0,
-                                         kBufferFlagEndOfStream);
-}
-
-MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer(
-    const base::TimeDelta& timeout,
-    int* index) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer(
-      env, j_media_codec_.obj(), timeout.InMicroseconds());
-  *index = Java_DequeueInputResult_index(env, result.obj());
-  MediaCodecStatus status = static_cast<MediaCodecStatus>(
-      Java_DequeueInputResult_status(env, result.obj()));
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
-           << ", index: " << *index;
-  return status;
-}
-
-MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer(
-    const base::TimeDelta& timeout,
-    int* index,
-    size_t* offset,
-    size_t* size,
-    base::TimeDelta* presentation_time,
-    bool* end_of_stream,
-    bool* key_frame) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> result =
-      Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_.obj(),
-                                                timeout.InMicroseconds());
-  *index = Java_DequeueOutputResult_index(env, result.obj());
-  *offset = base::checked_cast<size_t>(
-      Java_DequeueOutputResult_offset(env, result.obj()));
-  *size = base::checked_cast<size_t>(
-      Java_DequeueOutputResult_numBytes(env, result.obj()));
-  if (presentation_time) {
-    *presentation_time = base::TimeDelta::FromMicroseconds(
-        Java_DequeueOutputResult_presentationTimeMicroseconds(env,
-                                                              result.obj()));
-  }
-  int flags = Java_DequeueOutputResult_flags(env, result.obj());
-  if (end_of_stream)
-    *end_of_stream = flags & kBufferFlagEndOfStream;
-  if (key_frame)
-    *key_frame = flags & kBufferFlagSyncFrame;
-  MediaCodecStatus status = static_cast<MediaCodecStatus>(
-      Java_DequeueOutputResult_status(env, result.obj()));
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status
-           << ", index: " << *index << ", offset: " << *offset
-           << ", size: " << *size << ", flags: " << flags;
-  return status;
-}
-
-void SdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) {
-  DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index;
-  JNIEnv* env = AttachCurrentThread();
-  CHECK(env);
-
-  Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_.obj(), index,
-                                            render);
-}
-
-int SdkMediaCodecBridge::GetOutputBuffersCount() {
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj());
-}
-
-size_t SdkMediaCodecBridge::GetOutputBuffersCapacity() {
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_getOutputBuffersCapacity(env,
-                                                        j_media_codec_.obj());
-}
-
-void SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
-                                         uint8_t** data,
-                                         size_t* capacity) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer(
-      env, j_media_codec_.obj(), input_buffer_index));
-  *data = static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj()));
-  *capacity =
-      base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj()));
-}
-
-bool SdkMediaCodecBridge::CopyFromOutputBuffer(int index,
-                                               size_t offset,
-                                               void* dst,
-                                               int dst_size) {
-  void* src_data = nullptr;
-  size_t src_capacity = GetOutputBufferAddress(index, offset, &src_data);
-  if (src_capacity < offset ||
-      src_capacity - offset < static_cast<size_t>(dst_size)) {
-    return false;
-  }
-  memcpy(dst, static_cast<uint8_t*>(src_data) + offset, dst_size);
-  return true;
-}
-
-int SdkMediaCodecBridge::GetOutputBufferAddress(int index,
-                                                size_t offset,
-                                                void** addr) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> j_buffer(
-      Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
-  *addr =
-      reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())) +
-      offset;
-  return env->GetDirectBufferCapacity(j_buffer.obj()) - offset;
-}
-
-// static
-bool SdkMediaCodecBridge::RegisterSdkMediaCodecBridge(JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
-// static
-AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) {
-  if (!MediaCodecUtil::IsMediaCodecAvailable())
-    return nullptr;
-
-  const std::string mime = AudioCodecToAndroidMimeType(codec);
-  return mime.empty() ? nullptr : new AudioCodecBridge(mime);
-}
-
-// static
-bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) {
-  return MediaCodecUtil::IsKnownUnaccelerated(
-      AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER);
-}
-
-AudioCodecBridge::AudioCodecBridge(const std::string& mime)
-    // Audio codec doesn't care about security level and there is no need for
-    // audio encoding yet.
-    : SdkMediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {}
-
-bool AudioCodecBridge::ConfigureAndStart(const AudioCodec& codec,
-                                         int sample_rate,
-                                         int channel_count,
-                                         const uint8_t* extra_data,
-                                         size_t extra_data_size,
-                                         int64_t codec_delay_ns,
-                                         int64_t seek_preroll_ns,
-                                         bool play_audio,
-                                         jobject media_crypto) {
-  JNIEnv* env = AttachCurrentThread();
-
-  if (!media_codec())
-    return false;
-
-  std::string codec_string = AudioCodecToAndroidMimeType(codec);
-  if (codec_string.empty())
-    return false;
-
-  ScopedJavaLocalRef<jstring> j_mime =
-      ConvertUTF8ToJavaString(env, codec_string);
-  ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat(
-      env, j_mime.obj(), sample_rate, channel_count));
-  DCHECK(!j_format.is_null());
-
-  if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size,
-                            codec_delay_ns, seek_preroll_ns)) {
-    return false;
-  }
-
-  if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format.obj(),
-                                            media_crypto, 0, play_audio)) {
-    return false;
-  }
-
-  return Start();
-}
-
-bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
-                                            const AudioCodec& codec,
-                                            const uint8_t* extra_data,
-                                            size_t extra_data_size,
-                                            int64_t codec_delay_ns,
-                                            int64_t seek_preroll_ns) {
-  if (extra_data_size == 0 && codec != kCodecOpus)
-    return true;
-
-  JNIEnv* env = AttachCurrentThread();
-  switch (codec) {
-    case kCodecVorbis: {
-      if (extra_data[0] != 2) {
-        LOG(ERROR) << "Invalid number of vorbis headers before the codec "
-                   << "header: " << extra_data[0];
-        return false;
-      }
-
-      size_t header_length[2];
-      // |total_length| keeps track of the total number of bytes before the last
-      // header.
-      size_t total_length = 1;
-      const uint8_t* current_pos = extra_data;
-      // Calculate the length of the first 2 headers.
-      for (int i = 0; i < 2; ++i) {
-        header_length[i] = 0;
-        while (total_length < extra_data_size) {
-          size_t size = *(++current_pos);
-          total_length += 1 + size;
-          if (total_length > 0x80000000) {
-            LOG(ERROR) << "Vorbis header size too large";
-            return false;
-          }
-          header_length[i] += size;
-          if (size < 0xFF)
-            break;
-        }
-        if (total_length >= extra_data_size) {
-          LOG(ERROR) << "Invalid vorbis header size in the extra data";
-          return false;
-        }
-      }
-      current_pos++;
-      // The first header is identification header.
-      ScopedJavaLocalRef<jbyteArray> first_header =
-          base::android::ToJavaByteArray(env, current_pos, header_length[0]);
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0,
-                                                 first_header.obj());
-      // The last header is codec header.
-      ScopedJavaLocalRef<jbyteArray> last_header =
-          base::android::ToJavaByteArray(env, extra_data + total_length,
-                                         extra_data_size - total_length);
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1,
-                                                 last_header.obj());
-      break;
-    }
-    case kCodecAAC: {
-      media::BitReader reader(extra_data, extra_data_size);
-
-      // The following code is copied from aac.cc
-      // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
-      uint8_t profile = 0;
-      uint8_t frequency_index = 0;
-      uint8_t channel_config = 0;
-      RETURN_ON_ERROR(reader.ReadBits(5, &profile));
-      RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
-
-      if (0xf == frequency_index)
-        RETURN_ON_ERROR(reader.SkipBits(24));
-      RETURN_ON_ERROR(reader.ReadBits(4, &channel_config));
-
-      if (profile == 5 || profile == 29) {
-        // Read extension config.
-        RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
-        if (frequency_index == 0xf)
-          RETURN_ON_ERROR(reader.SkipBits(24));
-        RETURN_ON_ERROR(reader.ReadBits(5, &profile));
-      }
-
-      if (profile < 1 || profile > 4 || frequency_index == 0xf ||
-          channel_config > 7) {
-        LOG(ERROR) << "Invalid AAC header";
-        return false;
-      }
-      const size_t kCsdLength = 2;
-      uint8_t csd[kCsdLength];
-      csd[0] = profile << 3 | frequency_index >> 1;
-      csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3;
-      ScopedJavaLocalRef<jbyteArray> byte_array =
-          base::android::ToJavaByteArray(env, csd, kCsdLength);
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0,
-                                                 byte_array.obj());
-
-      // TODO(qinmin): pass an extra variable to this function to determine
-      // whether we need to call this.
-      Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format);
-      break;
-    }
-    case kCodecOpus: {
-      if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 ||
-          seek_preroll_ns < 0) {
-        LOG(ERROR) << "Invalid Opus Header";
-        return false;
-      }
-
-      // csd0 - Opus Header
-      ScopedJavaLocalRef<jbyteArray> csd0 =
-          base::android::ToJavaByteArray(env, extra_data, extra_data_size);
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj());
-
-      // csd1 - Codec Delay
-      ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray(
-          env, reinterpret_cast<const uint8_t*>(&codec_delay_ns),
-          sizeof(int64_t));
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj());
-
-      // csd2 - Seek Preroll
-      ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray(
-          env, reinterpret_cast<const uint8_t*>(&seek_preroll_ns),
-          sizeof(int64_t));
-      Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj());
-      break;
-    }
-    default:
-      LOG(ERROR) << "Invalid header encountered for codec: "
-                 << AudioCodecToAndroidMimeType(codec);
-      return false;
-  }
-  return true;
-}
-
-int64_t AudioCodecBridge::PlayOutputBuffer(int index,
-                                           size_t size,
-                                           size_t offset,
-                                           bool postpone) {
-  DCHECK_LE(0, index);
-  int numBytes = base::checked_cast<int>(size);
-
-  void* buffer = nullptr;
-  int capacity = GetOutputBufferAddress(index, offset, &buffer);
-  numBytes = std::min(capacity, numBytes);
-  CHECK_GE(numBytes, 0);
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray(
-      env, static_cast<uint8_t*>(buffer), numBytes);
-  return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(),
-                                                byte_array.obj(), postpone);
-}
-
-void AudioCodecBridge::SetVolume(double volume) {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_setVolume(env, media_codec(), volume);
-}
-
-// static
-bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec,
-                                            MediaCodecDirection direction) {
-  return MediaCodecUtil::IsKnownUnaccelerated(
-      VideoCodecToAndroidMimeType(codec), direction);
-}
-
-// static
-VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec,
-                                                  bool is_secure,
-                                                  const gfx::Size& size,
-                                                  jobject surface,
-                                                  jobject media_crypto) {
-  if (!MediaCodecUtil::IsMediaCodecAvailable())
-    return nullptr;
-
-  const std::string mime = VideoCodecToAndroidMimeType(codec);
-  if (mime.empty())
-    return nullptr;
-
-  scoped_ptr<VideoCodecBridge> bridge(
-      new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER));
-  if (!bridge->media_codec())
-    return nullptr;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  ScopedJavaLocalRef<jobject> j_format(
-      Java_MediaCodecBridge_createVideoDecoderFormat(
-          env, j_mime.obj(), size.width(), size.height()));
-  DCHECK(!j_format.is_null());
-  if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(),
-                                            j_format.obj(), surface,
-                                            media_crypto, 0)) {
-    return nullptr;
-  }
-
-  return bridge->Start() ? bridge.release() : nullptr;
-}
-
-// static
-VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec,
-                                                  const gfx::Size& size,
-                                                  int bit_rate,
-                                                  int frame_rate,
-                                                  int i_frame_interval,
-                                                  int color_format) {
-  if (!MediaCodecUtil::IsMediaCodecAvailable())
-    return nullptr;
-
-  const std::string mime = VideoCodecToAndroidMimeType(codec);
-  if (mime.empty())
-    return nullptr;
-
-  scoped_ptr<VideoCodecBridge> bridge(
-      new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER));
-  if (!bridge->media_codec())
-    return nullptr;
-
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
-  ScopedJavaLocalRef<jobject> j_format(
-      Java_MediaCodecBridge_createVideoEncoderFormat(
-          env, j_mime.obj(), size.width(), size.height(), bit_rate, frame_rate,
-          i_frame_interval, color_format));
-  DCHECK(!j_format.is_null());
-  if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(),
-                                            j_format.obj(), nullptr, nullptr,
-                                            kConfigureFlagEncode)) {
-    return nullptr;
-  }
-
-  return bridge->Start() ? bridge.release() : nullptr;
-}
-
-VideoCodecBridge::VideoCodecBridge(const std::string& mime,
-                                   bool is_secure,
-                                   MediaCodecDirection direction)
-    : SdkMediaCodecBridge(mime, is_secure, direction),
-      adaptive_playback_supported_for_testing_(-1) {}
-
-void VideoCodecBridge::SetVideoBitrate(int bps) {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps);
-}
-
-void VideoCodecBridge::RequestKeyFrameSoon() {
-  JNIEnv* env = AttachCurrentThread();
-  Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec());
-}
-
-bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) {
-  if (adaptive_playback_supported_for_testing_ == 0)
-    return false;
-  else if (adaptive_playback_supported_for_testing_ > 0)
-    return true;
-  JNIEnv* env = AttachCurrentThread();
-  return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(),
-                                                           width, height);
-}
-
-}  // namespace media
diff --git a/media/base/android/sdk_media_codec_bridge.h b/media/base/android/sdk_media_codec_bridge.h
deleted file mode 100644
index c495ffc9..0000000
--- a/media/base/android/sdk_media_codec_bridge.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (c) 2013 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 MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
-#define MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
-
-#include <jni.h>
-#include <stdint.h>
-
-#include <set>
-#include <string>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "media/base/android/media_codec_bridge.h"
-#include "media/base/audio_decoder_config.h"
-#include "media/base/media_export.h"
-#include "media/base/video_decoder_config.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace media {
-
-// This class implements MediaCodecBridge using android MediaCodec SDK APIs.
-class MEDIA_EXPORT SdkMediaCodecBridge : public MediaCodecBridge {
- public:
-  ~SdkMediaCodecBridge() override;
-
-  // MediaCodecBridge implementations.
-  MediaCodecStatus Reset() override;
-  bool Start() override;
-  void Stop() override;
-  void GetOutputFormat(int* width, int* height) override;
-  int GetOutputSamplingRate() override;
-  MediaCodecStatus QueueInputBuffer(
-      int index,
-      const uint8_t* data,
-      size_t data_size,
-      const base::TimeDelta& presentation_time) override;
-  using MediaCodecBridge::QueueSecureInputBuffer;
-  MediaCodecStatus QueueSecureInputBuffer(
-      int index,
-      const uint8_t* data,
-      size_t data_size,
-      const std::vector<char>& key_id,
-      const std::vector<char>& iv,
-      const SubsampleEntry* subsamples,
-      int subsamples_size,
-      const base::TimeDelta& presentation_time) override;
-  void QueueEOS(int input_buffer_index) override;
-  MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout,
-                                      int* index) override;
-  MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout,
-                                       int* index,
-                                       size_t* offset,
-                                       size_t* size,
-                                       base::TimeDelta* presentation_time,
-                                       bool* end_of_stream,
-                                       bool* key_frame) override;
-  void ReleaseOutputBuffer(int index, bool render) override;
-  int GetOutputBuffersCount() override;
-  size_t GetOutputBuffersCapacity() override;
-  void GetInputBuffer(int input_buffer_index,
-                      uint8_t** data,
-                      size_t* capacity) override;
-  bool CopyFromOutputBuffer(int index,
-                            size_t offset,
-                            void* dst,
-                            int dst_size) override;
-
-  static bool RegisterSdkMediaCodecBridge(JNIEnv* env);
-
- protected:
-  SdkMediaCodecBridge(const std::string& mime,
-                      bool is_secure,
-                      MediaCodecDirection direction);
-
-  // Called to get the buffer address given the output buffer index and offset.
-  // This function returns the size of the output and |addr| is the pointer to
-  // the address to read.
-  int GetOutputBufferAddress(int index, size_t offset, void** addr);
-
-  jobject media_codec() { return j_media_codec_.obj(); }
-  MediaCodecDirection direction_;
-
- private:
-  // Java MediaCodec instance.
-  base::android::ScopedJavaGlobalRef<jobject> j_media_codec_;
-
-  DISALLOW_COPY_AND_ASSIGN(SdkMediaCodecBridge);
-};
-
-// Class for handling audio decoding using android MediaCodec APIs.
-// TODO(qinmin): implement the logic to switch between NDK and SDK
-// MediaCodecBridge.
-class MEDIA_EXPORT AudioCodecBridge : public SdkMediaCodecBridge {
- public:
-  // Returns an AudioCodecBridge instance if |codec| is supported, or a NULL
-  // pointer otherwise.
-  static AudioCodecBridge* Create(const AudioCodec& codec);
-
-  // See MediaCodecUtil::IsKnownUnaccelerated().
-  static bool IsKnownUnaccelerated(const AudioCodec& codec);
-
-  // Start the audio codec bridge.
-  bool ConfigureAndStart(const AudioCodec& codec,
-                         int sample_rate,
-                         int channel_count,
-                         const uint8_t* extra_data,
-                         size_t extra_data_size,
-                         int64_t codec_delay_ns,
-                         int64_t seek_preroll_ns,
-                         bool play_audio,
-                         jobject media_crypto) WARN_UNUSED_RESULT;
-
-  // Plays the output buffer right away or save for later playback if |postpone|
-  // is set to true. This call must be called after DequeueOutputBuffer() and
-  // before ReleaseOutputBuffer. The data is extracted from the output buffers
-  // using |index|, |size| and |offset|. Returns the playback head position
-  // expressed in frames.
-  // When |postpone| is set to true, the next PlayOutputBuffer() should have
-  // postpone == false, and it will play two buffers: the postponed one and
-  // the one identified by |index|.
-  int64_t PlayOutputBuffer(int index,
-                           size_t size,
-                           size_t offset,
-                           bool postpone = false);
-
-  // Set the volume of the audio output.
-  void SetVolume(double volume);
-
- private:
-  explicit AudioCodecBridge(const std::string& mime);
-
-  // Configure the java MediaFormat object with the extra codec data passed in.
-  bool ConfigureMediaFormat(jobject j_format,
-                            const AudioCodec& codec,
-                            const uint8_t* extra_data,
-                            size_t extra_data_size,
-                            int64_t codec_delay_ns,
-                            int64_t seek_preroll_ns);
-};
-
-// Class for handling video encoding/decoding using android MediaCodec APIs.
-// TODO(qinmin): implement the logic to switch between NDK and SDK
-// MediaCodecBridge.
-class MEDIA_EXPORT VideoCodecBridge : public SdkMediaCodecBridge {
- public:
-  // See MediaCodecUtil::IsKnownUnaccelerated().
-  static bool IsKnownUnaccelerated(const VideoCodec& codec,
-                                   MediaCodecDirection direction);
-
-  // Create, start, and return a VideoCodecBridge decoder or NULL on failure.
-  static VideoCodecBridge* CreateDecoder(
-      const VideoCodec& codec,  // e.g. media::kCodecVP8
-      bool is_secure,
-      const gfx::Size& size,  // Output frame size.
-      jobject surface,        // Output surface, optional.
-      jobject media_crypto);  // MediaCrypto object, optional.
-
-  // Create, start, and return a VideoCodecBridge encoder or NULL on failure.
-  static VideoCodecBridge* CreateEncoder(
-      const VideoCodec& codec,  // e.g. media::kCodecVP8
-      const gfx::Size& size,    // input frame size
-      int bit_rate,             // bits/second
-      int frame_rate,           // frames/second
-      int i_frame_interval,     // count
-      int color_format);        // MediaCodecInfo.CodecCapabilities.
-
-  void SetVideoBitrate(int bps);
-  void RequestKeyFrameSoon();
-
-  // Returns whether adaptive playback is supported for this object given
-  // the new size.
-  bool IsAdaptivePlaybackSupported(int width, int height);
-
-  // Test-only method to set the return value of IsAdaptivePlaybackSupported().
-  // Without this function, the return value of that function will be device
-  // dependent. If |adaptive_playback_supported| is equal to 0, the return value
-  // will be false. If |adaptive_playback_supported| is larger than 0, the
-  // return value will be true.
-  void set_adaptive_playback_supported_for_testing(
-      int adaptive_playback_supported) {
-    adaptive_playback_supported_for_testing_ = adaptive_playback_supported;
-  }
-
- private:
-  VideoCodecBridge(const std::string& mime,
-                   bool is_secure,
-                   MediaCodecDirection direction);
-
-  int adaptive_playback_supported_for_testing_;
-};
-
-}  // namespace media
-
-#endif  // MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/sdk_media_codec_bridge_unittest.cc b/media/base/android/sdk_media_codec_bridge_unittest.cc
deleted file mode 100644
index 2f6274f..0000000
--- a/media/base/android/sdk_media_codec_bridge_unittest.cc
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2015 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 <string>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "media/base/android/media_codec_util.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/test_data_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace {
-
-// The first frame of
-// http://www.html5rocks.com/en/tutorials/audio/quick/test.mp3
-unsigned char test_mp3[] = {
-    0xff, 0xfb, 0xd2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x7e, 0x40,
-    0xc0, 0x19, 0x4a, 0x80, 0x0d, 0x60, 0x48, 0x1b, 0x40, 0xf7, 0xbd, 0xb9,
-    0xd9, 0x40, 0x6f, 0x82, 0x01, 0x8b, 0x17, 0xa0, 0x80, 0xc5, 0x01, 0xad,
-    0x9a, 0xd3, 0x00, 0x12, 0xc0, 0x72, 0x93, 0x67, 0xd0, 0x03, 0x6f, 0xa4,
-    0xc0, 0xc3, 0x23, 0xee, 0x9b, 0xc0, 0xcc, 0x02, 0xa0, 0xa1, 0x30, 0x0c,
-    0x52, 0x2d, 0xfd, 0x6e, 0x08, 0x83, 0x60, 0x40, 0x46, 0x06, 0x4b, 0x20,
-    0x82, 0x82, 0x7f, 0xd4, 0x81, 0xe7, 0x00, 0x64, 0x20, 0x18, 0xec, 0xc2,
-    0x06, 0x57, 0x0f, 0x81, 0x93, 0x0b, 0x00, 0x66, 0xe3, 0xb7, 0xe8, 0x32,
-    0x6e, 0xf0, 0x32, 0xb0, 0x58, 0x0c, 0x7c, 0x3a, 0x03, 0x22, 0x14, 0x80,
-    0xc9, 0x01, 0x80, 0x30, 0x20, 0x14, 0x0c, 0x96, 0x73, 0xfe, 0x9f, 0x6c,
-    0x0c, 0xd2, 0x25, 0x0f, 0xdc, 0x0c, 0x32, 0x43, 0x03, 0x27, 0x87, 0xc0,
-    0xc2, 0xc0, 0x20, 0xfc, 0x42, 0xc5, 0xff, 0xff, 0xd4, 0x80, 0x01, 0x01,
-    0x80, 0xc3, 0x81, 0x01, 0x95, 0x03, 0x28, 0x82, 0xc0, 0xc3, 0x01, 0xa1,
-    0x06, 0x81, 0x87, 0xc2, 0x40, 0x64, 0xc1, 0xf0, 0x12, 0x02, 0xff, 0xf6,
-    0x5b, 0x9f, 0x44, 0xdc, 0xdd, 0x0b, 0x38, 0x59, 0xe0, 0x31, 0x71, 0x60,
-    0x0c, 0xb4, 0x22, 0x03, 0x3b, 0x96, 0x40, 0xc8, 0x63, 0x90, 0x0a, 0x23,
-    0x81, 0x9e, 0x4c, 0x20, 0x65, 0xb3, 0x18, 0x19, 0x6c, 0x42, 0x06, 0x36,
-    0x1d, 0x01, 0x90, 0x87, 0xdf, 0xff, 0xd0, 0x65, 0xa6, 0xea, 0x66, 0xfd,
-    0x40, 0x0c, 0x48, 0x03, 0x1a, 0x09, 0x01, 0x21, 0x98, 0x19, 0x2c, 0x36,
-    0x06, 0x43, 0x21, 0x81, 0x92, 0xca, 0x60, 0x64, 0x70, 0xb8, 0x19, 0x20,
-    0x6c, 0x02, 0x83, 0x80, 0xcb, 0x60, 0x65, 0x32, 0x28, 0x18, 0x64, 0x24,
-    0x06, 0x3a, 0x0c, 0x00, 0xe1, 0x00, 0x18, 0xd0, 0x35, 0xff, 0xff, 0xff,
-    0xe8, 0x32, 0xef, 0xb2, 0x90, 0x65, 0xbb, 0xdd, 0x94, 0x82, 0x0b, 0x4c,
-    0xfa, 0x25, 0xf3, 0x74, 0x13, 0x0f, 0xf8, 0x19, 0x28, 0x84, 0x06, 0x36,
-    0x11, 0x01, 0x20, 0x80, 0x18, 0xb4, 0x52, 0x0e, 0x15, 0x00, 0x30, 0x50,
-    0x0c, 0x84, 0x32, 0x03, 0x11, 0x04, 0x03, 0x48, 0x04, 0x00, 0x00, 0x31,
-    0x21, 0x00, 0x0c, 0x84, 0x18, 0x03, 0x07, 0x85, 0x40, 0xc6, 0xa5, 0x70,
-    0x32, 0xb8, 0x7c, 0x0c, 0x54, 0x04, 0x00, 0xd0, 0x08, 0x59, 0x58, 0x18,
-    0x20, 0x14, 0x06, 0x30, 0x30, 0x01, 0x9b, 0x86, 0x00, 0x6b, 0x54, 0xa8,
-    0x19, 0x8c, 0x2a, 0x06, 0x16, 0x09, 0x01, 0xa0, 0xd0, 0xa0, 0x69, 0x74,
-    0xb8, 0x19, 0xc4, 0x4a, 0xa3, 0xda, 0x9d, 0x1e, 0x4f, 0x05, 0xc0, 0x5b,
-    0x0b, 0x03, 0xc2, 0x76, 0xa3, 0x4f, 0xb9, 0x16, 0xc2, 0x70, 0x41, 0x07,
-    0xa0, 0x84, 0x16, 0x38, 0x4a, 0xc8, 0xaf, 0xee, 0x7f, 0x93, 0xb5, 0x5c,
-    0x39, 0x1e, 0x29, 0xd9, 0x8c, 0x80, 0xb5, 0x80, 0xe6, 0x85, 0xb2, 0x99,
-    0x68, 0x85, 0x46, 0x91, 0x60, 0xdb, 0x06, 0xfa, 0x38, 0x7a, 0xc7, 0xac,
-    0x85, 0xa8, 0xd3, 0xe6, 0x99, 0x3b, 0x66, 0x43, 0x23, 0x1f, 0x84, 0xe1,
-    0x65, 0x5e, 0xbc, 0x84, 0x18, 0x62, 0xe6, 0x42, 0x0b, 0x82, 0xe4, 0xd3,
-    0x42, 0xd2, 0x05, 0x81, 0x4e, 0xe4, 0x9f, 0x8c, 0xc8, 0x7f, 0xa3, 0xe0,
-    0x8d, 0xf1, 0x0f, 0x38, 0xe5, 0x3f, 0xc4, 0x2c, 0x24, 0x65, 0x8d, 0xb9,
-    0x58, 0xac, 0x39, 0x0e, 0x37, 0x99, 0x2e, 0x85, 0xe0, 0xb7, 0x98, 0x41,
-    0x20, 0x38, 0x1b, 0x95, 0x07, 0xfa, 0xa8, 0x9c, 0x21, 0x0f, 0x13, 0x8c,
-    0xa5, 0xc1, 0x76, 0xae, 0x0b, 0xc1, 0x30, 0x27, 0x08, 0xc1, 0xf6, 0x4d,
-    0xce, 0xb4, 0x41, 0x38, 0x1e, 0x82, 0x10, 0x74, 0x45, 0x91, 0x90, 0xff,
-    0x41, 0x8b, 0x62, 0x1a, 0x71, 0xb6, 0x45, 0x63, 0x8c, 0xce, 0xb8, 0x54,
-    0x1b, 0xe8, 0x5d, 0x9e, 0x35, 0x9d, 0x6c, 0xac, 0xe8, 0x83, 0xa1, 0xe9,
-    0x3f, 0x13, 0x74, 0x11, 0x04, 0x10, 0xf1, 0x37, 0x38, 0xc6, 0x00, 0x60,
-    0x27, 0x48, 0x38, 0x85, 0x92, 0x76, 0xb7, 0xf3, 0xa7, 0x1c, 0x4b, 0xf9,
-    0x3b, 0x5a, 0x88, 0xac, 0x60, 0x1b, 0x85, 0x81, 0x16, 0xab, 0x44, 0x17,
-    0x08, 0x2e, 0x0f, 0xd4, 0xe2, 0xde, 0x49, 0xc9, 0xe1, 0xc0, 0xc0, 0xa0,
-    0x7e, 0x73, 0xa1, 0x67, 0xf8, 0xf5, 0x9f, 0xc4, 0x21, 0x50, 0x4f, 0x05,
-    0x2c, 0xfc, 0x5c, 0xaa, 0x85, 0xb0, 0xfa, 0x67, 0x80, 0x7e, 0x0f, 0xfd,
-    0x92, 0x30, 0xd5, 0xa0, 0xd4, 0x05, 0xdd, 0x06, 0x68, 0x1d, 0x6e, 0x4e,
-    0x8b, 0x79, 0xd6, 0xfc, 0xff, 0x2e, 0x6e, 0x7c, 0xba, 0x03, 0x90, 0xd4,
-    0x25, 0x65, 0x8e, 0xe7, 0x3a, 0xd1, 0xd6, 0xdc, 0xf0, 0xbe, 0x12, 0xc4,
-    0x31, 0x08, 0x16, 0x70, 0x31, 0x85, 0x61, 0x38, 0x27, 0x0a, 0x91, 0x5f,
-    0x03, 0x38, 0xeb, 0x37, 0x13, 0x48, 0x41, 0xbe, 0x7f, 0x04, 0x70, 0x62,
-    0x2b, 0x15, 0x91, 0x67, 0x63, 0x4f, 0xad, 0xa7, 0x1d, 0x3f, 0x44, 0x17,
-    0x02, 0x08, 0x0d, 0xf2, 0xfc, 0x03, 0xa0, 0x74, 0x21, 0x8b, 0x07, 0x3a,
-    0x8d, 0x0f, 0x54, 0x58, 0x94, 0x12, 0xc5, 0x62, 0x18, 0xb9, 0x42, 0xf0,
-    0x6c, 0x73, 0xa0, 0x92, 0xad, 0x27, 0x1c, 0x20, 0x0f, 0xc1, 0xca, 0x44,
-    0x87, 0x47, 0xc5, 0x43, 0x23, 0x01, 0xda, 0x23, 0xe2, 0x89, 0x38, 0x9f,
-    0x1f, 0x8d, 0x8c, 0xc6, 0x95, 0xa3, 0x34, 0x21, 0x21, 0x2d, 0x49, 0xea,
-    0x4b, 0x05, 0x85, 0xf5, 0x58, 0x25, 0x13, 0xcd, 0x51, 0x19, 0x1a, 0x88,
-    0xa6, 0x83, 0xd6, 0xd0, 0xbc, 0x25, 0x19, 0x1c, 0x92, 0x12, 0x44, 0x5d,
-    0x1c, 0x04, 0xf1, 0x99, 0xdf, 0x92, 0x8e, 0x09, 0x85, 0xf3, 0x88, 0x82,
-    0x4c, 0x22, 0x17, 0xc5, 0x25, 0x23, 0xed, 0x78, 0xf5, 0x41, 0xd1, 0xe9,
-    0x8a, 0xb3, 0x52, 0xd1, 0x3d, 0x79, 0x81, 0x4d, 0x31, 0x24, 0xf9, 0x38,
-    0x96, 0xbc, 0xf4, 0x8c, 0x25, 0xe9, 0xf2, 0x73, 0x94, 0x85, 0xc2, 0x61,
-    0x6a, 0x34, 0x68, 0x65, 0x78, 0x87, 0xa6, 0x4f};
-
-}  // namespace
-
-namespace media {
-
-// Helper macro to skip the test if MediaCodecBridge isn't available.
-#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE()        \
-  do {                                                            \
-    if (!MediaCodecUtil::IsMediaCodecAvailable()) {               \
-      VLOG(0) << "Could not run test - not supported on device."; \
-      return;                                                     \
-    }                                                             \
-  } while (0)
-
-static const int kPresentationTimeBase = 100;
-
-static inline const base::TimeDelta InfiniteTimeOut() {
-  return base::TimeDelta::FromMicroseconds(-1);
-}
-
-void DecodeMediaFrame(VideoCodecBridge* media_codec,
-                      const uint8* data,
-                      size_t data_size,
-                      const base::TimeDelta input_presentation_timestamp,
-                      const base::TimeDelta initial_timestamp_lower_bound) {
-  base::TimeDelta input_pts = input_presentation_timestamp;
-  base::TimeDelta timestamp = initial_timestamp_lower_bound;
-  base::TimeDelta new_timestamp;
-  for (int i = 0; i < 10; ++i) {
-    int input_buf_index = -1;
-    MediaCodecStatus status =
-        media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-    ASSERT_EQ(MEDIA_CODEC_OK, status);
-
-    media_codec->QueueInputBuffer(input_buf_index, data, data_size,
-                                  input_presentation_timestamp);
-
-    size_t unused_offset = 0;
-    size_t size = 0;
-    bool eos = false;
-    int output_buf_index = -1;
-    status = media_codec->DequeueOutputBuffer(
-        InfiniteTimeOut(), &output_buf_index, &unused_offset, &size,
-        &new_timestamp, &eos, nullptr);
-
-    if (status == MEDIA_CODEC_OK && output_buf_index > 0) {
-      media_codec->ReleaseOutputBuffer(output_buf_index, false);
-    }
-    // Output time stamp should not be smaller than old timestamp.
-    ASSERT_TRUE(new_timestamp >= timestamp);
-    input_pts += base::TimeDelta::FromMicroseconds(33000);
-    timestamp = new_timestamp;
-  }
-}
-
-TEST(SdkMediaCodecBridgeTest, Initialize) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::MediaCodecBridge> media_codec;
-  media_codec.reset(VideoCodecBridge::CreateDecoder(
-      kCodecH264, false, gfx::Size(640, 480), nullptr, nullptr));
-}
-
-TEST(SdkMediaCodecBridgeTest, DoNormal) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::AudioCodecBridge> media_codec;
-  media_codec.reset(AudioCodecBridge::Create(kCodecMP3));
-
-  ASSERT_TRUE(media_codec->ConfigureAndStart(kCodecMP3, 44100, 2, nullptr, 0, 0,
-                                             0, false, nullptr));
-
-  int input_buf_index = -1;
-  MediaCodecStatus status =
-      media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-  ASSERT_EQ(MEDIA_CODEC_OK, status);
-  ASSERT_GE(input_buf_index, 0);
-
-  int64 input_pts = kPresentationTimeBase;
-  media_codec->QueueInputBuffer(input_buf_index, test_mp3, sizeof(test_mp3),
-                                base::TimeDelta::FromMicroseconds(++input_pts));
-
-  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-  media_codec->QueueInputBuffer(input_buf_index, test_mp3, sizeof(test_mp3),
-                                base::TimeDelta::FromMicroseconds(++input_pts));
-
-  status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index);
-  media_codec->QueueEOS(input_buf_index);
-
-  input_pts = kPresentationTimeBase;
-  bool eos = false;
-  while (!eos) {
-    size_t unused_offset = 0;
-    size_t size = 0;
-    base::TimeDelta timestamp;
-    int output_buf_index = -1;
-    status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(),
-                                              &output_buf_index, &unused_offset,
-                                              &size, &timestamp, &eos, nullptr);
-    switch (status) {
-      case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
-        FAIL();
-        return;
-
-      case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
-        continue;
-
-      case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
-        continue;
-
-      default:
-        break;
-    }
-    ASSERT_GE(output_buf_index, 0);
-    EXPECT_LE(1u, size);
-    if (!eos)
-      EXPECT_EQ(++input_pts, timestamp.InMicroseconds());
-    ASSERT_LE(input_pts, kPresentationTimeBase + 2);
-  }
-  ASSERT_EQ(input_pts, kPresentationTimeBase + 2);
-}
-
-TEST(SdkMediaCodecBridgeTest, InvalidVorbisHeader) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::AudioCodecBridge> media_codec;
-  media_codec.reset(AudioCodecBridge::Create(kCodecVorbis));
-
-  // The first byte of the header is not 0x02.
-  uint8 invalid_first_byte[] = {0x00, 0xff, 0xff, 0xff, 0xff};
-  EXPECT_FALSE(media_codec->ConfigureAndStart(
-      kCodecVorbis, 44100, 2, invalid_first_byte, sizeof(invalid_first_byte), 0,
-      0, false, nullptr));
-
-  // Size of the header does not match with the data we passed in.
-  uint8 invalid_size[] = {0x02, 0x01, 0xff, 0x01, 0xff};
-  EXPECT_FALSE(media_codec->ConfigureAndStart(
-      kCodecVorbis, 44100, 2, invalid_size, sizeof(invalid_size), 0, 0, false,
-      nullptr));
-
-  // Size of the header is too large.
-  size_t large_size = 8 * 1024 * 1024 + 2;
-  uint8* very_large_header = new uint8[large_size];
-  very_large_header[0] = 0x02;
-  for (size_t i = 1; i < large_size - 1; ++i)
-    very_large_header[i] = 0xff;
-  very_large_header[large_size - 1] = 0xfe;
-  EXPECT_FALSE(media_codec->ConfigureAndStart(kCodecVorbis, 44100, 2,
-                                              very_large_header, 0x80000000, 0,
-                                              0, false, nullptr));
-  delete[] very_large_header;
-}
-
-TEST(SdkMediaCodecBridgeTest, InvalidOpusHeader) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<media::AudioCodecBridge> media_codec;
-  media_codec.reset(AudioCodecBridge::Create(kCodecOpus));
-  uint8 dummy_extra_data[] = {0, 0};
-
-  // Extra Data is NULL.
-  EXPECT_FALSE(media_codec->ConfigureAndStart(kCodecOpus, 48000, 2, nullptr, 0,
-                                              -1, 0, false, nullptr));
-
-  // Codec Delay is < 0.
-  EXPECT_FALSE(media_codec->ConfigureAndStart(
-      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), -1, 0,
-      false, nullptr));
-
-  // Seek Preroll is < 0.
-  EXPECT_FALSE(media_codec->ConfigureAndStart(
-      kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), 0, -1,
-      false, nullptr));
-}
-
-TEST(SdkMediaCodecBridgeTest, PresentationTimestampsDoNotDecrease) {
-  SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
-
-  scoped_ptr<VideoCodecBridge> media_codec(VideoCodecBridge::CreateDecoder(
-      kCodecVP8, false, gfx::Size(320, 240), nullptr, nullptr));
-  EXPECT_TRUE(media_codec.get());
-  scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vp8-I-frame-320x240");
-  DecodeMediaFrame(media_codec.get(), buffer->data(), buffer->data_size(),
-                   base::TimeDelta(), base::TimeDelta());
-
-  // Simulate a seek to 10 seconds, and each chunk has 2 I-frames.
-  std::vector<uint8> chunk(buffer->data(),
-                           buffer->data() + buffer->data_size());
-  chunk.insert(chunk.end(), buffer->data(),
-               buffer->data() + buffer->data_size());
-  media_codec->Reset();
-  DecodeMediaFrame(media_codec.get(), &chunk[0], chunk.size(),
-                   base::TimeDelta::FromMicroseconds(10000000),
-                   base::TimeDelta::FromMicroseconds(9900000));
-
-  // Simulate a seek to 5 seconds.
-  media_codec->Reset();
-  DecodeMediaFrame(media_codec.get(), &chunk[0], chunk.size(),
-                   base::TimeDelta::FromMicroseconds(5000000),
-                   base::TimeDelta::FromMicroseconds(4900000));
-}
-
-TEST(SdkMediaCodecBridgeTest, CreateUnsupportedCodec) {
-  EXPECT_EQ(nullptr, AudioCodecBridge::Create(kUnknownAudioCodec));
-  EXPECT_EQ(nullptr, VideoCodecBridge::CreateDecoder(kUnknownVideoCodec, false,
-                                                     gfx::Size(320, 240),
-                                                     nullptr, nullptr));
-}
-
-}  // namespace media
diff --git a/media/base/android/video_decoder_job.cc b/media/base/android/video_decoder_job.cc
index 3dfe3b83..cec1b393 100644
--- a/media/base/android/video_decoder_job.cc
+++ b/media/base/android/video_decoder_job.cc
@@ -7,8 +7,8 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/threading/thread.h"
+#include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_drm_bridge.h"
-#include "media/base/android/sdk_media_codec_bridge.h"
 
 namespace media {
 
diff --git a/media/base/mac/avfoundation_glue.mm b/media/base/mac/avfoundation_glue.mm
index aed571d5..e1c9297 100644
--- a/media/base/mac/avfoundation_glue.mm
+++ b/media/base/mac/avfoundation_glue.mm
@@ -10,6 +10,7 @@
 #include "base/lazy_instance.h"
 #include "base/mac/mac_util.h"
 #include "base/metrics/histogram.h"
+#include "base/trace_event/trace_event.h"
 #include "media/base/media_switches.h"
 
 namespace {
@@ -156,6 +157,7 @@
 } static g_avfoundation_initialization = INITIALIZE_NOT_CALLED;
 
 void AVFoundationGlue::InitializeAVFoundation() {
+  TRACE_EVENT0("video", "AVFoundationGlue::InitializeAVFoundation");
   CHECK([NSThread isMainThread]);
   if (g_avfoundation_initialization != INITIALIZE_NOT_CALLED)
     return;
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 4df032a..3c7686f 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -128,4 +128,7 @@
 const char kDisableRTCSmoothnessAlgorithm[] =
     "disable-rtc-smoothness-algorithm";
 
+// Use shared block-based buffering for media.
+const char kUseNewMediaCache[] = "use-new-media-cache";
+
 }  // namespace switches
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index e99904aeef..e8c99b4 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -62,6 +62,8 @@
 
 MEDIA_EXPORT extern const char kDisableRTCSmoothnessAlgorithm[];
 
+MEDIA_EXPORT extern const char kUseNewMediaCache[];
+
 }  // namespace switches
 
 #endif  // MEDIA_BASE_MEDIA_SWITCHES_H_
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 779e820..6bb95327 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -104,13 +104,13 @@
 
 class BufferedDataSourceHostImpl;
 
-#define STATIC_ASSERT_MATCHING_ENUM(name) \
-  static_assert(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
-                static_cast<int>(BufferedResourceLoader::k ## name), \
+#define STATIC_ASSERT_MATCHING_ENUM(name, name2)                    \
+  static_assert(static_cast<int>(WebMediaPlayer::CORSMode##name) == \
+                    static_cast<int>(UrlData::name2),               \
                 "mismatching enum values: " #name)
-STATIC_ASSERT_MATCHING_ENUM(Unspecified);
-STATIC_ASSERT_MATCHING_ENUM(Anonymous);
-STATIC_ASSERT_MATCHING_ENUM(UseCredentials);
+STATIC_ASSERT_MATCHING_ENUM(Unspecified, CORS_UNSPECIFIED);
+STATIC_ASSERT_MATCHING_ENUM(Anonymous, CORS_ANONYMOUS);
+STATIC_ASSERT_MATCHING_ENUM(UseCredentials, CORS_USE_CREDENTIALS);
 #undef STATIC_ASSERT_MATCHING_ENUM
 
 #define BIND_TO_RENDER_LOOP(function) \
@@ -128,6 +128,7 @@
     base::WeakPtr<WebMediaPlayerDelegate> delegate,
     scoped_ptr<RendererFactory> renderer_factory,
     CdmFactory* cdm_factory,
+    linked_ptr<UrlIndex> url_index,
     const WebMediaPlayerParams& params)
     : frame_(frame),
       network_state_(WebMediaPlayer::NetworkStateEmpty),
@@ -163,6 +164,7 @@
       last_reported_memory_usage_(0),
       supports_save_(true),
       chunk_demuxer_(NULL),
+      url_index_(url_index),
       // Threaded compositing isn't enabled universally yet.
       compositor_task_runner_(
           params.compositor_task_runner()
@@ -277,14 +279,21 @@
   }
 
   // Otherwise it's a regular request which requires resolving the URL first.
-  data_source_.reset(new BufferedDataSource(
-      url,
-      static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
-      main_task_runner_,
-      frame_,
-      media_log_.get(),
-      &buffered_data_source_host_,
-      base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseNewMediaCache)) {
+    // Remove this when MultiBufferDataSource becomes default.
+    LOG(WARNING) << "Using MultibufferDataSource";
+    data_source_.reset(new MultibufferDataSource(
+        url, static_cast<UrlData::CORSMode>(cors_mode), main_task_runner_,
+        url_index_, frame_, media_log_.get(), &buffered_data_source_host_,
+        base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
+  } else {
+    data_source_.reset(new BufferedDataSource(
+        url, static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
+        main_task_runner_, frame_, media_log_.get(),
+        &buffered_data_source_host_,
+        base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
+  }
   data_source_->SetPreload(preload_);
   data_source_->SetBufferingStrategy(buffering_strategy_);
   data_source_->Initialize(
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index 0ec8076..3918395 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -10,6 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -22,6 +23,7 @@
 #include "media/blink/buffered_data_source_host_impl.h"
 #include "media/blink/encrypted_media_player_support.h"
 #include "media/blink/media_blink_export.h"
+#include "media/blink/multibuffer_data_source.h"
 #include "media/blink/video_frame_compositor.h"
 #include "media/blink/webmediaplayer_delegate.h"
 #include "media/blink/webmediaplayer_params.h"
@@ -54,6 +56,7 @@
 class ChunkDemuxer;
 class GpuVideoAcceleratorFactories;
 class MediaLog;
+class UrlIndex;
 class VideoFrameCompositor;
 class WebAudioSourceProviderImpl;
 class WebMediaPlayerDelegate;
@@ -79,6 +82,7 @@
       base::WeakPtr<WebMediaPlayerDelegate> delegate,
       scoped_ptr<RendererFactory> renderer_factory,
       CdmFactory* cdm_factory,
+      linked_ptr<UrlIndex> url_index,
       const WebMediaPlayerParams& params);
   ~WebMediaPlayerImpl() override;
 
@@ -372,11 +376,12 @@
   //
   // |demuxer_| will contain the appropriate demuxer based on which resource
   // load strategy we're using.
-  scoped_ptr<BufferedDataSource> data_source_;
+  scoped_ptr<BufferedDataSourceInterface> data_source_;
   scoped_ptr<Demuxer> demuxer_;
   ChunkDemuxer* chunk_demuxer_;
 
   BufferedDataSourceHostImpl buffered_data_source_host_;
+  linked_ptr<UrlIndex> url_index_;
 
   // Video rendering members.
   scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
diff --git a/media/capture/video/mac/video_capture_device_factory_mac.h b/media/capture/video/mac/video_capture_device_factory_mac.h
index 07e127b9..bc2df52 100644
--- a/media/capture/video/mac/video_capture_device_factory_mac.h
+++ b/media/capture/video/mac/video_capture_device_factory_mac.h
@@ -15,8 +15,6 @@
 class MEDIA_EXPORT VideoCaptureDeviceFactoryMac
     : public VideoCaptureDeviceFactory {
  public:
-  static bool PlatformSupportsAVFoundation();
-
   explicit VideoCaptureDeviceFactoryMac(
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   ~VideoCaptureDeviceFactoryMac() override;
diff --git a/media/capture/video/mac/video_capture_device_factory_mac.mm b/media/capture/video/mac/video_capture_device_factory_mac.mm
index 3d7c795d..573a8b5 100644
--- a/media/capture/video/mac/video_capture_device_factory_mac.mm
+++ b/media/capture/video/mac/video_capture_device_factory_mac.mm
@@ -81,11 +81,6 @@
   callback.Run(device_names.Pass());
 }
 
-// static
-bool VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation() {
-  return AVFoundationGlue::IsAVFoundationSupported();
-}
-
 VideoCaptureDeviceFactoryMac::VideoCaptureDeviceFactoryMac(
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
     : ui_task_runner_(ui_task_runner) {
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index c4734c8..f3186e7 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -265,10 +265,9 @@
   VideoCaptureDevice::Name device_name("jibberish", "jibberish", api_type);
 #elif defined(OS_MACOSX)
   VideoCaptureDevice::Name device_name(
-      "jibberish", "jibberish",
-      VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation()
-          ? VideoCaptureDevice::Name::AVFOUNDATION
-          : VideoCaptureDevice::Name::QTKIT);
+      "jibberish", "jibberish", AVFoundationGlue::IsAVFoundationSupported()
+                                    ? VideoCaptureDevice::Name::AVFOUNDATION
+                                    : VideoCaptureDevice::Name::QTKIT);
 #else
   VideoCaptureDevice::Name device_name("jibberish", "jibberish");
 #endif
@@ -277,7 +276,7 @@
 #if !defined(OS_MACOSX)
   EXPECT_TRUE(device == NULL);
 #else
-  if (VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation()) {
+  if (AVFoundationGlue::IsAVFoundationSupported()) {
     EXPECT_TRUE(device == NULL);
   } else {
     // The presence of the actual device is only checked on AllocateAndStart()
diff --git a/media/media.gyp b/media/media.gyp
index 70be514..dbd452d 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -1187,12 +1187,12 @@
       ],
       'sources': [
         'base/android/access_unit_queue_unittest.cc',
+        'base/android/media_codec_bridge_unittest.cc',
         'base/android/media_codec_decoder_unittest.cc',
         'base/android/media_codec_player_unittest.cc',
         'base/android/media_drm_bridge_unittest.cc',
         'base/android/media_player_bridge_unittest.cc',
         'base/android/media_source_player_unittest.cc',
-        'base/android/sdk_media_codec_bridge_unittest.cc',
         'base/android/test_data_factory.cc',
         'base/android/test_data_factory.h',
         'base/android/test_statistics.h',
@@ -1813,7 +1813,6 @@
             'base/android/java/src/org/chromium/media/AudioManagerAndroid.java',
             'base/android/java/src/org/chromium/media/AudioRecordInput.java',
             'base/android/java/src/org/chromium/media/MediaCodecBridge.java',
-            'base/android/java/src/org/chromium/media/MediaCodecUtil.java',
             'base/android/java/src/org/chromium/media/MediaDrmBridge.java',
             'base/android/java/src/org/chromium/media/MediaPlayerBridge.java',
             'base/android/java/src/org/chromium/media/MediaPlayerListener.java',
@@ -1863,8 +1862,6 @@
             'base/android/media_codec_player.h',
             'base/android/media_codec_video_decoder.cc',
             'base/android/media_codec_video_decoder.h',
-            'base/android/media_codec_util.cc',
-            'base/android/media_codec_util.h',
             'base/android/media_common_android.h',
             'base/android/media_decoder_job.cc',
             'base/android/media_decoder_job.h',
@@ -1891,28 +1888,12 @@
             'base/android/media_task_runner.h',
             'base/android/media_url_interceptor.h',
             'base/android/provision_fetcher.h',
-            'base/android/sdk_media_codec_bridge.cc',
-            'base/android/sdk_media_codec_bridge.h',
             'base/android/video_decoder_job.cc',
             'base/android/video_decoder_job.h',
             'base/android/webaudio_media_codec_bridge.cc',
             'base/android/webaudio_media_codec_bridge.h',
             'base/android/webaudio_media_codec_info.h',
           ],
-          'conditions': [
-            # Only 64 bit builds are using android-21 NDK library, check common.gypi
-            ['target_arch=="arm64" or target_arch=="x64" or target_arch=="mips64el"', {
-              'sources': [
-                'base/android/ndk_media_codec_bridge.cc',
-                'base/android/ndk_media_codec_bridge.h',
-              ],
-              'link_settings': {
-                'libraries': [
-                  '-lmediandk',
-                ],
-              },
-            }],
-          ],
           'dependencies': [
             '../base/base.gyp:base',
             '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
diff --git a/mojo/edk/system/broker_messages.h b/mojo/edk/system/broker_messages.h
index 7d8946d..0ce0960 100644
--- a/mojo/edk/system/broker_messages.h
+++ b/mojo/edk/system/broker_messages.h
@@ -46,6 +46,9 @@
 
 #endif
 
+// Route id used for messages between ChildBroker and ChildBrokerHost.
+const uint64_t kBrokerRouteId = 1;
+
 // Multiplexing related messages. They are all asynchronous messages.
 // They are sent over RawChannel.
 enum MultiplexMessages {
diff --git a/mojo/edk/system/broker_state.cc b/mojo/edk/system/broker_state.cc
index b875b31..4fad5a98 100644
--- a/mojo/edk/system/broker_state.cc
+++ b/mojo/edk/system/broker_state.cc
@@ -95,16 +95,12 @@
 
   if (pending_child_connects_.find(pipe_id) != pending_child_connects_.end()) {
     // A child process has already tried to connect.
-    EnsureProcessesConnected(base::GetCurrentProcId(),
-                             pending_child_connects_[pipe_id]->GetProcessId());
-    pending_child_connects_[pipe_id]->ConnectMessagePipe(
-        pipe_id, base::GetCurrentProcId());
-    base::ProcessId peer_pid = pending_child_connects_[pipe_id]->GetProcessId();
+    ChildBrokerHost* child_host = pending_child_connects_[pipe_id];
+    child_host->channel()->AddRoute(pipe_id, message_pipe);
+    child_host->ConnectMessagePipe(pipe_id, 0);
     pending_child_connects_.erase(pipe_id);
-    connected_pipes_[message_pipe] = child_channels_[peer_pid];
-    child_channels_[peer_pid]->AddRoute(pipe_id, message_pipe);
-    message_pipe->GotNonTransferableChannel(
-        child_channels_[peer_pid]->channel());
+    connected_pipes_[message_pipe] = child_host->channel();
+    message_pipe->GotNonTransferableChannel(child_host->channel()->channel());
     return;
   }
 
@@ -117,7 +113,7 @@
   base::AutoLock auto_lock(lock_);
 
   CHECK(connected_pipes_.find(message_pipe) != connected_pipes_.end());
-  connected_pipes_[message_pipe]->RemoveRoute(pipe_id, message_pipe);
+  connected_pipes_[message_pipe]->RemoveRoute(pipe_id);
   connected_pipes_.erase(message_pipe);
 }
 
@@ -181,17 +177,11 @@
 
   if (pending_connects_.find(pipe_id) != pending_connects_.end()) {
     // This parent process is the other side of the given pipe.
-    EnsureProcessesConnected(base::GetCurrentProcId(),
-                             pipe_process->GetProcessId());
     MessagePipeDispatcher* pending_pipe = pending_connects_[pipe_id];
-    connected_pipes_[pending_pipe] =
-        child_channels_[pipe_process->GetProcessId()];
-    child_channels_[pipe_process->GetProcessId()]->AddRoute(
-        pipe_id, pending_pipe);
-    pending_pipe->GotNonTransferableChannel(
-        child_channels_[pipe_process->GetProcessId()]->channel());
-    pipe_process->ConnectMessagePipe(
-        pipe_id, base::GetCurrentProcId());
+    connected_pipes_[pending_pipe] = pipe_process->channel();
+    pipe_process->channel()->AddRoute(pipe_id, pending_pipe);
+    pending_pipe->GotNonTransferableChannel(pipe_process->channel()->channel());
+    pipe_process->ConnectMessagePipe(pipe_id, 0);
     pending_connects_.erase(pipe_id);
     return;
   }
@@ -225,6 +215,7 @@
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
   lock_.AssertAcquired();
   CHECK_NE(pid1, pid2);
+  CHECK_NE(pid1, base::GetCurrentProcId());
   CHECK_NE(pid2, base::GetCurrentProcId());
   std::pair<base::ProcessId, base::ProcessId> processes;
   processes.first = std::min(pid1, pid2);
@@ -234,17 +225,6 @@
 
   connected_processes_.insert(processes);
   PlatformChannelPair channel_pair;
-  if (pid1 == base::GetCurrentProcId()) {
-    CHECK(child_channels_.find(pid2) == child_channels_.end());
-    CHECK(child_processes_.find(pid2) != child_processes_.end());
-    child_channels_[pid2] = new RoutedRawChannel(
-        channel_pair.PassServerHandle(),
-        base::Bind(&BrokerState::ChannelDestructed, base::Unretained(this)));
-    child_processes_[pid2]->ConnectToProcess(base::GetCurrentProcId(),
-                                             channel_pair.PassClientHandle());
-    return;
-  }
-
   CHECK(child_processes_.find(pid1) != child_processes_.end());
   CHECK(child_processes_.find(pid2) != child_processes_.end());
   child_processes_[pid1]->ConnectToProcess(pid2,
@@ -254,14 +234,6 @@
 }
 
 void BrokerState::ChannelDestructed(RoutedRawChannel* channel) {
-  DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
-  base::AutoLock auto_lock(lock_);
-  for (auto it : child_channels_) {
-    if (it.second == channel) {
-      child_channels_.erase(it.first);
-      break;
-    }
-  }
 }
 
 }  // namespace edk
diff --git a/mojo/edk/system/broker_state.h b/mojo/edk/system/broker_state.h
index 29f3ffe..0b017e8 100644
--- a/mojo/edk/system/broker_state.h
+++ b/mojo/edk/system/broker_state.h
@@ -61,8 +61,6 @@
 
   // Checks if there's a direct channel between the two processes, and if not
   // creates one and tells them about it.
-  // If one of the processes is the current one, it should be pid1.
-  // Called on the IO thread.
   void EnsureProcessesConnected(base::ProcessId pid1, base::ProcessId pid2);
 
   // Callback when a RoutedRawChannel is destroyed for cleanup.
@@ -90,10 +88,6 @@
 
   base::Lock lock_;  // Guards access to below.
 
-  // Holds a map of all the RoutedRawChannel that connect this parent process to
-  // a child process. The key is the child process'd pid.
-  base::hash_map<base::ProcessId, RoutedRawChannel*> child_channels_;
-
   base::hash_map<uint64_t, ChildBrokerHost*> pending_child_connects_;
 
   // Each entry is an std::pair of ints of processe IDs that have
diff --git a/mojo/edk/system/child_broker.cc b/mojo/edk/system/child_broker.cc
index 31bae43a..2964d20e 100644
--- a/mojo/edk/system/child_broker.cc
+++ b/mojo/edk/system/child_broker.cc
@@ -10,7 +10,6 @@
 #include "mojo/edk/embedder/platform_channel_pair.h"
 #include "mojo/edk/system/broker_messages.h"
 #include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/routed_raw_channel.h"
 
 namespace mojo {
 namespace edk {
@@ -163,7 +162,7 @@
     uint64_t pipe_id, MessagePipeDispatcher* message_pipe) {
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
   CHECK(connected_pipes_.find(message_pipe) != connected_pipes_.end());
-  connected_pipes_[message_pipe]->RemoveRoute(pipe_id, message_pipe);
+  connected_pipes_[message_pipe]->RemoveRoute(pipe_id);
   connected_pipes_.erase(message_pipe);
 }
 
@@ -211,7 +210,12 @@
     CHECK(pending_connects_.find(pipe_id) != pending_connects_.end());
     MessagePipeDispatcher* pipe = pending_connects_[pipe_id];
     pending_connects_.erase(pipe_id);
-    if (channels_.find(peer_pid) == channels_.end()) {
+    if (peer_pid == 0) {
+      // The other side is in the parent process.
+      connected_pipes_[pipe] = parent_async_channel_;
+      parent_async_channel_->AddRoute(pipe_id, pipe);
+      pipe->GotNonTransferableChannel(parent_async_channel_->channel());
+    } else if (channels_.find(peer_pid) == channels_.end()) {
       // We saw the peer process die before we got the reply from the parent.
       pipe->OnError(ERROR_READ_SHUTDOWN);
     } else {
@@ -241,8 +245,9 @@
 
 void ChildBroker::WriteAsyncMessage(scoped_ptr<MessageInTransit> message) {
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
+  message->set_route_id(kBrokerRouteId);
   if (parent_async_channel_) {
-    parent_async_channel_->WriteMessage(message.Pass());
+    parent_async_channel_->channel()->WriteMessage(message.Pass());
   } else {
     async_channel_queue_.AddMessage(message.Pass());
   }
@@ -252,11 +257,14 @@
     ScopedPlatformHandle parent_async_channel_handle) {
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
 
-  parent_async_channel_ =
-      RawChannel::Create(parent_async_channel_handle.Pass());
-  parent_async_channel_->Init(this);
-  while (!async_channel_queue_.IsEmpty())
-    parent_async_channel_->WriteMessage(async_channel_queue_.GetMessage());
+  parent_async_channel_ = new RoutedRawChannel(
+      parent_async_channel_handle.Pass()  ,
+      base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
+  parent_async_channel_->AddRoute(kBrokerRouteId, this);
+  while (!async_channel_queue_.IsEmpty()) {
+    parent_async_channel_->channel()->WriteMessage(
+        async_channel_queue_.GetMessage());
+  }
 
   while (!pending_inprocess_connects_.empty()) {
     ConnectMessagePipe(pending_inprocess_connects_.begin()->first,
diff --git a/mojo/edk/system/child_broker.h b/mojo/edk/system/child_broker.h
index 6a9e488..38cef56 100644
--- a/mojo/edk/system/child_broker.h
+++ b/mojo/edk/system/child_broker.h
@@ -14,12 +14,11 @@
 #include "mojo/edk/embedder/scoped_platform_handle.h"
 #include "mojo/edk/system/broker.h"
 #include "mojo/edk/system/message_in_transit_queue.h"
-#include "mojo/edk/system/raw_channel.h"
+#include "mojo/edk/system/routed_raw_channel.h"
 #include "mojo/edk/system/system_impl_export.h"
 
 namespace mojo {
 namespace edk {
-class RoutedRawChannel;
 struct BrokerMessage;
 
 // An implementation of Broker used in (sandboxed) child processes. It talks
@@ -100,7 +99,7 @@
   // would be convenient, we don't use Mojo IPC because it would be a layering
   // violation (and cirular dependency) if the system layer depended on
   // bindings.
-  RawChannel* parent_async_channel_;
+  RoutedRawChannel* parent_async_channel_;
 
   // Queue of messages to |parent_async_channel_| that are sent before it is
   // created.
diff --git a/mojo/edk/system/child_broker_host.cc b/mojo/edk/system/child_broker_host.cc
index fd134db..95518c6 100644
--- a/mojo/edk/system/child_broker_host.cc
+++ b/mojo/edk/system/child_broker_host.cc
@@ -25,7 +25,7 @@
 
 ChildBrokerHost::ChildBrokerHost(base::ProcessHandle child_process,
                                  ScopedPlatformHandle pipe)
-    : process_id_(base::GetProcId(child_process)) {
+    : process_id_(base::GetProcId(child_process)), child_channel_(nullptr) {
   ScopedPlatformHandle parent_async_channel_handle;
 #if defined(OS_POSIX)
   parent_async_channel_handle = pipe.Pass();
@@ -55,25 +55,10 @@
   DCHECK(rv || GetLastError() == ERROR_IO_PENDING);
 #endif
 
-  child_channel_ = RawChannel::Create(parent_async_channel_handle.Pass());
   internal::g_io_thread_task_runner->PostTask(
       FROM_HERE,
-      base::Bind(&RawChannel::Init, base::Unretained(child_channel_), this));
-  internal::g_io_thread_task_runner->PostTask(
-      FROM_HERE,
-      base::Bind(&RawChannel::EnsureLazyInitialized,
-                  base::Unretained(child_channel_)));
-
-  BrokerState::GetInstance()->ChildBrokerHostCreated(this);
-
-#if defined(OS_WIN)
-  // Call this after RawChannel::Init because this call could cause us to get
-  // notified that the child has gone away and to delete this class and shut
-  // down child_channel_ before Init() has run.
-  internal::g_io_thread_task_runner->PostTask(
-      FROM_HERE,
-      base::Bind(&ChildBrokerHost::RegisterIOHandler, base::Unretained(this)));
-#endif
+      base::Bind(&ChildBrokerHost::InitOnIO, base::Unretained(this),
+                 base::Passed(&parent_async_channel_handle)));
 }
 
 base::ProcessId ChildBrokerHost::GetProcessId() {
@@ -96,7 +81,8 @@
   dispatchers->push_back(dispatcher);
   message->SetDispatchers(dispatchers.Pass());
   message->SerializeAndCloseDispatchers();
-  child_channel_->WriteMessage(message.Pass());
+  message->set_route_id(kBrokerRouteId);
+  child_channel_->channel()->WriteMessage(message.Pass());
 }
 
 void ChildBrokerHost::ConnectMessagePipe(uint64_t pipe_id,
@@ -109,14 +95,34 @@
   data.process_id = process_id;
   scoped_ptr<MessageInTransit> message(new MessageInTransit(
       MessageInTransit::Type::MESSAGE, sizeof(data), &data));
-  child_channel_->WriteMessage(message.Pass());
+  message->set_route_id(kBrokerRouteId);
+  child_channel_->channel()->WriteMessage(message.Pass());
 }
 
 ChildBrokerHost::~ChildBrokerHost() {
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
   BrokerState::GetInstance()->ChildBrokerHostDestructed(this);
   if (child_channel_)
-    child_channel_->Shutdown();
+    child_channel_->RemoveRoute(kBrokerRouteId);
+}
+
+void ChildBrokerHost::InitOnIO(
+    ScopedPlatformHandle parent_async_channel_handle) {
+  child_channel_ = new RoutedRawChannel(
+      parent_async_channel_handle.Pass(),
+      base::Bind(&ChildBrokerHost::ChannelDestructed, base::Unretained(this)));
+  child_channel_->AddRoute(kBrokerRouteId, this);
+
+  BrokerState::GetInstance()->ChildBrokerHostCreated(this);
+
+#if defined(OS_WIN)
+  // Call this after RoutedRawChannel calls its RawChannel::Init because this
+  // call could cause us to get notified that the child has gone away and to
+  // delete this class and shut down child_channel_ before Init() has run.
+  base::MessageLoopForIO::current()->RegisterIOHandler(
+      sync_channel_.get().handle, this);
+  BeginRead();
+#endif
 }
 
 void ChildBrokerHost::OnReadMessage(
@@ -149,8 +155,11 @@
 
 void ChildBrokerHost::OnError(Error error) {
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
-  child_channel_->Shutdown();
+  child_channel_->RemoveRoute(kBrokerRouteId);
   child_channel_ = nullptr;
+}
+
+void ChildBrokerHost::ChannelDestructed(RoutedRawChannel* channel) {
   // On Windows, we have two pipes to the child process. It's easier to wait
   // until we get the error from the pipe that is used for synchronous I/O.
 #if !defined(OS_WIN)
@@ -159,12 +168,6 @@
 }
 
 #if defined(OS_WIN)
-void ChildBrokerHost::RegisterIOHandler() {
-  base::MessageLoopForIO::current()->RegisterIOHandler(
-      sync_channel_.get().handle, this);
-  BeginRead();
-}
-
 void ChildBrokerHost::BeginRead() {
   BOOL rv = ReadFile(sync_channel_.get().handle,
                      &read_data_[num_bytes_read_],
diff --git a/mojo/edk/system/child_broker_host.h b/mojo/edk/system/child_broker_host.h
index 35153d4..c74c237 100644
--- a/mojo/edk/system/child_broker_host.h
+++ b/mojo/edk/system/child_broker_host.h
@@ -12,7 +12,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/process/process.h"
 #include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/raw_channel.h"
+#include "mojo/edk/system/routed_raw_channel.h"
 #include "mojo/edk/system/system_impl_export.h"
 
 namespace mojo {
@@ -42,20 +42,27 @@
   void ConnectToProcess(base::ProcessId process_id, ScopedPlatformHandle pipe);
 
   // Sends a message to the child process that |pipe_id|'s other end is in
-  // |process_id|.
+  // |process_id|. If the other end is in this parent process, |process_id| will
+  // be 0.
   void ConnectMessagePipe(uint64_t pipe_id, base::ProcessId process_id);
 
+  RoutedRawChannel* channel() { return child_channel_; }
+
  private:
   ~ChildBrokerHost() override;
 
+  void InitOnIO(ScopedPlatformHandle parent_async_channel_handle);
+
   // RawChannel::Delegate implementation:
   void OnReadMessage(
       const MessageInTransit::View& message_view,
       ScopedPlatformHandleVectorPtr platform_handles) override;
   void OnError(Error error) override;
 
+  // Callback for when child_channel_ is destroyed.
+  void ChannelDestructed(RoutedRawChannel* channel);
+
 #if defined(OS_WIN)
-  void RegisterIOHandler();
   void BeginRead();
 
   // base::MessageLoopForIO::IOHandler implementation:
@@ -71,7 +78,7 @@
   base::ProcessId process_id_;
 
   // Channel used to receive and send multiplexing related messages.
-  RawChannel* child_channel_;
+  RoutedRawChannel* child_channel_;
 
 #if defined(OS_WIN)
   // Handle to the child process, used for duplication of handles.
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc
index a7634175..77f5b3e 100644
--- a/mojo/edk/system/core.cc
+++ b/mojo/edk/system/core.cc
@@ -299,7 +299,11 @@
                       nullptr);
   } else {
     uint64_t pipe_id = 0;
-    while (pipe_id == 0)
+    // route_id 0 is used internally in RoutedRawChannel. See kInternalRouteId
+    // in routed_raw_channel.cc.
+    // route_id 1 is used by broker communication. See kBrokerRouteId in
+    // broker_messages.h.
+    while (pipe_id < 2)
       pipe_id = base::RandUint64();
     dispatcher0->InitNonTransferable(pipe_id);
     dispatcher1->InitNonTransferable(pipe_id);
diff --git a/mojo/edk/system/routed_raw_channel.cc b/mojo/edk/system/routed_raw_channel.cc
index 8a5e768..825fc2fa 100644
--- a/mojo/edk/system/routed_raw_channel.cc
+++ b/mojo/edk/system/routed_raw_channel.cc
@@ -7,13 +7,12 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "mojo/edk/embedder/embedder_internal.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
 
 namespace mojo {
 namespace edk {
 
 namespace {
-const uint64_t kInternalRoutingId = 0;
+const uint64_t kInternalRouteId = 0;
 }
 
 RoutedRawChannel::PendingMessage::PendingMessage() {
@@ -36,47 +35,46 @@
                   base::Unretained(channel_)));
 }
 
-void RoutedRawChannel::AddRoute(uint64_t pipe_id, MessagePipeDispatcher* pipe) {
-  CHECK_NE(pipe_id, kInternalRoutingId) << kInternalRoutingId << " is reserved";
-  base::AutoLock auto_lock(lock_);
-  CHECK(routes_.find(pipe_id) == routes_.end());
-  routes_[pipe_id] = pipe;
+void RoutedRawChannel::AddRoute(uint64_t route_id,
+                                RawChannel::Delegate* delegate) {
+  DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
+  CHECK_NE(route_id, kInternalRouteId) << kInternalRouteId << " is reserved";
+  CHECK(routes_.find(route_id) == routes_.end());
+  routes_[route_id] = delegate;
 
   for (size_t i = 0; i < pending_messages_.size();) {
     MessageInTransit::View view(pending_messages_[i]->message.size(),
                                 &pending_messages_[i]->message[0]);
-    if (view.route_id() == pipe_id) {
-      pipe->OnReadMessage(view, pending_messages_[i]->handles.Pass());
+    if (view.route_id() == route_id) {
+      delegate->OnReadMessage(view, pending_messages_[i]->handles.Pass());
       pending_messages_.erase(pending_messages_.begin() + i);
     } else {
       ++i;
     }
   }
 
-  if (close_routes_.find(pipe_id) != close_routes_.end())
-    pipe->OnError(ERROR_READ_SHUTDOWN);
+  if (close_routes_.find(route_id) != close_routes_.end())
+    delegate->OnError(ERROR_READ_SHUTDOWN);
 }
 
-void RoutedRawChannel::RemoveRoute(uint64_t pipe_id,
-                                   MessagePipeDispatcher* pipe) {
-  base::AutoLock auto_lock(lock_);
-  CHECK(routes_.find(pipe_id) != routes_.end());
-  CHECK_EQ(routes_[pipe_id], pipe);
-  routes_.erase(pipe_id);
+void RoutedRawChannel::RemoveRoute(uint64_t route_id) {
+  DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
+  CHECK(routes_.find(route_id) != routes_.end());
+  routes_.erase(route_id);
 
   // Only send a message to the other side to close the route if we hadn't
   // received a close route message. Otherwise they would keep going back and
   // forth.
-  if (close_routes_.find(pipe_id) != close_routes_.end()) {
-    close_routes_.erase(pipe_id);
+  if (close_routes_.find(route_id) != close_routes_.end()) {
+    close_routes_.erase(route_id);
   } else if (channel_) {
     // Default route id of 0 to reach the other side's RoutedRawChannel.
     char message_data[sizeof(uint64_t)];
-    memcpy(&message_data[0], &pipe_id, sizeof(uint64_t));
+    memcpy(&message_data[0], &route_id, sizeof(uint64_t));
     scoped_ptr<MessageInTransit> message(new MessageInTransit(
         MessageInTransit::Type::MESSAGE, arraysize(message_data),
           message_data));
-    message->set_route_id(kInternalRoutingId);
+    message->set_route_id(kInternalRouteId);
     channel_->WriteMessage(message.Pass());
   }
 
@@ -95,14 +93,13 @@
     ScopedPlatformHandleVectorPtr platform_handles) {
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
   // Note: normally, when a message arrives here we should find a corresponding
-  // entry for the MessagePipeDispatcher with the given route_id. However it is
+  // entry for the RawChannel::Delegate with the given route_id. However it is
   // possible that they just connected, and due to race conditions one side has
   // connected and sent a message (and even closed) before the other side had a
   // chance to register with this RoutedRawChannel. In that case, we must buffer
   // all messages.
-  base::AutoLock auto_lock(lock_);
   uint64_t route_id = message_view.route_id();
-  if (route_id == kInternalRoutingId) {
+  if (route_id == kInternalRouteId) {
     if (message_view.num_bytes() !=  sizeof(uint64_t)) {
       NOTREACHED() << "Invalid internal message in RoutedRawChannel." ;
       return;
@@ -134,22 +131,19 @@
 
 void RoutedRawChannel::OnError(Error error) {
   DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
-  bool destruct = false;
-  {
-    base::AutoLock auto_lock(lock_);
 
-    channel_->Shutdown();
-    channel_ = nullptr;
-    if (routes_.empty()) {
-      destruct = true;
-    } else {
-      for (auto it = routes_.begin(); it != routes_.end(); ++it)
-        it->second->OnError(error);
-    }
+  channel_->Shutdown();
+  channel_ = nullptr;
+  if (routes_.empty()) {
+    delete this;
+    return;
   }
 
-  if (destruct)
-    delete this;
+  for (auto it = routes_.begin(); it != routes_.end();) {
+    // Handle the delegate calling RemoveRoute in this call.
+    auto cur_it = it++;
+    cur_it->second->OnError(error);
+  }
 }
 
 }  // namespace edk
diff --git a/mojo/edk/system/routed_raw_channel.h b/mojo/edk/system/routed_raw_channel.h
index f5a350b..3461d64b 100644
--- a/mojo/edk/system/routed_raw_channel.h
+++ b/mojo/edk/system/routed_raw_channel.h
@@ -8,7 +8,6 @@
 #include "base/callback.h"
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
-#include "base/synchronization/lock.h"
 #include "mojo/edk/embedder/platform_handle_vector.h"
 #include "mojo/edk/embedder/scoped_platform_handle.h"
 #include "mojo/edk/system/broker.h"
@@ -20,20 +19,21 @@
 class RawChannel;
 
 // This class wraps a RawChannel and adds routing on top of it.
-// Non-transferable MessagePipeDispatchers call here, indirectly through the
-// Broker interface, to associate with their pipe_id.
+// Any RawChannel::Delegate can call here, indirectly through the Broker
+// interface, to get notified about messages with its route_id.
 class RoutedRawChannel : public RawChannel::Delegate {
  public:
   RoutedRawChannel(
       ScopedPlatformHandle handle,
       const base::Callback<void(RoutedRawChannel*)>& destruct_callback);
 
-  // Connect the given |pipe| with the pipe_id route. Only non-transferable
-  // message pipes can call this, and they can only call it once.
-  void AddRoute(uint64_t pipe_id, MessagePipeDispatcher* pipe);
+  // These methods should all be called on the IO thread only.
 
-  // Called when the MessagePipeDispatcher is going away.
-  void RemoveRoute(uint64_t pipe_id, MessagePipeDispatcher* pipe);
+  // Connect the given |delegate| with the |route_id|.
+  void AddRoute(uint64_t route_id, RawChannel::Delegate* delegate);
+
+  // Called when the route listener is going away.
+  void RemoveRoute(uint64_t route_id);
 
   RawChannel* channel() { return channel_; }
 
@@ -49,8 +49,7 @@
 
   RawChannel* channel_;
 
-  base::Lock lock_;  // Guards access to below.
-  base::hash_map<uint64_t, MessagePipeDispatcher*> routes_;
+  base::hash_map<uint64_t, RawChannel::Delegate*> routes_;
 
   // If we got messages before the route was added (due to race conditions
   // between different channels), this is used to buffer them.
diff --git a/mojo/public/cpp/system/handle.h b/mojo/public/cpp/system/handle.h
index 45624bc..1c3b149 100644
--- a/mojo/public/cpp/system/handle.h
+++ b/mojo/public/cpp/system/handle.h
@@ -285,6 +285,11 @@
   return a.value() < b.value();
 }
 
+// Comparison, so that |Handle|s can be used as keys in hash maps.
+inline bool operator==(const Handle a, const Handle b) {
+  return a.value() == b.value();
+}
+
 }  // namespace mojo
 
 #endif  // MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index 66b4401..f26b394 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -890,8 +890,6 @@
     if (notbroken_alternative_service_info_vector.empty()) {
       continue;
     }
-    alternative_service_map->Put(server,
-                                 notbroken_alternative_service_info_vector);
     std::string canonical_suffix =
         http_server_properties_impl_->GetCanonicalSuffix(server.host());
     if (!canonical_suffix.empty()) {
@@ -899,16 +897,20 @@
         continue;
       persisted_map[canonical_suffix] = true;
     }
+    alternative_service_map->Put(server,
+                                 notbroken_alternative_service_info_vector);
     ++count;
   }
 
   ServerNetworkStatsMap* server_network_stats_map =
       new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist);
-  const ServerNetworkStatsMap& main_server_network_stats_map =
+  const ServerNetworkStatsMap& network_stats_map =
       http_server_properties_impl_->server_network_stats_map();
-  for (ServerNetworkStatsMap::const_iterator it =
-           main_server_network_stats_map.begin();
-       it != main_server_network_stats_map.end(); ++it) {
+  count = 0;
+  for (ServerNetworkStatsMap::const_iterator it = network_stats_map.begin();
+       it != network_stats_map.end() &&
+       count < kMaxServerNetworkStatsHostsToPersist;
+       ++it, ++count) {
     server_network_stats_map->Put(it->first, it->second);
   }
 
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc
index 60ae002b..2eed68c3 100644
--- a/net/quic/quic_protocol_test.cc
+++ b/net/quic/quic_protocol_test.cc
@@ -7,6 +7,7 @@
 #include <sstream>
 
 #include "base/stl_util.h"
+#include "net/quic/quic_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
@@ -45,6 +46,20 @@
   EXPECT_TRUE(IsAwaitingPacket(ack_frame, 10u));
 }
 
+TEST(QuicProtocolTest, QuicDeprecatedErrorCodeCount) {
+  // If you deprecated any QuicErrorCode, you will need to update the
+  // deprecated QuicErrorCode count. Otherwise this test will fail.
+  int num_deprecated_errors = 0;
+  std::string invalid_error_code = "INVALID_ERROR_CODE";
+  for (int i = 0; i < QUIC_LAST_ERROR; ++i) {
+    if (QuicUtils::ErrorToString(static_cast<QuicErrorCode>(i)) ==
+        invalid_error_code) {
+      ++num_deprecated_errors;
+    }
+  }
+  EXPECT_EQ(kDeprecatedQuicErrorCount, num_deprecated_errors);
+}
+
 TEST(QuicProtocolTest, QuicVersionToQuicTag) {
   // If you add a new version to the QuicVersion enum you will need to add a new
   // case to QuicVersionToQuicTag, otherwise this test will fail.
diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc
index 90d357c..f3ccf98 100644
--- a/net/quic/test_tools/crypto_test_utils_chromium.cc
+++ b/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -72,7 +72,7 @@
   scoped_ptr<CTVerifier> cert_transparency_verifier_;
 };
 
-const string kSignature(2048, 's');
+const char kSignature[] = "signature";
 const char kSCT[] = "CryptoServerTests";
 
 class FakeProofSource : public ProofSource {
@@ -216,7 +216,7 @@
 #endif
   base::FilePath certs_dir = GetTestCertsDirectory();
   CHECK(source->Initialize(
-      certs_dir.AppendASCII("quic_test.example.com.crt"),
+      certs_dir.AppendASCII("quic_chain.crt"),
       certs_dir.AppendASCII("quic_test.example.com.key.pkcs8"),
       certs_dir.AppendASCII("quic_test.example.com.key.sct")));
   return source;
diff --git a/net/sdch/sdch_owner.cc b/net/sdch/sdch_owner.cc
index ca9b5a7..81936c2b 100644
--- a/net/sdch/sdch_owner.cc
+++ b/net/sdch/sdch_owner.cc
@@ -489,12 +489,11 @@
   base::TimeDelta time_since_last_used(now -
       base::Time::FromDoubleT(last_used_seconds_since_epoch));
 
-  // TODO(rdsmith): Distinguish between "Never used" and "Actually not
-  // touched for 48 hours".
-  UMA_HISTOGRAM_CUSTOM_TIMES(
-      "Sdch3.UsageInterval",
-      use_count ? time_since_last_used : base::TimeDelta::FromHours(48),
-      base::TimeDelta(), base::TimeDelta::FromHours(48), 50);
+  if (use_count) {
+    UMA_HISTOGRAM_CUSTOM_TIMES("Sdch3.UsageInterval2", time_since_last_used,
+                               base::TimeDelta(), base::TimeDelta::FromDays(7),
+                               50);
+  }
 
   specific_dictionary_map->SetDouble(kDictionaryLastUsedKey, now.ToDoubleT());
   specific_dictionary_map->SetInteger(kDictionaryUseCountKey, use_count + 1);
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 814951cf..d1a3038 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -563,9 +563,7 @@
   EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
 }
 
-// TODO(jri): This test fails in net_unittest. Figure out whether to leave
-// disabled or to fix it.
-TEST_P(EndToEndTest, DISABLED_SimpleRequestResponseWithLargeReject) {
+TEST_P(EndToEndTest, SimpleRequestResponseWithLargeReject) {
   chlo_multiplier_ = 1;
   ASSERT_TRUE(Initialize());
 
diff --git a/ppapi/BUILD.gn b/ppapi/BUILD.gn
index 818736e..842dbbd 100644
--- a/ppapi/BUILD.gn
+++ b/ppapi/BUILD.gn
@@ -70,7 +70,7 @@
   ]
 }
 
-shared_library("blink_test_plugin") {
+loadable_module("blink_test_plugin") {
   sources = [
     "tests/blink_test_plugin.cc",
   ]
diff --git a/ppapi/examples/BUILD.gn b/ppapi/examples/BUILD.gn
index 9369c585..65eb4645 100644
--- a/ppapi/examples/BUILD.gn
+++ b/ppapi/examples/BUILD.gn
@@ -7,6 +7,7 @@
   deps = [
     "//ppapi/examples/2d",
     "//ppapi/examples/audio",
+    "//ppapi/examples/audio_encode",
     "//ppapi/examples/audio_input",
     "//ppapi/examples/compositor",
     "//ppapi/examples/crxfs",
diff --git a/ppapi/examples/audio_encode/BUILD.gn b/ppapi/examples/audio_encode/BUILD.gn
new file mode 100644
index 0000000..2c68f68
--- /dev/null
+++ b/ppapi/examples/audio_encode/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2015 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("//ppapi/examples/ppapi_example.gni")
+
+ppapi_example("audio_encode") {
+  output_name = "ppapi_example_audio_encode"
+  sources = [
+    "audio_encode.cc",
+  ]
+  deps = [
+    "//ppapi/cpp",
+  ]
+}
diff --git a/ppapi/examples/audio_encode/audio_encode.cc b/ppapi/examples/audio_encode/audio_encode.cc
new file mode 100644
index 0000000..a5f3372
--- /dev/null
+++ b/ppapi/examples/audio_encode/audio_encode.cc
@@ -0,0 +1,383 @@
+// Copyright 2015 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 <stdlib.h>
+#include <string.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "ppapi/cpp/audio_buffer.h"
+#include "ppapi/cpp/audio_encoder.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/media_stream_audio_track.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var_array_buffer.h"
+#include "ppapi/cpp/var_dictionary.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+// When compiling natively on Windows, PostMessage can be #define-d to
+// something else.
+#ifdef PostMessage
+#undef PostMessage
+#endif
+
+// This example demonstrates receiving audio samples from an audio
+// track and encoding them.
+
+namespace {
+
+class AudioEncoderInstance : public pp::Instance {
+ public:
+  explicit AudioEncoderInstance(PP_Instance instance);
+  virtual ~AudioEncoderInstance();
+
+ private:
+  // pp::Instance implementation.
+  virtual void HandleMessage(const pp::Var& var_message);
+
+  std::string ProfileToString(PP_AudioProfile profile);
+
+  void GetSupportedProfiles();
+  void OnGetSupportedProfiles(
+      int32_t result,
+      const std::vector<PP_AudioProfileDescription> profiles);
+
+  void StartAudioTrack(const pp::Resource& resource_track);
+  void StopAudioTrack();
+  void OnGetBuffer(int32_t result, pp::AudioBuffer buffer);
+
+  void InitializeEncoder();
+  void OnEncoderInitialized(int32_t result);
+  void OnAudioTrackConfigured(int32_t result);
+  void GetEncoderBuffer(const pp::AudioBuffer& track_buffer);
+  void OnGetEncoderBuffer(int32_t result,
+                          pp::AudioBuffer buffer,
+                          pp::AudioBuffer track_buffer);
+  void OnEncodeDone(int32_t result);
+  void OnGetBitstreamBuffer(int32_t result,
+                            const PP_AudioBitstreamBuffer& buffer);
+
+  pp::VarDictionary NewCommand(const std::string& type);
+
+  void Log(const std::string& message);
+  void LogError(int32_t error, const std::string& message);
+
+  void PostAudioFormat();
+  void PostDataMessage(const void* data, uint32_t size);
+
+  pp::CompletionCallbackFactory<AudioEncoderInstance> callback_factory_;
+
+  // Set when the plugin is not performing any encoding and just passing the
+  // uncompressed data directly to web page.
+  bool no_encoding_;
+
+  uint32_t channels_;
+  uint32_t sample_rate_;
+  uint32_t sample_size_;
+  uint32_t samples_per_frame_;
+
+  pp::MediaStreamAudioTrack audio_track_;
+  pp::AudioEncoder audio_encoder_;
+};
+
+AudioEncoderInstance::AudioEncoderInstance(PP_Instance instance)
+    : pp::Instance(instance),
+      callback_factory_(this),
+      no_encoding_(true),
+      channels_(0),
+      sample_rate_(0),
+      sample_size_(0),
+      samples_per_frame_(0),
+      audio_encoder_(this) {
+  GetSupportedProfiles();
+}
+
+AudioEncoderInstance::~AudioEncoderInstance() {}
+
+void AudioEncoderInstance::HandleMessage(const pp::Var& var_message) {
+  if (!var_message.is_dictionary()) {
+    LogError(PP_ERROR_FAILED,
+             "Cannot handle incoming message, not a dictionary");
+    return;
+  }
+
+  pp::VarDictionary dict_message(var_message);
+  std::string command = dict_message.Get("command").AsString();
+
+  if (command == "start") {
+    pp::Var var_track = dict_message.Get("track");
+    if (!var_track.is_resource()) {
+      LogError(PP_ERROR_FAILED, "Given track is not a resource");
+      return;
+    }
+    std::string profile = dict_message.Get("profile").AsString();
+    if (profile == "wav") {
+      no_encoding_ = true;
+    } else {
+      no_encoding_ = false;
+    }
+    StartAudioTrack(var_track.AsResource());
+  } else if (command == "stop") {
+    StopAudioTrack();
+  } else {
+    LogError(PP_ERROR_FAILED, "Invalid command");
+  }
+}
+
+std::string AudioEncoderInstance::ProfileToString(PP_AudioProfile profile) {
+  if (profile == PP_AUDIOPROFILE_OPUS)
+    return "opus";
+  return "unknown";
+}
+
+void AudioEncoderInstance::GetSupportedProfiles() {
+  audio_encoder_.GetSupportedProfiles(callback_factory_.NewCallbackWithOutput(
+      &AudioEncoderInstance::OnGetSupportedProfiles));
+}
+
+void AudioEncoderInstance::OnGetSupportedProfiles(
+    int32_t result,
+    const std::vector<PP_AudioProfileDescription> profiles) {
+  pp::VarDictionary dictionary = NewCommand("supportedProfiles");
+  pp::VarArray js_profiles;
+  dictionary.Set(pp::Var("profiles"), js_profiles);
+
+  if (result < 0) {
+    LogError(result, "Cannot get supported profiles");
+    PostMessage(dictionary);
+  }
+
+  int32_t idx = 0;
+  for (std::vector<PP_AudioProfileDescription>::const_iterator it =
+           profiles.begin();
+       it != profiles.end(); ++it) {
+    pp::VarDictionary js_profile;
+    js_profile.Set(pp::Var("name"), pp::Var(ProfileToString(it->profile)));
+    js_profile.Set(pp::Var("sample_size"),
+                   pp::Var(static_cast<int32_t>(it->sample_size)));
+    js_profile.Set(pp::Var("sample_rate"),
+                   pp::Var(static_cast<int32_t>(it->sample_rate)));
+    js_profiles.Set(idx++, js_profile);
+  }
+  PostMessage(dictionary);
+}
+
+void AudioEncoderInstance::StartAudioTrack(const pp::Resource& resource_track) {
+  audio_track_ = pp::MediaStreamAudioTrack(resource_track);
+  audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
+      &AudioEncoderInstance::OnGetBuffer));
+}
+
+void AudioEncoderInstance::StopAudioTrack() {
+  channels_ = 0;
+  audio_track_.Close();
+  audio_track_ = pp::MediaStreamAudioTrack();
+  audio_encoder_.Close();
+  audio_encoder_ = pp::AudioEncoder();
+}
+
+void AudioEncoderInstance::OnGetBuffer(int32_t result, pp::AudioBuffer buffer) {
+  if (result == PP_ERROR_ABORTED)
+    return;
+  if (result != PP_OK) {
+    LogError(result, "Cannot get audio track buffer");
+    return;
+  }
+
+  // If this is the first buffer, then we need to initialize the encoder.
+  if (channels_ == 0) {
+    channels_ = buffer.GetNumberOfChannels();
+    sample_rate_ = buffer.GetSampleRate();
+    sample_size_ = buffer.GetSampleSize();
+    samples_per_frame_ = buffer.GetNumberOfSamples();
+
+    if (no_encoding_) {
+      PostAudioFormat();
+      PostDataMessage(buffer.GetDataBuffer(), buffer.GetDataBufferSize());
+      audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
+          &AudioEncoderInstance::OnGetBuffer));
+    } else {
+      InitializeEncoder();
+    }
+
+    // Given that once the encoder is initialized we might reconfigure the
+    // media track, we discard the first buffer to keep this example a bit
+    // simpler.
+    audio_track_.RecycleBuffer(buffer);
+  } else {
+    if (no_encoding_) {
+      PostDataMessage(buffer.GetDataBuffer(), buffer.GetDataBufferSize());
+      audio_track_.RecycleBuffer(buffer);
+    } else {
+      GetEncoderBuffer(buffer);
+    }
+
+    audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
+        &AudioEncoderInstance::OnGetBuffer));
+  }
+}
+
+void AudioEncoderInstance::InitializeEncoder() {
+  if (audio_encoder_.is_null())
+    audio_encoder_ = pp::AudioEncoder(this);
+  audio_encoder_.Initialize(
+      channels_, static_cast<PP_AudioBuffer_SampleRate>(sample_rate_),
+      static_cast<PP_AudioBuffer_SampleSize>(sample_size_),
+      PP_AUDIOPROFILE_OPUS, 100000, PP_HARDWAREACCELERATION_WITHFALLBACK,
+      callback_factory_.NewCallback(
+          &AudioEncoderInstance::OnEncoderInitialized));
+}
+
+void AudioEncoderInstance::OnEncoderInitialized(int32_t result) {
+  if (result == PP_ERROR_ABORTED)
+    return;
+  if (result != PP_OK) {
+    LogError(result, "Cannot initialize encoder");
+    return;
+  }
+
+  int32_t attribs[] = {
+      // Duration in milliseconds.
+      PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION,
+      1000 / (sample_rate_ / audio_encoder_.GetNumberOfSamples()),
+      PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE};
+  audio_track_.Configure(attribs,
+                         callback_factory_.NewCallback(
+                             &AudioEncoderInstance::OnAudioTrackConfigured));
+
+  samples_per_frame_ = audio_encoder_.GetNumberOfSamples();
+  PostAudioFormat();
+}
+
+void AudioEncoderInstance::OnAudioTrackConfigured(int32_t result) {
+  if (result == PP_ERROR_ABORTED)
+    return;
+  if (result != PP_OK) {
+    LogError(result, "Cannot configure audio track buffer duration");
+    return;
+  }
+
+  audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
+      &AudioEncoderInstance::OnGetBuffer));
+  audio_encoder_.GetBitstreamBuffer(callback_factory_.NewCallbackWithOutput(
+      &AudioEncoderInstance::OnGetBitstreamBuffer));
+}
+
+void AudioEncoderInstance::GetEncoderBuffer(
+    const pp::AudioBuffer& track_buffer) {
+  audio_encoder_.GetBuffer(callback_factory_.NewCallbackWithOutput(
+      &AudioEncoderInstance::OnGetEncoderBuffer, track_buffer));
+}
+
+void AudioEncoderInstance::OnGetEncoderBuffer(int32_t result,
+                                              pp::AudioBuffer buffer,
+                                              pp::AudioBuffer track_buffer) {
+  const char* error(nullptr);
+
+  if (result != PP_OK)
+    error = "Cannot get encoder buffer";
+  if (buffer.GetDataBufferSize() != track_buffer.GetDataBufferSize()) {
+    result = PP_ERROR_FAILED;
+    error = "Invalid buffer size";
+  }
+
+  if (result == PP_OK) {
+    memcpy(buffer.GetDataBuffer(), track_buffer.GetDataBuffer(),
+           buffer.GetDataBufferSize());
+    audio_encoder_.Encode(buffer, callback_factory_.NewCallback(
+                                      &AudioEncoderInstance::OnEncodeDone));
+  } else {
+    LogError(result, error);
+    StopAudioTrack();
+  }
+  audio_track_.RecycleBuffer(track_buffer);
+}
+
+void AudioEncoderInstance::OnEncodeDone(int32_t result) {}
+
+void AudioEncoderInstance::OnGetBitstreamBuffer(
+    int32_t result,
+    const PP_AudioBitstreamBuffer& buffer) {
+  if (result == PP_ERROR_ABORTED)
+    return;
+  if (result != PP_OK) {
+    LogError(result, "Cannot get bitstream buffer");
+    return;
+  }
+
+  audio_encoder_.GetBitstreamBuffer(callback_factory_.NewCallbackWithOutput(
+      &AudioEncoderInstance::OnGetBitstreamBuffer));
+
+  PostDataMessage(buffer.buffer, buffer.size);
+  audio_encoder_.RecycleBitstreamBuffer(buffer);
+}
+
+pp::VarDictionary AudioEncoderInstance::NewCommand(const std::string& type) {
+  pp::VarDictionary dictionary;
+  dictionary.Set(pp::Var("command"), pp::Var(type));
+  return dictionary;
+}
+
+void AudioEncoderInstance::Log(const std::string& message) {
+  pp::VarDictionary dictionary = NewCommand("log");
+  dictionary.Set(pp::Var("message"), pp::Var(message));
+  PostMessage(dictionary);
+}
+
+void AudioEncoderInstance::LogError(int32_t error, const std::string& message) {
+  pp::VarDictionary dictionary = NewCommand("error");
+  std::string msg("Error: ");
+  msg.append(message);
+  msg.append(" : ");
+  msg.append(pp::Var(error).DebugString());
+  dictionary.Set(pp::Var("message"), pp::Var(msg));
+  PostMessage(dictionary);
+}
+
+void AudioEncoderInstance::PostAudioFormat() {
+  pp::VarDictionary dictionary = NewCommand("format");
+  dictionary.Set(pp::Var("channels"), pp::Var(static_cast<int32_t>(channels_)));
+  dictionary.Set(pp::Var("sample_rate"),
+                 pp::Var(static_cast<int32_t>(sample_rate_)));
+  dictionary.Set(pp::Var("sample_size"),
+                 pp::Var(static_cast<int32_t>(sample_size_)));
+  dictionary.Set(pp::Var("sample_per_frame"),
+                 pp::Var(static_cast<int32_t>(samples_per_frame_)));
+  PostMessage(dictionary);
+}
+
+void AudioEncoderInstance::PostDataMessage(const void* data, uint32_t size) {
+  pp::VarDictionary dictionary = NewCommand("data");
+  uint8_t* buffer;
+
+  pp::VarArrayBuffer array_buffer = pp::VarArrayBuffer(size);
+  buffer = static_cast<uint8_t*>(array_buffer.Map());
+  memcpy(buffer, data, size);
+  array_buffer.Unmap();
+
+  dictionary.Set(pp::Var("buffer"), array_buffer);
+
+  PostMessage(dictionary);
+}
+
+class AudioEncoderModule : public pp::Module {
+ public:
+  virtual pp::Instance* CreateInstance(PP_Instance instance) {
+    return new AudioEncoderInstance(instance);
+  }
+};
+
+}  // namespace
+
+namespace pp {
+
+// Factory function for your specialization of the Module object.
+Module* CreateModule() {
+  return new AudioEncoderModule();
+}
+
+}  // namespace pp
diff --git a/ppapi/examples/audio_encode/audio_encode.html b/ppapi/examples/audio_encode/audio_encode.html
new file mode 100644
index 0000000..36b322a
--- /dev/null
+++ b/ppapi/examples/audio_encode/audio_encode.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html>
+<html>
+  <!--
+  Copyright 2015 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.
+  -->
+<head>
+  <title>Audio Encoder Example</title>
+  <script type="text/javascript">
+    var plugin;
+    var track;
+    var writer;
+    var profiles;
+
+    function writeString(array, offset, string) {
+      var out = new Uint8Array(array);
+      for (var i = 0; i < string.length; i++)
+        out.set([string.charCodeAt(i)], i + offset);
+      return string.length;
+    }
+    function writeValue(array, bytes, offset, value) {
+      var out = new Uint8Array(array);
+      for (var i = 0; i < bytes; i++)
+        out.set([((value >>> (i * 8)) & 0xff)], offset + i);
+      return bytes;
+    }
+    // Writes way data.
+    var WavWriter = function() {
+      this.chunkSizeOffset = 0;
+      this.arrayBuffer = new ArrayBuffer();
+    };
+    WavWriter.prototype = {
+      writeHeader: function(format) {
+        this.arrayBuffer =
+          new ArrayBuffer(4 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 2 + 2 + 4 + 4);
+        var i = 0;
+        // File header
+        i += writeString(this.arrayBuffer, i, 'RIFF');
+        i += 4; // Gap for final size.
+        i += writeString(this.arrayBuffer, i, 'WAVE');
+        // Chunk ID.
+        i += writeString(this.arrayBuffer, i, 'fmt ');
+        // Chunk length.
+        i += writeValue(this.arrayBuffer, 4, i, 16);
+        // Codec (uncompressed LPCM).
+        i += writeValue(this.arrayBuffer, 2, i, 1);
+        // Number of channels.
+        i += writeValue(this.arrayBuffer, 2, i, format.channels);
+        // Sample rate.
+        i += writeValue(this.arrayBuffer, 4, i, format.sample_rate);
+        // Average bytes per seconds (sample rate * bytes per sample)
+        i += writeValue(this.arrayBuffer, 4, i,
+                        format.sample_rate * format.sample_size);
+        // Bytes per sample.
+        i += writeValue(this.arrayBuffer, 2, i,
+                        format.sample_size * format.channels);
+        // Bits per sample.
+        i += writeValue(this.arrayBuffer, 2, i, format.sample_size * 8);
+
+        // Data chunk
+        i += writeString(this.arrayBuffer, i, 'data');
+        this.chunkSizeOffset = i; // Location of the chunk's size
+      },
+      writeData: function(data) {
+        var tmp = new Uint8Array(this.arrayBuffer.byteLength + data.byteLength);
+        tmp.set(new Uint8Array(this.arrayBuffer), 0);
+        tmp.set(new Uint8Array(data), this.arrayBuffer.byteLength);
+        this.arrayBuffer = tmp.buffer;
+      },
+      end: function() {
+        var out = new Uint32Array(this.arrayBuffer);
+        out.set([this.arrayBuffer.byteLength - 8], 1);
+        out.set([this.arrayBuffer.byteLength - this.chunkSizeOffset],
+                this.chunkSizeOffset / 4);
+      },
+      getSize: function() {
+        return this.arrayBuffer.byteLength;
+      },
+      getData: function() {
+        return this.arrayBuffer;
+      },
+      getExtension: function() {
+        return 'wav';
+      },
+    };
+
+    // Writes ogg data.
+    var OggWriter = function(profile) {
+      this.writeHeader = this._writeOpusHeader;
+      this.arrayBuffer = new ArrayBuffer();
+      this.pageSequence = 0;
+      this.bitstreamNumber = 0;
+      this.position = 0;
+      this.dataWritten = false;
+    };
+    OggWriter.prototype = {
+      _Start: 0x2,
+      _Continue: 0x1,
+      _Stop: 0x4,
+      _append: function(data) {
+        var tmp = new Uint8Array(this.arrayBuffer.byteLength + data.byteLength);
+        tmp.set(new Uint8Array(this.arrayBuffer), 0);
+        tmp.set(new Uint8Array(data), this.arrayBuffer.byteLength);
+        this.arrayBuffer = tmp.buffer;
+      },
+      _makeCRCTable: function() {
+        var crcTable = [];
+        for (var n = 0; n < 256; n++) {
+          var r = n << 24;
+          for (var i = 0; i < 8; i++) {
+            if (r & 0x80000000)
+              r = (r << 1) ^ 0x04c11db7;
+            else
+              r <<= 1;
+          }
+          crcTable[n] = r & 0xffffffff;
+        }
+        return crcTable;
+      },
+      _crc32: function(data, start, end) {
+        var crc = 0;
+        var u8data = new Uint8Array(data)
+        var crcTable = this._crcTable || (this._crcTable = this._makeCRCTable());
+        for (var i = start; i < end; i++)
+          crc = (crc << 8) ^ crcTable[((crc >> 24) & 0xff) ^ u8data[i]];
+        return crc;
+      },
+      _writePage: function(flag, size, position) {
+        var pages = 1 + Math.floor(size / 255);
+        var buffer = new ArrayBuffer(27 + pages), i = 0;
+        // capture_pattern.
+        i += writeString(buffer, i, 'OggS');
+        // stream_structure_version.
+        i += writeValue(buffer, 1, i, 0);
+        // header_type_flag.
+        i += writeValue(buffer, 1, i, flag);
+        // granule_position.
+        // TODO(llandwerlin): Not writing more than 32bits for now,
+        // because Javascript doesn't have 64bits integers, this limits
+        // the duration to ~24 hours at 48kHz sampling rate.
+        i += writeValue(buffer, 4, i, position != undefined ? position : 0);
+        i += writeValue(buffer, 4, i, 0);
+        // bitstream_serial_number.
+        i += writeValue(buffer, 4, i, this.bitstreamNumber);
+        // page_sequence_number.
+        i += writeValue(buffer, 4, i, this.pageSequence++);
+        // CRC_checksum.
+        i += writeValue(buffer, 4, i, 0);
+        // number_page_segments.
+        i += writeValue(buffer, 1, i, pages);
+        // segment sizes.
+        for (var j = 0; j < (pages - 1); j++)
+          i += writeValue(buffer, 1, i, 255);
+        i += writeValue(buffer, 1, i, size % 255);
+
+        this._append(buffer);
+      },
+      _writePageChecksum: function(pageOffset) {
+        var crc = this._crc32(this.arrayBuffer, pageOffset,
+                              this.arrayBuffer.byteLength);
+        writeValue(this.arrayBuffer, 4, pageOffset + 22, crc);
+      },
+      _writeOpusHeader: function(format) {
+        this.format = format;
+        var start = this.getSize();
+        var buffer = new ArrayBuffer(8 + 1 + 1 + 2 + 4 + 2 + 1), i = 0;
+        // Opus header.
+        i += writeString(buffer, i, 'OpusHead');
+        // version.
+        i += writeValue(buffer, 1, i, 1);
+        // channel count.
+        i += writeValue(buffer, 1, i, format.channels);
+        // pre-skip.
+        i += writeValue(buffer, 2, i, 0);
+        // input sample rate.
+        i += writeValue(buffer, 4, i, format.sample_rate);
+        // output gain.
+        i += writeValue(buffer, 2, i, 0);
+        // channel mapping family.
+        i += writeValue(buffer, 1, i, 0);
+
+        this._writePage(this._Start, buffer.byteLength);
+        this._append(buffer);
+        this._writePageChecksum(start);
+        this._writeCommentHeader('OpusTags');
+      },
+      _writeCommentHeader: function(name) {
+        var start = this.getSize();
+        var buffer = new ArrayBuffer(8 + 4 + 8 + 4 + 4 + 13), i = 0;
+        // Opus comment header.
+        i += writeString(buffer, i, name);
+        // Vendor string.
+        i += this._writeLengthString(buffer, i, 'Chromium');
+        // User comment list length
+        i += writeValue(buffer, 4, i, 1);
+        // User comment 0 length.
+        i += this._writeLengthString(buffer, i, 'TITLE=example');
+
+        this._writePage(this._Continue, buffer.byteLength);
+        this._append(buffer);
+        this._writePageChecksum(start);
+      },
+      _writeLengthString: function(buffer, offset, str) {
+        return (writeValue(buffer, offset, 4, str.length) +
+                writeString(buffer, offset, str));
+      },
+      writeData: function(data) {
+        this.position += this.format.sample_per_frame / this.format.channels;
+        var start = this.getSize();
+        this._writePage(0, data.byteLength, this.position);
+        this._append(data);
+        this._writePageChecksum(start);
+        this.dataWritten = true;
+      },
+      end: function() {
+        this._writePage(this._Stop, 0);
+      },
+      getSize: function() {
+        return this.arrayBuffer.byteLength;
+      },
+      getData: function() {
+        return this.arrayBuffer;
+      },
+      getExtension: function() {
+        return 'ogg';
+      },
+    };
+
+    function $(id) {
+      return document.getElementById(id);
+    }
+
+    function success(stream) {
+      track = stream.getAudioTracks()[0];
+      var list = $('profileList');
+      var profile = profiles[list.selectedIndex];
+      plugin.postMessage({
+        command: 'start',
+        profile: profile.name,
+        sample_size: profile.sample_size,
+        sample_rate: profile.sample_rate,
+        track: track,
+      });
+    }
+
+    function failure(e) {
+      console.log("Error: ", e);
+    }
+
+    function cleanupDownload() {
+      var download = $('download');
+      if (!download)
+        return;
+      download.parentNode.removeChild(download);
+    }
+
+    function setDownload(data, filename) {
+      var mimeType = 'application/octet-stream';
+      var blob = new Blob([data], { type: mimeType });
+      var a = document.createElement('a');
+      a.id = "download";
+      a.download = filename;
+      a.href = window.URL.createObjectURL(blob);
+      a.textContent = 'Download';
+      a.dataset.downloadurl = [mimeType, a.download, a.href].join(':');
+      $('download-box').appendChild(a);
+    }
+
+    function startRecord() {
+      var list = $('profileList');
+      var profile = profiles[list.selectedIndex];
+      if (profile.name == 'wav')
+        writer = new WavWriter();
+      else
+        writer = new OggWriter(profile);
+      cleanupDownload();
+
+      var constraints = [];
+      if (profile.name == 'opus') {
+        // Chromium outputs 32kHz sampling rate by default. This isn't a
+        // supported sampling rate for the Opus codec. So we force the
+        // output to 48kHz. If Chromium implements the GetUserMedia
+        // audio constraints at some point, we could potentially get rid
+        // of this.
+        constraints.push({ googAudioProcessing48kHzSupport: true });
+      }
+
+      navigator.webkitGetUserMedia({ audio: { optional: constraints },
+                                     video: false},
+                                   success, failure);
+    }
+
+    function stopRecord() {
+      plugin.postMessage({
+        command: "stop"
+      });
+      track.stop();
+      writer.end();
+      setDownload(writer.getData(), 'Capture.' + writer.getExtension());
+    }
+
+    function saveBlob(blob) {
+      var blobUrl = URL.createObjectURL(blob);
+      window.location = blobUrl;
+    }
+
+    function handleMessage(msg) {
+      if (msg.data.command == 'log') {
+        console.log(msg.data.message);
+      } else if (msg.data.command == 'error') {
+        console.error(msg.data.message);
+      } else if (msg.data.command == 'data') {
+        writer.writeData(msg.data.buffer);
+        $('length').textContent = ' Size: ' + writer.getSize() + ' bytes';
+      } else if (msg.data.command == 'format') {
+        writer.writeHeader(msg.data);
+        $('length').textContent = ' Size: ' + writer.getSize() + ' bytes';
+      } else if (msg.data.command == 'supportedProfiles') {
+        profiles = [];
+        var profileList = $('profileList');
+        while (profileList.lastChild)
+          profileList.remove(profileList.lastChild);
+
+        var item = document.createElement('option');
+        item.label = 'wav';
+        profiles.push({ name: 'wav',
+                        sample_rate: 0,
+                        sample_size: 0,
+                        sample_per_frame:
+                        msg.data.profiles[0].sample_per_frame });
+        profileList.appendChild(item);
+        for (var i = 0; i < msg.data.profiles.length; i++) {
+          var item = document.createElement('option');
+          item.label = msg.data.profiles[i].name + ' - ' +
+            msg.data.profiles[i].sample_rate + 'Hz';
+          profiles.push(msg.data.profiles[i]);
+          profileList.appendChild(item);
+        }
+      }
+    }
+
+    function resetData() {
+      writer = new WavWriter();
+      $('length').textContent = ' Size: ' + writer.getSize() + ' bytes';
+    }
+
+    function initialize() {
+      plugin = $('plugin');
+      plugin.addEventListener('message', handleMessage, false);
+
+      $('start').addEventListener('click', function (e) {
+        resetData();
+        startRecord();
+      });
+      $('stop').addEventListener('click', function (e) {
+        stopRecord();
+      });
+    }
+
+    document.addEventListener('DOMContentLoaded', initialize, false);
+  </script>
+</head>
+
+<body>
+  <h1>Pepper Audio Encoder API Example</h1><br>
+  This example demonstrates receiving frames from an audio MediaStreamTrack and
+  encoding them using AudioEncode.<br>
+
+  <select id="profileList"></select>
+  <input type="button" id="start" value="Start Recording"/>
+  <input type="button" id="stop" value="Stop Recording"/>
+  <div id="download-box"></div>
+  <div id="length"></div>
+  <br>
+  <embed id="plugin" type="application/x-ppapi-example-audio-encode"/>
+</body>
+</html>
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index e0c21fb..a6f90c9 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -351,6 +351,16 @@
       ],
     },
     {
+      'target_name': 'ppapi_example_audio_encode',
+      'dependencies': [
+        'ppapi_example_skeleton',
+        'ppapi.gyp:ppapi_cpp',
+      ],
+      'sources': [
+        'examples/audio_encode/audio_encode.cc',
+      ],
+    },
+    {
       # GN version: //ppapi/examples/audio_input
       'target_name': 'ppapi_example_audio_input',
       'dependencies': [
diff --git a/remoting/host/cast_extension_session.cc b/remoting/host/cast_extension_session.cc
index 1b8df91..9e4b12d 100644
--- a/remoting/host/cast_extension_session.cc
+++ b/remoting/host/cast_extension_session.cc
@@ -12,7 +12,7 @@
 #include "net/url_request/url_request_context_getter.h"
 #include "remoting/host/client_session.h"
 #include "remoting/proto/control.pb.h"
-#include "remoting/protocol/chromium_port_allocator_factory.h"
+#include "remoting/protocol/chromium_port_allocator.h"
 #include "remoting/protocol/client_stub.h"
 #include "remoting/protocol/webrtc_video_capturer_adapter.h"
 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
@@ -50,8 +50,9 @@
 const char kStreamLabel[] = "stream_label";
 
 // Default STUN server used to construct
-// webrtc::PeerConnectionInterface::RTCConfiguration for the PeerConnection.
-const char kDefaultStunURI[] = "stun:stun.l.google.com:19302";
+// ChromiumPortAllocator for the PeerConnection.
+const char kDefaultStunHost[] = "stun.l.google.com";
+const int kDefaultStunPort = 19302;
 
 const char kWorkerThreadName[] = "CastExtensionSessionWorkerThread";
 
@@ -481,13 +482,6 @@
 
   VLOG(1) << "Created PeerConnectionFactory successfully.";
 
-  webrtc::PeerConnectionInterface::IceServers servers;
-  webrtc::PeerConnectionInterface::IceServer server;
-  server.uri = kDefaultStunURI;
-  servers.push_back(server);
-  webrtc::PeerConnectionInterface::RTCConfiguration rtc_config;
-  rtc_config.servers = servers;
-
   // DTLS-SRTP is the preferred encryption method. If set to kValueFalse, the
   // peer connection uses SDES. Disabling SDES as well will cause the peer
   // connection to fail to connect.
@@ -497,12 +491,17 @@
   constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
                            webrtc::MediaConstraintsInterface::kValueTrue);
 
-  rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-      port_allocator_factory = protocol::ChromiumPortAllocatorFactory::Create(
-          network_settings_, url_request_context_getter_);
+  rtc::scoped_ptr<protocol::ChromiumPortAllocator> port_allocator(
+      protocol::ChromiumPortAllocator::Create(url_request_context_getter_,
+                                              network_settings_)
+          .release());
+  std::vector<rtc::SocketAddress> stun_hosts;
+  stun_hosts.push_back(rtc::SocketAddress(kDefaultStunHost, kDefaultStunPort));
+  port_allocator->SetStunHosts(stun_hosts);
 
+  webrtc::PeerConnectionInterface::RTCConfiguration rtc_config;
   peer_connection_ = peer_conn_factory_->CreatePeerConnection(
-      rtc_config, &constraints, port_allocator_factory, nullptr, this);
+      rtc_config, &constraints, port_allocator.Pass(), nullptr, this);
 
   if (!peer_connection_.get()) {
     CleanupPeerConnection();
diff --git a/remoting/host/cast_extension_session.h b/remoting/host/cast_extension_session.h
index 3c0fe4b4..f71d893 100644
--- a/remoting/host/cast_extension_session.h
+++ b/remoting/host/cast_extension_session.h
@@ -198,7 +198,7 @@
   rtc::scoped_refptr<CastCreateSessionDescriptionObserver>
       create_session_desc_observer_;
 
-  // Parameters passed to ChromiumPortAllocatorFactory on creation.
+  // Parameters passed to ChromiumPortAllocator on creation.
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
   const protocol::NetworkSettings& network_settings_;
 
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index 6aa39d4..124c76818 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -1501,8 +1501,8 @@
 #if !defined(NDEBUG)
     network_settings.flags = protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING;
 
-    rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-        port_allocator_factory = protocol::ChromiumPortAllocatorFactory::Create(
+    scoped_ptr<protocol::PortAllocatorFactory> port_allocator_factory =
+        protocol::ChromiumPortAllocatorFactory::Create(
             network_settings, context_->url_request_context_getter());
 
     jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
@@ -1514,7 +1514,8 @@
     scoped_ptr<protocol::TransportFactory> transport_factory(
         new protocol::WebrtcTransportFactory(
             jingle_glue::JingleThreadWrapper::current(), signal_strategy_.get(),
-            port_allocator_factory, protocol::TransportRole::SERVER));
+            std::move(port_allocator_factory),
+            protocol::TransportRole::SERVER));
 
     session_manager.reset(
         new protocol::JingleSessionManager(transport_factory.Pass()));
diff --git a/remoting/protocol/chromium_port_allocator.h b/remoting/protocol/chromium_port_allocator.h
index a2b759c..021000e 100644
--- a/remoting/protocol/chromium_port_allocator.h
+++ b/remoting/protocol/chromium_port_allocator.h
@@ -9,12 +9,9 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "net/url_request/url_request_context_getter.h"
 #include "third_party/webrtc/p2p/client/httpportallocator.h"
 
-namespace net {
-class URLRequestContextGetter;
-}  // namespace net
-
 namespace remoting {
 namespace protocol {
 
diff --git a/remoting/protocol/chromium_port_allocator_factory.cc b/remoting/protocol/chromium_port_allocator_factory.cc
index b262611..32c980b 100644
--- a/remoting/protocol/chromium_port_allocator_factory.cc
+++ b/remoting/protocol/chromium_port_allocator_factory.cc
@@ -20,33 +20,17 @@
 
 ChromiumPortAllocatorFactory::~ChromiumPortAllocatorFactory() {}
 
-rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-ChromiumPortAllocatorFactory::Create(
+scoped_ptr<PortAllocatorFactory> ChromiumPortAllocatorFactory::Create(
     const NetworkSettings& network_settings,
     scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
-  rtc::RefCountedObject<ChromiumPortAllocatorFactory>* allocator_factory =
-      new rtc::RefCountedObject<ChromiumPortAllocatorFactory>(
-          network_settings, url_request_context_getter);
-  return allocator_factory;
+  return scoped_ptr<PortAllocatorFactory>(new ChromiumPortAllocatorFactory(
+      network_settings, url_request_context_getter));
 }
 
-cricket::PortAllocator* ChromiumPortAllocatorFactory::CreatePortAllocator(
-    const std::vector<StunConfiguration>& stun_servers,
-    const std::vector<TurnConfiguration>& turn_configurations) {
+cricket::PortAllocator* ChromiumPortAllocatorFactory::CreatePortAllocator() {
   scoped_ptr<ChromiumPortAllocator> port_allocator(
       ChromiumPortAllocator::Create(url_request_context_getter_,
                                     network_settings_));
-
-  std::vector<rtc::SocketAddress> stun_hosts;
-  for (auto stun_it = stun_servers.begin(); stun_it != stun_servers.end();
-       ++stun_it) {
-    stun_hosts.push_back(stun_it->server);
-  }
-  port_allocator->SetStunHosts(stun_hosts);
-
-  // TODO(aiguha): Figure out how to translate |turn_configurations| into
-  // turn hosts so we can set |port_allocator|'s relay hosts.
-
   return port_allocator.release();
 }
 
diff --git a/remoting/protocol/chromium_port_allocator_factory.h b/remoting/protocol/chromium_port_allocator_factory.h
index bbfa1b7..4c7db57 100644
--- a/remoting/protocol/chromium_port_allocator_factory.h
+++ b/remoting/protocol/chromium_port_allocator_factory.h
@@ -7,8 +7,9 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "remoting/protocol/network_settings.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "remoting/protocol/port_allocator_factory.h"
 
 namespace net {
 class URLRequestContextGetter;
@@ -17,17 +18,14 @@
 namespace remoting {
 namespace protocol {
 
-class ChromiumPortAllocatorFactory
-    : public webrtc::PortAllocatorFactoryInterface {
+class ChromiumPortAllocatorFactory : public PortAllocatorFactory {
  public:
-  static rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface> Create(
+  static scoped_ptr<PortAllocatorFactory> Create(
       const NetworkSettings& network_settings,
       scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
 
-  // webrtc::PortAllocatorFactoryInterface implementation.
-  cricket::PortAllocator* CreatePortAllocator(
-      const std::vector<StunConfiguration>& stun_servers,
-      const std::vector<TurnConfiguration>& turn_configurations) override;
+  // PortAllocatorFactory implementation.
+  cricket::PortAllocator* CreatePortAllocator() override;
 
  protected:
   ChromiumPortAllocatorFactory(
diff --git a/remoting/protocol/port_allocator_factory.h b/remoting/protocol/port_allocator_factory.h
new file mode 100644
index 0000000..741ccca
--- /dev/null
+++ b/remoting/protocol/port_allocator_factory.h
@@ -0,0 +1,25 @@
+// Copyright 2015 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_PROTOCOL_PORT_ALLOCATOR_FACTORY_H_
+#define REMOTING_PROTOCOL_PORT_ALLOCATOR_FACTORY_H_
+
+#include "third_party/webrtc/p2p/base/portallocator.h"
+
+namespace remoting {
+namespace protocol {
+
+// Factory class used for creating cricket::PortAllocator that is used
+// for ICE negotiation.
+class PortAllocatorFactory {
+ public:
+  virtual cricket::PortAllocator* CreatePortAllocator() = 0;
+
+  virtual ~PortAllocatorFactory() {}
+};
+
+}  // namespace protocol
+}  // namespace remoting
+
+#endif  // REMOTING_PROTOCOL_PORT_ALLOCATOR_FACTORY_H_
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc
index 253293eb..2c82aab 100644
--- a/remoting/protocol/webrtc_transport.cc
+++ b/remoting/protocol/webrtc_transport.cc
@@ -99,11 +99,9 @@
 
 }  // namespace
 
-WebrtcTransport::WebrtcTransport(
-    rtc::Thread* worker_thread,
-    rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-        port_allocator_factory,
-    TransportRole role)
+WebrtcTransport::WebrtcTransport(rtc::Thread* worker_thread,
+                                 PortAllocatorFactory* port_allocator_factory,
+                                 TransportRole role)
     : port_allocator_factory_(port_allocator_factory),
       role_(role),
       worker_thread_(worker_thread),
@@ -138,8 +136,11 @@
   constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
                            webrtc::MediaConstraintsInterface::kValueTrue);
 
+  rtc::scoped_ptr<cricket::PortAllocator> port_allocator(
+      port_allocator_factory_->CreatePortAllocator());
+
   peer_connection_ = peer_connection_factory_->CreatePeerConnection(
-      rtc_config, &constraints, port_allocator_factory_, nullptr, this);
+      rtc_config, &constraints, std::move(port_allocator), nullptr, this);
 
   data_stream_adapter_.Initialize(peer_connection_,
                                   role_ == TransportRole::SERVER);
@@ -488,19 +489,18 @@
 WebrtcTransportFactory::WebrtcTransportFactory(
     rtc::Thread* worker_thread,
     SignalStrategy* signal_strategy,
-    rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-        port_allocator_factory,
+    scoped_ptr<PortAllocatorFactory> port_allocator_factory,
     TransportRole role)
     : worker_thread_(worker_thread),
       signal_strategy_(signal_strategy),
-      port_allocator_factory_(port_allocator_factory),
+      port_allocator_factory_(std::move(port_allocator_factory)),
       role_(role) {}
 
 WebrtcTransportFactory::~WebrtcTransportFactory() {}
 
 scoped_ptr<Transport> WebrtcTransportFactory::CreateTransport() {
-  return make_scoped_ptr(
-      new WebrtcTransport(worker_thread_, port_allocator_factory_, role_));
+  return make_scoped_ptr(new WebrtcTransport(
+      worker_thread_, port_allocator_factory_.get(), role_));
 }
 
 }  // namespace protocol
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h
index afba35e..6fc79d72 100644
--- a/remoting/protocol/webrtc_transport.h
+++ b/remoting/protocol/webrtc_transport.h
@@ -6,11 +6,13 @@
 #define REMOTING_PROTOCOL_WEBRTC_TRANSPORT_H_
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "base/timer/timer.h"
+#include "remoting/protocol/port_allocator_factory.h"
 #include "remoting/protocol/transport.h"
 #include "remoting/protocol/webrtc_data_stream_adapter.h"
 #include "remoting/signaling/signal_strategy.h"
@@ -27,8 +29,7 @@
                         public webrtc::PeerConnectionObserver {
  public:
   WebrtcTransport(rtc::Thread* worker_thread,
-                  rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-                      port_allocator_factory,
+                  PortAllocatorFactory* port_allocator_factory,
                   TransportRole role);
   ~WebrtcTransport() override;
 
@@ -79,8 +80,7 @@
 
   base::ThreadChecker thread_checker_;
 
-  rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-      port_allocator_factory_;
+  PortAllocatorFactory* port_allocator_factory_;
   TransportRole role_;
   EventHandler* event_handler_ = nullptr;
   rtc::Thread* worker_thread_;
@@ -113,8 +113,7 @@
   WebrtcTransportFactory(
       rtc::Thread* worker_thread,
       SignalStrategy* signal_strategy,
-      rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-          port_allocator_factory,
+      scoped_ptr<PortAllocatorFactory> port_allocator_factory,
       TransportRole role);
   ~WebrtcTransportFactory() override;
 
@@ -124,8 +123,7 @@
  private:
   rtc::Thread* worker_thread_;
   SignalStrategy* signal_strategy_;
-  rtc::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
-      port_allocator_factory_;
+  scoped_ptr<PortAllocatorFactory> port_allocator_factory_;
   TransportRole role_;
 
   DISALLOW_COPY_AND_ASSIGN(WebrtcTransportFactory);
diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi
index cbd416fb..b5e2153 100644
--- a/remoting/remoting_srcs.gypi
+++ b/remoting/remoting_srcs.gypi
@@ -210,6 +210,7 @@
       'protocol/chromium_socket_factory.h',
       'protocol/ice_connection_to_client.cc',
       'protocol/ice_connection_to_client.h',
+      'protocol/port_allocator_factory.h',
       'protocol/video_frame_pump.cc',
       'protocol/video_frame_pump.h',
       'protocol/webrtc_connection_to_client.cc',
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 796f4e7..da86234 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -245,10 +245,6 @@
  */
 #define SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
 
-/* Disable tight bounds for saveLayer offscreens in Skia until rebaselining is done.
- */
-#define SK_SUPPORT_SRC_BOUNDS_BLOAT_FOR_IMAGEFILTERS
-
 /* This flag forces Skia not to use typographic metrics with GDI.
  */
 #define SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
diff --git a/sync/android/model_type_helper.cc b/sync/android/model_type_helper.cc
index 64d808f..304d9e7 100644
--- a/sync/android/model_type_helper.cc
+++ b/sync/android/model_type_helper.cc
@@ -4,6 +4,8 @@
 
 #include "sync/android/model_type_helper.h"
 
+#include <string>
+
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "jni/ModelTypeHelper_jni.h"
diff --git a/sync/android/model_type_helper.h b/sync/android/model_type_helper.h
index dc3d6bf..d389d08d 100644
--- a/sync/android/model_type_helper.h
+++ b/sync/android/model_type_helper.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 SYNC_MODEL_TYPE_HELPER_H_
-#define SYNC_MODEL_TYPE_HELPER_H_
+#ifndef SYNC_ANDROID_MODEL_TYPE_HELPER_H_
+#define SYNC_ANDROID_MODEL_TYPE_HELPER_H_
 
 #include <jni.h>
 
@@ -13,4 +13,4 @@
 
 }
 
-#endif  // SYNC_MODEL_TYPE_HELPER_H_
+#endif  // SYNC_ANDROID_MODEL_TYPE_HELPER_H_
diff --git a/sync/android/sync_jni_registrar.h b/sync/android/sync_jni_registrar.h
index 5a13680..548407f 100644
--- a/sync/android/sync_jni_registrar.h
+++ b/sync/android/sync_jni_registrar.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 SYNC_JNI_REGISTRAR_H_
-#define SYNC_JNI_REGISTRAR_H_
+#ifndef SYNC_ANDROID_SYNC_JNI_REGISTRAR_H_
+#define SYNC_ANDROID_SYNC_JNI_REGISTRAR_H_
 
 #include <jni.h>
 
@@ -15,4 +15,4 @@
 
 }
 
-#endif  // SYNC_JNI_REGISTRAR_H_
+#endif  // SYNC_ANDROID_SYNC_JNI_REGISTRAR_H_
diff --git a/sync/api/attachments/attachment_id.h b/sync/api/attachments/attachment_id.h
index 039d38684..835011a 100644
--- a/sync/api/attachments/attachment_id.h
+++ b/sync/api/attachments/attachment_id.h
@@ -72,7 +72,7 @@
 
   ImmutableAttachmentIdProto proto_;
 
-  AttachmentId(sync_pb::AttachmentIdProto* proto);
+  explicit AttachmentId(sync_pb::AttachmentIdProto* proto);
 };
 
 // All public interfaces use AttachmentIdList. AttachmentIdSet is used in
diff --git a/sync/api/entity_change.cc b/sync/api/entity_change.cc
index e2f2bedb9..81020de 100644
--- a/sync/api/entity_change.cc
+++ b/sync/api/entity_change.cc
@@ -26,7 +26,7 @@
 EntityChange::EntityChange(std::string client_key,
                            ChangeType type,
                            EntityDataPtr data)
-    : client_key_(client_key), type_(type), data_(data){};
+    : client_key_(client_key), type_(type), data_(data) {}
 
 EntityChange::~EntityChange() {}
 
diff --git a/sync/api/entity_data.cc b/sync/api/entity_data.cc
index 0914022..35e5e74 100644
--- a/sync/api/entity_data.cc
+++ b/sync/api/entity_data.cc
@@ -4,6 +4,8 @@
 
 #include "sync/api/entity_data.h"
 
+#include <algorithm>
+
 #include "base/logging.h"
 
 namespace syncer_v2 {
diff --git a/sync/api/fake_sync_change_processor.cc b/sync/api/fake_sync_change_processor.cc
index 2721650..b9adf88 100644
--- a/sync/api/fake_sync_change_processor.cc
+++ b/sync/api/fake_sync_change_processor.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "sync/api/fake_sync_change_processor.h"
+
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_data.h"
 
diff --git a/sync/api/fake_sync_change_processor.h b/sync/api/fake_sync_change_processor.h
index d9bd5964..7271edf 100644
--- a/sync/api/fake_sync_change_processor.h
+++ b/sync/api/fake_sync_change_processor.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_API_FAKE_SYNC_CHANGE_PROCESSOR_H_
 #define SYNC_API_FAKE_SYNC_CHANGE_PROCESSOR_H_
 
+#include <string>
+
 #include "sync/api/sync_change_processor.h"
 
 namespace syncer {
diff --git a/sync/api/sync_change_processor.h b/sync/api/sync_change_processor.h
index b70ef3df..e815d3e1 100644
--- a/sync/api/sync_change_processor.h
+++ b/sync/api/sync_change_processor.h
@@ -5,6 +5,7 @@
 #ifndef SYNC_API_SYNC_CHANGE_PROCESSOR_H_
 #define SYNC_API_SYNC_CHANGE_PROCESSOR_H_
 
+#include <string>
 #include <vector>
 
 #include "sync/api/sync_data.h"
@@ -59,7 +60,7 @@
   //
   // Refer to sync_data.h for a description of |sync_tag|.
   //
-  // TODO:(maniscalco): N.B. this method should really be pure virtual. An
+  // TODO(maniscalco): N.B. this method should really be pure virtual. An
   // implentation is provided here just to verify that everything compiles.
   // Update this method to be pure virtual (bug 353300).
   virtual void GetSyncData(const ModelType& type,
diff --git a/sync/api/sync_data.cc b/sync/api/sync_data.cc
index d6c9152..17b54dc7c 100644
--- a/sync/api/sync_data.cc
+++ b/sync/api/sync_data.cc
@@ -4,6 +4,7 @@
 
 #include "sync/api/sync_data.h"
 
+#include <algorithm>
 #include <ostream>
 
 #include "base/json/json_writer.h"
diff --git a/sync/api/sync_data_unittest.cc b/sync/api/sync_data_unittest.cc
index 9d45149..9d676c09 100644
--- a/sync/api/sync_data_unittest.cc
+++ b/sync/api/sync_data_unittest.cc
@@ -23,9 +23,9 @@
 
 namespace {
 
-const string kSyncTag = "3984729834";
+const char kSyncTag[] = "3984729834";
 const ModelType kDatatype = syncer::PREFERENCES;
-const string kNonUniqueTitle = "my preference";
+const char kNonUniqueTitle[] = "my preference";
 const int64 kId = 439829;
 const base::Time kLastModifiedTime = base::Time();
 
diff --git a/sync/api/sync_error.h b/sync/api/sync_error.h
index 281621e5..d2832a51 100644
--- a/sync/api/sync_error.h
+++ b/sync/api/sync_error.h
@@ -27,21 +27,23 @@
   // in the datatype being disabled) from actionable sync errors (which might
   // have more complicated results).
   enum ErrorType {
-    UNSET,                // No error.
-    UNRECOVERABLE_ERROR,  // An unrecoverable runtime error was encountered, and
-                          // sync should be disabled and purged completely.
-    DATATYPE_ERROR,       // A datatype error was encountered, and the datatype
-                          // should be disabled and purged completely. Note that
-                          // datatype errors may be reset, triggering a
-                          // re-enable.
-    PERSISTENCE_ERROR,    // A persistence error was detected, and the
-                          // datataype should be associated after a sync update.
-    CRYPTO_ERROR,         // A cryptographer error was detected, and the
-                          // datatype should be associated after it is resolved.
-    UNREADY_ERROR,        // A datatype is not ready to start yet, so should be
-                          // neither purged nor enabled until it is ready.
-    DATATYPE_POLICY_ERROR // A datatype should be disabled and purged due
-                          // to configuration constraints.
+    UNSET,                 // No error.
+    UNRECOVERABLE_ERROR,   // An unrecoverable runtime error was encountered,
+                           // and sync should be disabled and purged completely.
+    DATATYPE_ERROR,        // A datatype error was encountered, and the datatype
+                           // should be disabled and purged completely. Note
+                           // that datatype errors may be reset, triggering a
+                           // re-enable.
+    PERSISTENCE_ERROR,     // A persistence error was detected, and the
+                           // datataype should be associated after a sync
+                           // update.
+    CRYPTO_ERROR,          // A cryptographer error was detected, and the
+                           // datatype should be associated after it is
+                           // resolved.
+    UNREADY_ERROR,         // A datatype is not ready to start yet, so should be
+                           // neither purged nor enabled until it is ready.
+    DATATYPE_POLICY_ERROR  // A datatype should be disabled and purged due to
+                           // configuration constraints.
   };
 
   // Severity is used to indicate how an error should be logged and
@@ -93,6 +95,7 @@
 
   // Returns empty string is IsSet() is false.
   std::string ToString() const;
+
  private:
   // Print error information to log.
   void PrintLogError() const;
diff --git a/sync/api/sync_error_factory_mock.h b/sync/api/sync_error_factory_mock.h
index bd675ee2..cffab26 100644
--- a/sync/api/sync_error_factory_mock.h
+++ b/sync/api/sync_error_factory_mock.h
@@ -5,8 +5,9 @@
 #ifndef SYNC_API_SYNC_ERROR_FACTORY_MOCK_H_
 #define SYNC_API_SYNC_ERROR_FACTORY_MOCK_H_
 
-#include "sync/api/sync_error_factory.h"
+#include <string>
 
+#include "sync/api/sync_error_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace syncer {
diff --git a/sync/engine/all_status.cc b/sync/engine/all_status.cc
index 36fb23ef..10b54e0 100644
--- a/sync/engine/all_status.cc
+++ b/sync/engine/all_status.cc
@@ -164,7 +164,7 @@
 
 void AllStatus::IncrementNudgeCounter(NudgeSource source) {
   ScopedStatusLock lock(this);
-  switch(source) {
+  switch (source) {
     case NUDGE_SOURCE_LOCAL_REFRESH:
       status_.nudge_source_local_refresh++;
       return;
diff --git a/sync/engine/all_status.h b/sync/engine/all_status.h
index 6eadc6d..95d9545 100644
--- a/sync/engine/all_status.h
+++ b/sync/engine/all_status.h
@@ -5,8 +5,8 @@
 // The AllStatus object watches various sync engine components and aggregates
 // the status of all of them into one place.
 
-#ifndef SYNC_INTERNAL_API_ALL_STATUS_H_
-#define SYNC_INTERNAL_API_ALL_STATUS_H_
+#ifndef SYNC_ENGINE_ALL_STATUS_H_
+#define SYNC_ENGINE_ALL_STATUS_H_
 
 #include <map>
 #include <string>
@@ -35,7 +35,6 @@
 // we will continue to collect data and update state mid-sync-cycle in case we
 // need to debug slow or stuck sync cycles.
 class AllStatus : public SyncEngineEventListener {
-  friend class ScopedStatusLock;
  public:
   AllStatus();
   ~AllStatus() override;
@@ -77,6 +76,10 @@
   SyncStatus status_;
 
   mutable base::Lock mutex_;  // Protects all data members.
+
+ private:
+  friend class ScopedStatusLock;
+
   DISALLOW_COPY_AND_ASSIGN(AllStatus);
 };
 
@@ -90,4 +93,4 @@
 
 }  // namespace syncer
 
-#endif  // SYNC_INTERNAL_API_ALL_STATUS_H_
+#endif  // SYNC_ENGINE_ALL_STATUS_H_
diff --git a/sync/engine/apply_control_data_updates.cc b/sync/engine/apply_control_data_updates.cc
index 49825b83..ce6c6c5 100644
--- a/sync/engine/apply_control_data_updates.cc
+++ b/sync/engine/apply_control_data_updates.cc
@@ -4,6 +4,8 @@
 
 #include "sync/engine/apply_control_data_updates.h"
 
+#include <vector>
+
 #include "base/metrics/histogram.h"
 #include "sync/engine/conflict_resolver.h"
 #include "sync/engine/conflict_util.h"
diff --git a/sync/engine/apply_control_data_updates_unittest.cc b/sync/engine/apply_control_data_updates_unittest.cc
index c01e5a71..405ae0e7 100644
--- a/sync/engine/apply_control_data_updates_unittest.cc
+++ b/sync/engine/apply_control_data_updates_unittest.cc
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "sync/engine/apply_control_data_updates.h"
+
+#include <string>
+
 #include "base/format_macros.h"
 #include "base/location.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
-#include "sync/engine/apply_control_data_updates.h"
 #include "sync/engine/syncer.h"
 #include "sync/engine/syncer_util.h"
 #include "sync/internal_api/public/test/test_entry_factory.h"
diff --git a/sync/engine/backoff_delay_provider.cc b/sync/engine/backoff_delay_provider.cc
index bff3fd6..ddd90ed8 100644
--- a/sync/engine/backoff_delay_provider.cc
+++ b/sync/engine/backoff_delay_provider.cc
@@ -4,6 +4,8 @@
 
 #include "sync/engine/backoff_delay_provider.h"
 
+#include <algorithm>
+
 #include "base/rand_util.h"
 #include "sync/internal_api/public/engine/polling_constants.h"
 #include "sync/internal_api/public/sessions/model_neutral_state.h"
diff --git a/sync/engine/commit_queue.cc b/sync/engine/commit_queue.cc
index 1a0e58bb..dbe4c0a 100644
--- a/sync/engine/commit_queue.cc
+++ b/sync/engine/commit_queue.cc
@@ -12,4 +12,4 @@
 CommitQueue::~CommitQueue() {
 }
 
-}  // namespace syncer
+}  // namespace syncer_v2
diff --git a/sync/engine/conflict_resolver.h b/sync/engine/conflict_resolver.h
index 5838623..3266afb 100644
--- a/sync/engine/conflict_resolver.h
+++ b/sync/engine/conflict_resolver.h
@@ -29,9 +29,6 @@
 }  // namespace sessions
 
 class ConflictResolver {
-  friend class SyncerTest;
-  FRIEND_TEST_ALL_PREFIXES(SyncerTest,
-                           ConflictResolverMergeOverwritesLocalEntry);
  public:
   // Enumeration of different conflict resolutions. Used for histogramming.
   enum SimpleConflictResolutions {
@@ -57,6 +54,10 @@
                         UpdateCounters* counters);
 
  private:
+  friend class SyncerTest;
+  FRIEND_TEST_ALL_PREFIXES(SyncerTest,
+                           ConflictResolverMergeOverwritesLocalEntry);
+
   void ProcessSimpleConflict(
       syncable::WriteTransaction* trans,
       const syncable::Id& id,
diff --git a/sync/engine/directory_commit_contribution.cc b/sync/engine/directory_commit_contribution.cc
index 568d621..a65e3da3 100644
--- a/sync/engine/directory_commit_contribution.cc
+++ b/sync/engine/directory_commit_contribution.cc
@@ -4,6 +4,9 @@
 
 #include "sync/engine/directory_commit_contribution.h"
 
+#include <algorithm>
+#include <set>
+
 #include "sync/engine/commit_util.h"
 #include "sync/engine/get_commit_ids.h"
 #include "sync/engine/syncer_util.h"
diff --git a/sync/engine/directory_commit_contribution_unittest.cc b/sync/engine/directory_commit_contribution_unittest.cc
index ce0fa75..3789bee3 100644
--- a/sync/engine/directory_commit_contribution_unittest.cc
+++ b/sync/engine/directory_commit_contribution_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "sync/engine/directory_commit_contribution.h"
 
+#include <set>
+#include <string>
+
 #include "base/message_loop/message_loop.h"
 #include "sync/internal_api/public/base/attachment_id_proto.h"
 #include "sync/sessions/status_controller.h"
@@ -291,7 +294,6 @@
 
 // Test that bookmarks support hierarchy.
 TEST_F(DirectoryCommitContributionTest, HierarchySupport_Bookmark) {
-
   // Create a normal-looking bookmark item.
   int64 bm1;
   {
diff --git a/sync/engine/directory_commit_contributor.h b/sync/engine/directory_commit_contributor.h
index 62251f7c..430bcaf 100644
--- a/sync/engine/directory_commit_contributor.h
+++ b/sync/engine/directory_commit_contributor.h
@@ -45,6 +45,6 @@
   DISALLOW_COPY_AND_ASSIGN(DirectoryCommitContributor);
 };
 
-}  // namespace
+}  // namespace syncer
 
 #endif  // SYNC_ENGINE_DIRECTORY_COMMIT_CONTRIBUTOR_H_
diff --git a/sync/engine/directory_update_handler.cc b/sync/engine/directory_update_handler.cc
index 8adc6dd..60b08c53 100644
--- a/sync/engine/directory_update_handler.cc
+++ b/sync/engine/directory_update_handler.cc
@@ -4,6 +4,8 @@
 
 #include "sync/engine/directory_update_handler.h"
 
+#include <vector>
+
 #include "sync/engine/conflict_resolver.h"
 #include "sync/engine/process_updates_util.h"
 #include "sync/engine/update_applicator.h"
diff --git a/sync/engine/directory_update_handler_unittest.cc b/sync/engine/directory_update_handler_unittest.cc
index 6238eb0..3a29d1c9 100644
--- a/sync/engine/directory_update_handler_unittest.cc
+++ b/sync/engine/directory_update_handler_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "sync/engine/directory_update_handler.h"
 
+#include <set>
+#include <string>
 #include <utility>
 
 #include "base/compiler_specific.h"
@@ -533,7 +535,7 @@
   AddDefaultFieldValue(BOOKMARKS, &result);
   return result;
 }
-} // namespace
+}  // namespace
 
 // Test update application for a few bookmark items.
 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmark) {
diff --git a/sync/engine/entity_tracker_unittest.cc b/sync/engine/entity_tracker_unittest.cc
index 02dabf0d..5dd2d38 100644
--- a/sync/engine/entity_tracker_unittest.cc
+++ b/sync/engine/entity_tracker_unittest.cc
@@ -156,4 +156,4 @@
   EXPECT_TRUE(entity->HasPendingCommit());
 }
 
-}  // namespace syncer
+}  // namespace syncer_v2
diff --git a/sync/engine/get_commit_ids.cc b/sync/engine/get_commit_ids.cc
index 543dc1bf..5c4d1111 100644
--- a/sync/engine/get_commit_ids.cc
+++ b/sync/engine/get_commit_ids.cc
@@ -69,7 +69,7 @@
   if (cryptographer) {
     encrypted_types = dir->GetNigoriHandler()->GetEncryptedTypes(trans);
     passphrase_missing = cryptographer->has_pending_keys();
-  };
+  }
 
   // We filter out all unready entries from the set of unsynced handles. This
   // new set of ready and unsynced items is then what we use to determine what
diff --git a/sync/engine/get_updates_processor_unittest.cc b/sync/engine/get_updates_processor_unittest.cc
index 566a295c..c89b57d 100644
--- a/sync/engine/get_updates_processor_unittest.cc
+++ b/sync/engine/get_updates_processor_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "sync/engine/get_updates_processor.h"
 
+#include <string>
+
 #include "base/message_loop/message_loop.h"
 #include "base/stl_util.h"
 #include "sync/engine/get_updates_delegate.h"
diff --git a/sync/engine/model_type_worker.cc b/sync/engine/model_type_worker.cc
index afcf0f4b..991ee82 100644
--- a/sync/engine/model_type_worker.cc
+++ b/sync/engine/model_type_worker.cc
@@ -5,6 +5,7 @@
 #include "sync/engine/model_type_worker.h"
 
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/format_macros.h"
@@ -461,4 +462,4 @@
   return true;
 }
 
-}  // namespace syncer
+}  // namespace syncer_v2
diff --git a/sync/engine/model_type_worker.h b/sync/engine/model_type_worker.h
index 130c1d3..a6a1ae8 100644
--- a/sync/engine/model_type_worker.h
+++ b/sync/engine/model_type_worker.h
@@ -5,6 +5,9 @@
 #ifndef SYNC_ENGINE_MODEL_TYPE_WORKER_H_
 #define SYNC_ENGINE_MODEL_TYPE_WORKER_H_
 
+#include <map>
+#include <string>
+
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
@@ -164,6 +167,6 @@
   base::WeakPtrFactory<ModelTypeWorker> weak_ptr_factory_;
 };
 
-}  // namespace syncer
+}  // namespace syncer_v2
 
 #endif  // SYNC_ENGINE_MODEL_TYPE_WORKER_H_
diff --git a/sync/engine/model_type_worker_unittest.cc b/sync/engine/model_type_worker_unittest.cc
index 06fc15c9..b0f7484 100644
--- a/sync/engine/model_type_worker_unittest.cc
+++ b/sync/engine/model_type_worker_unittest.cc
@@ -1140,4 +1140,4 @@
   EXPECT_TRUE(HasUpdateResponseOnModelThread("tag1"));
 }
 
-}  // namespace syncer
+}  // namespace syncer_v2
diff --git a/sync/engine/net/url_translator.cc b/sync/engine/net/url_translator.cc
index 285053a..dd0b57ef 100644
--- a/sync/engine/net/url_translator.cc
+++ b/sync/engine/net/url_translator.cc
@@ -24,7 +24,7 @@
 #else
 const char kClientName[] = "Chromium";
 #endif  // defined(GOOGLE_CHROME_BUILD)
-}
+}  // namespace
 
 // Convenience wrappers around CgiEscapePath().
 string CgiEscapeString(const char* src) {
diff --git a/sync/engine/non_blocking_type_commit_contribution.cc b/sync/engine/non_blocking_type_commit_contribution.cc
index cdebda3..55b81e2 100644
--- a/sync/engine/non_blocking_type_commit_contribution.cc
+++ b/sync/engine/non_blocking_type_commit_contribution.cc
@@ -4,6 +4,8 @@
 
 #include "sync/engine/non_blocking_type_commit_contribution.h"
 
+#include <algorithm>
+
 #include "base/values.h"
 #include "sync/engine/model_type_worker.h"
 #include "sync/internal_api/public/non_blocking_sync_common.h"
@@ -116,4 +118,4 @@
   return sequence_numbers_.size();
 }
 
-}  // namespace syncer
+}  // namespace syncer_v2
diff --git a/sync/engine/non_blocking_type_commit_contribution.h b/sync/engine/non_blocking_type_commit_contribution.h
index 3247a2c2..41ee4de 100644
--- a/sync/engine/non_blocking_type_commit_contribution.h
+++ b/sync/engine/non_blocking_type_commit_contribution.h
@@ -61,6 +61,6 @@
   DISALLOW_COPY_AND_ASSIGN(NonBlockingTypeCommitContribution);
 };
 
-}  // namespace syncer
+}  // namespace syncer_v2
 
 #endif  // SYNC_ENGINE_NON_BLOCKING_TYPE_COMMIT_CONTRIBUTION_H_
diff --git a/sync/engine/nudge_source.cc b/sync/engine/nudge_source.cc
index 62a2409..5445e9d 100644
--- a/sync/engine/nudge_source.cc
+++ b/sync/engine/nudge_source.cc
@@ -16,7 +16,7 @@
     ENUM_CASE(NUDGE_SOURCE_NOTIFICATION);
     ENUM_CASE(NUDGE_SOURCE_LOCAL);
     ENUM_CASE(NUDGE_SOURCE_LOCAL_REFRESH);
-  };
+  }
   NOTREACHED();
   return "";
 }
diff --git a/sync/engine/process_updates_util.cc b/sync/engine/process_updates_util.cc
index e1931d7..1ad577a2 100644
--- a/sync/engine/process_updates_util.cc
+++ b/sync/engine/process_updates_util.cc
@@ -4,6 +4,8 @@
 
 #include "sync/engine/process_updates_util.h"
 
+#include <string>
+
 #include "base/location.h"
 #include "base/metrics/sparse_histogram.h"
 #include "sync/engine/syncer_proto_util.h"
@@ -49,7 +51,7 @@
 // For more information, see FindLocalIdToUpdate().
 bool UpdateContainsNewVersion(syncable::BaseTransaction *trans,
                               const sync_pb::SyncEntity &update) {
-  int64 existing_version = -1; // The server always sends positive versions.
+  int64 existing_version = -1;  // The server always sends positive versions.
   syncable::Entry existing_entry(trans, GET_BY_ID,
                                  SyncableIdFromProto(update.id_string()));
   if (existing_entry.good())
@@ -159,7 +161,6 @@
 bool ReverifyEntry(syncable::ModelNeutralWriteTransaction* trans,
                    const sync_pb::SyncEntity& entry,
                    syncable::ModelNeutralMutableEntry* same_id) {
-
   const bool deleted = entry.has_deleted() && entry.deleted();
   const bool is_directory = IsFolder(entry);
   const ModelType model_type = GetModelType(entry);
diff --git a/sync/engine/sync_scheduler_unittest.cc b/sync/engine/sync_scheduler_unittest.cc
index dbf6fda..ea07b4a 100644
--- a/sync/engine/sync_scheduler_unittest.cc
+++ b/sync/engine/sync_scheduler_unittest.cc
@@ -305,7 +305,7 @@
   SyncShareTimes times;
   ModelTypeSet model_types(THEMES);
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times, true)))
       .RetiresOnSaturation();
@@ -321,7 +321,7 @@
   SyncShareTimes times2;
   model_types.Remove(THEMES);
   model_types.Put(TYPED_URLS);
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times2, true)));
   scheduler()->ScheduleLocalNudge(model_types, FROM_HERE);
@@ -334,7 +334,7 @@
   SyncShareTimes times;
   const ModelTypeSet model_types(THEMES);
 
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess),
                       RecordSyncShare(&times, true)));
 
@@ -364,7 +364,7 @@
 
   StartSyncConfiguration();
 
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
                       RecordSyncShare(&times, false)))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
@@ -391,7 +391,7 @@
 
   Mock::VerifyAndClearExpectations(syncer());
 
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess),
                       RecordSyncShare(&times, true)));
   RunLoop();
@@ -412,7 +412,7 @@
 
   // Make ConfigureSyncShare call scheduler->Stop(). It is not supposed to call
   // retry_task or dereference configuration params.
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
                       StopScheduler(scheduler()),
                       RecordSyncShare(&times, false)));
@@ -443,7 +443,7 @@
   StartSyncConfiguration();
 
   // Request a configure and make sure it fails.
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
                       RecordSyncShare(&times, false)));
   CallbackCounter ready_counter;
@@ -461,7 +461,7 @@
   Mock::VerifyAndClearExpectations(syncer());
 
   // Ask for a nudge while dealing with repeated configure failure.
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
                       RecordSyncShare(&times, false)));
   scheduler()->ScheduleLocalNudge(model_types, FROM_HERE);
@@ -473,13 +473,13 @@
   ASSERT_EQ(0, ready_counter.times_called());
 
   // Let the next configure retry succeed.
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess),
                       RecordSyncShare(&times, true)));
   RunLoop();
 
   // Now change the mode so nudge can execute.
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times, true)));
   StartSyncScheduler(base::Time());
@@ -491,7 +491,7 @@
   StartSyncScheduler(base::Time());
 
   SyncShareTimes times;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times, true)));
   const ModelTypeSet types1(THEMES), types2(TYPED_URLS), types3(THEMES);
@@ -506,7 +506,7 @@
   Mock::VerifyAndClearExpectations(syncer());
 
   SyncShareTimes times2;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times2, true)));
   scheduler()->ScheduleLocalNudge(types3, FROM_HERE);
@@ -518,7 +518,7 @@
   StartSyncScheduler(base::Time());
 
   SyncShareTimes times;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times, true)));
   ModelTypeSet types1(THEMES), types2(TYPED_URLS), types3;
@@ -549,7 +549,7 @@
   StartSyncScheduler(base::Time());
 
   SyncShareTimes times1;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times1, true)))
       .RetiresOnSaturation();
@@ -561,7 +561,7 @@
 
   // Make sure a second, later, nudge is unaffected by first (no coalescing).
   SyncShareTimes times2;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times2, true)));
   scheduler()->ScheduleInvalidationNudge(
@@ -573,7 +573,8 @@
 TEST_F(SyncSchedulerTest, Polling) {
   SyncShareTimes times;
   TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+      .Times(AtLeast(kMinNumSamples))
       .WillRepeatedly(
           DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
                 RecordSyncShareMultiple(&times, kMinNumSamples, true)));
@@ -598,7 +599,8 @@
   // Use a large poll interval that wouldn't normally get hit on its own for
   // some time yet.
   TimeDelta poll_interval(TimeDelta::FromMilliseconds(500));
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+      .Times(AtLeast(kMinNumSamples))
       .WillRepeatedly(
           DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
                 RecordSyncShareMultiple(&times, kMinNumSamples, true)));
@@ -621,7 +623,8 @@
 TEST_F(SyncSchedulerTest, PollingPersistenceBadClock) {
   SyncShareTimes times;
   TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+      .Times(AtLeast(kMinNumSamples))
       .WillRepeatedly(
           DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
                 RecordSyncShareMultiple(&times, kMinNumSamples, true)));
@@ -643,7 +646,8 @@
 TEST_F(SyncSchedulerTest, PollNotificationsDisabled) {
   SyncShareTimes times;
   TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+      .Times(AtLeast(kMinNumSamples))
       .WillRepeatedly(
           DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
                 RecordSyncShareMultiple(&times, kMinNumSamples, true)));
@@ -667,15 +671,15 @@
   TimeDelta poll1(TimeDelta::FromMilliseconds(120));
   TimeDelta poll2(TimeDelta::FromMilliseconds(30));
   scheduler()->OnReceivedLongPollIntervalUpdate(poll1);
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples))
-      .WillOnce(DoAll(
-          WithArgs<0,1>(
-              sessions::test_util::SimulatePollIntervalUpdate(poll2)),
-          Return(true)))
-      .WillRepeatedly(
-          DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
-                WithArg<1>(
-                    RecordSyncShareMultiple(&times, kMinNumSamples, true))));
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+      .Times(AtLeast(kMinNumSamples))
+      .WillOnce(
+          DoAll(WithArgs<0, 1>(
+                    sessions::test_util::SimulatePollIntervalUpdate(poll2)),
+                Return(true)))
+      .WillRepeatedly(DoAll(
+          Invoke(sessions::test_util::SimulatePollSuccess),
+          WithArg<1>(RecordSyncShareMultiple(&times, kMinNumSamples, true))));
 
   TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2;
   StartSyncScheduler(base::Time());
@@ -694,10 +698,10 @@
   TimeDelta throttle(TimeDelta::FromMinutes(10));
   scheduler()->OnReceivedLongPollIntervalUpdate(poll);
 
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          WithArg<2>(sessions::test_util::SimulateThrottled(throttle)),
-          Return(false)))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
+      .WillOnce(
+          DoAll(WithArg<2>(sessions::test_util::SimulateThrottled(throttle)),
+                Return(false)))
       .WillRepeatedly(AddFailureAndQuitLoopNow());
 
   StartSyncScheduler(base::Time());
@@ -728,12 +732,12 @@
   scheduler()->OnReceivedLongPollIntervalUpdate(poll);
 
   ::testing::InSequence seq;
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_))
-      .WillOnce(DoAll(
-          WithArg<1>(sessions::test_util::SimulateThrottled(throttle1)),
-          Return(false)))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+      .WillOnce(
+          DoAll(WithArg<1>(sessions::test_util::SimulateThrottled(throttle1)),
+                Return(false)))
       .RetiresOnSaturation();
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
       .WillRepeatedly(
           DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
                 RecordSyncShareMultiple(&times, kMinNumSamples, true)));
@@ -755,12 +759,12 @@
   scheduler()->OnReceivedLongPollIntervalUpdate(poll);
 
   ::testing::InSequence seq;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)),
-          Return(false)))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(
+          DoAll(WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)),
+                Return(false)))
       .RetiresOnSaturation();
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       QuitLoopNowAction(true)));
 
@@ -768,8 +772,8 @@
   StartSyncScheduler(base::Time());
   scheduler()->ScheduleLocalNudge(types, FROM_HERE);
 
-  PumpLoop(); // To get PerformDelayedNudge called.
-  PumpLoop(); // To get TrySyncSessionJob called
+  PumpLoop();  // To get PerformDelayedNudge called.
+  PumpLoop();  // To get TrySyncSessionJob called
   EXPECT_TRUE(scheduler()->IsCurrentlyThrottled());
   RunLoop();
   EXPECT_FALSE(scheduler()->IsCurrentlyThrottled());
@@ -784,12 +788,12 @@
   scheduler()->OnReceivedLongPollIntervalUpdate(poll);
 
   ::testing::InSequence seq;
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)),
-          Return(false)))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
+      .WillOnce(
+          DoAll(WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)),
+                Return(false)))
       .RetiresOnSaturation();
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess),
                       QuitLoopNowAction(true)));
 
@@ -828,17 +832,16 @@
   const ModelTypeSet types(THEMES);
 
   ::testing::InSequence seq;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          WithArg<2>(
-              sessions::test_util::SimulateTypesThrottled(types, throttle1)),
-          Return(false)))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(WithArg<2>(sessions::test_util::SimulateTypesThrottled(
+                          types, throttle1)),
+                      Return(false)))
       .RetiresOnSaturation();
 
   StartSyncScheduler(base::Time());
   scheduler()->ScheduleLocalNudge(types, FROM_HERE);
-  PumpLoop(); // To get PerformDelayedNudge called.
-  PumpLoop(); // To get TrySyncSessionJob called
+  PumpLoop();  // To get PerformDelayedNudge called.
+  PumpLoop();  // To get TrySyncSessionJob called
   EXPECT_TRUE(GetThrottledTypes().HasAll(types));
 
   // This won't cause a sync cycle because the types are throttled.
@@ -862,18 +865,16 @@
   const ModelTypeSet unthrottled_types(PREFERENCES);
 
   ::testing::InSequence seq;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          WithArg<2>(
-              sessions::test_util::SimulateTypesThrottled(
-                  throttled_types, throttle1)),
-          Return(false)))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(WithArg<2>(sessions::test_util::SimulateTypesThrottled(
+                          throttled_types, throttle1)),
+                      Return(false)))
       .RetiresOnSaturation();
 
   StartSyncScheduler(base::Time());
   scheduler()->ScheduleLocalNudge(throttled_types, FROM_HERE);
-  PumpLoop(); // To get PerformDelayedNudge called.
-  PumpLoop(); // To get TrySyncSessionJob called
+  PumpLoop();  // To get PerformDelayedNudge called.
+  PumpLoop();  // To get TrySyncSessionJob called
   EXPECT_TRUE(GetThrottledTypes().HasAll(throttled_types));
 
   // Ignore invalidations for throttled types.
@@ -888,7 +889,7 @@
   Mock::VerifyAndClearExpectations(syncer());
 
   // Local nudges for non-throttled types will trigger a sync.
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                             RecordSyncShare(&times, true)));
   scheduler()->ScheduleLocalNudge(unthrottled_types, FROM_HERE);
@@ -912,7 +913,7 @@
 
   const ModelTypeSet config_types(THEMES);
 
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess),
                       RecordSyncShare(&times, true)))
       .RetiresOnSaturation();
@@ -934,7 +935,7 @@
   // Switch to NORMAL_MODE to ensure NUDGES were properly saved and run.
   scheduler()->OnReceivedLongPollIntervalUpdate(TimeDelta::FromDays(1));
   SyncShareTimes times2;
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times2, true)));
 
@@ -964,7 +965,7 @@
 // Have the syncer fail during commit.  Expect that the scheduler enters
 // backoff.
 TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnce) {
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
                       QuitLoopNowAction(false)));
   EXPECT_TRUE(RunAndGetBackoff());
@@ -973,10 +974,10 @@
 // Have the syncer fail during download updates and succeed on the first
 // retry.  Expect that this clears the backoff state.
 TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadOnceThenSucceed) {
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          Invoke(sessions::test_util::SimulateDownloadUpdatesFailed),
-          Return(false)))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(
+          DoAll(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed),
+                Return(false)))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       QuitLoopNowAction(true)));
   EXPECT_FALSE(RunAndGetBackoff());
@@ -985,10 +986,9 @@
 // Have the syncer fail during commit and succeed on the first retry.  Expect
 // that this clears the backoff state.
 TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnceThenSucceed) {
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          Invoke(sessions::test_util::SimulateCommitFailed),
-          Return(false)))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
+                      Return(false)))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       QuitLoopNowAction(true)));
   EXPECT_FALSE(RunAndGetBackoff());
@@ -997,26 +997,26 @@
 // Have the syncer fail to download updates and fail again on the retry.
 // Expect this will leave the scheduler in backoff.
 TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadTwice) {
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          Invoke(sessions::test_util::SimulateDownloadUpdatesFailed),
-          Return(false)))
-      .WillRepeatedly(DoAll(
-          Invoke(sessions::test_util::SimulateDownloadUpdatesFailed),
-          QuitLoopNowAction(false)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(
+          DoAll(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed),
+                Return(false)))
+      .WillRepeatedly(
+          DoAll(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed),
+                QuitLoopNowAction(false)));
   EXPECT_TRUE(RunAndGetBackoff());
 }
 
 // Have the syncer fail to get the encryption key yet succeed in downloading
 // updates. Expect this will leave the scheduler in backoff.
 TEST_F(BackoffTriggersSyncSchedulerTest, FailGetEncryptionKey) {
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
-      .WillOnce(DoAll(
-          Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed),
-          Return(false)))
-      .WillRepeatedly(DoAll(
-          Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed),
-          QuitLoopNowAction(false)));
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
+      .WillOnce(
+          DoAll(Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed),
+                Return(false)))
+      .WillRepeatedly(
+          DoAll(Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed),
+                QuitLoopNowAction(false)));
   StartSyncConfiguration();
 
   ModelTypeSet types(THEMES);
@@ -1042,7 +1042,7 @@
   scheduler()->OnReceivedLongPollIntervalUpdate(poll);
   UseMockDelayProvider();
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
                       RecordSyncShareMultiple(&times, 1U, false)));
   EXPECT_CALL(*delay(), GetDelay(_)).
@@ -1090,9 +1090,11 @@
   SyncShareTimes times;
   UseMockDelayProvider();
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)).Times(kMinNumSamples)
-      .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
-          RecordSyncShareMultiple(&times, kMinNumSamples, false)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .Times(kMinNumSamples)
+      .WillRepeatedly(
+          DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
+                RecordSyncShareMultiple(&times, kMinNumSamples, false)));
 
   const TimeDelta first = TimeDelta::FromSeconds(kInitialBackoffRetrySeconds);
   const TimeDelta second = TimeDelta::FromMilliseconds(20);
@@ -1137,7 +1139,7 @@
   StartSyncScheduler(base::Time());
 
   // Kick off the test with a failed nudge.
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
                       RecordSyncShare(&times, false)));
   scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE);
@@ -1148,10 +1150,9 @@
   EXPECT_GE(times[0], optimal_job_time);
 
   // The retry succeeds.
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(DoAll(
-              Invoke(sessions::test_util::SimulateNormalSuccess),
-              RecordSyncShare(&times, true)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
+                      RecordSyncShare(&times, true)));
   RunLoop();
   Mock::VerifyAndClearExpectations(syncer());
   optimal_job_time = optimal_job_time + backoff;
@@ -1159,10 +1160,10 @@
   EXPECT_GE(times[1], optimal_job_time);
 
   // Now let the Poll timer do its thing.
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_))
-      .WillRepeatedly(DoAll(
-              Invoke(sessions::test_util::SimulatePollSuccess),
-              RecordSyncShareMultiple(&times, kMinNumSamples, true)));
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
+      .WillRepeatedly(
+          DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
+                RecordSyncShareMultiple(&times, kMinNumSamples, true)));
   const TimeDelta poll(TimeDelta::FromMilliseconds(10));
   scheduler()->OnReceivedLongPollIntervalUpdate(poll);
 
@@ -1187,11 +1188,11 @@
   SyncShareTimes times;
   const TimeDelta poll_interval(TimeDelta::FromMilliseconds(10));
   scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval);
-  UseMockDelayProvider(); // Will cause test failure if backoff is initiated.
+  UseMockDelayProvider();  // Will cause test failure if backoff is initiated.
   EXPECT_CALL(*delay(), GetDelay(_))
       .WillRepeatedly(Return(TimeDelta::FromMilliseconds(0)));
 
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollFailed),
                       RecordSyncShare(&times, false)))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
@@ -1213,11 +1214,11 @@
 TEST_F(SyncSchedulerTest, StartWhenNotConnected) {
   connection()->SetServerNotReachable();
   connection()->UpdateConnectionStatus();
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-    .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure),
-                    Return(false)))
-    .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
-                    Return(true)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure),
+                      Return(false)))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
+                      Return(true)));
   StartSyncScheduler(base::Time());
 
   scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE);
@@ -1239,15 +1240,15 @@
   connection()->SetServerNotReachable();
   connection()->UpdateConnectionStatus();
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-    .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure),
-                    Return(false)))
-    .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
-                    Return(true)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure),
+                      Return(false)))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
+                      Return(true)));
 
   scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE);
-  PumpLoop(); // To get PerformDelayedNudge called.
-  PumpLoop(); // Run the nudge, that will fail and schedule a quick retry.
+  PumpLoop();  // To get PerformDelayedNudge called.
+  PumpLoop();  // Run the nudge, that will fail and schedule a quick retry.
   ASSERT_TRUE(scheduler()->IsBackingOff());
 
   // Before we run the scheduled canary, trigger a server connection change.
@@ -1269,18 +1270,18 @@
   connection()->SetServerNotReachable();
   connection()->UpdateConnectionStatus();
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-    .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure),
-                    Return(false)))
-    .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
-                    Return(true)))
-    .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
-                    QuitLoopNowAction(true)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure),
+                      Return(false)))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
+                      Return(true)))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
+                      QuitLoopNowAction(true)));
 
   scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE);
 
-  PumpLoop(); // To get PerformDelayedNudge called.
-  PumpLoop(); // Run the nudge, that will fail and schedule a quick retry.
+  PumpLoop();  // To get PerformDelayedNudge called.
+  PumpLoop();  // Run the nudge, that will fail and schedule a quick retry.
   ASSERT_TRUE(scheduler()->IsBackingOff());
 
   // Before we run the scheduled canary, trigger a server connection change.
@@ -1295,10 +1296,10 @@
 // Tests that we don't crash trying to run two canaries at once if we receive
 // extra connection status change notifications.  See crbug.com/190085.
 TEST_F(SyncSchedulerTest, DoubleCanaryInConfigure) {
-  EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
-      .WillRepeatedly(DoAll(
-              Invoke(sessions::test_util::SimulateConfigureConnectionFailure),
-              Return(true)));
+  EXPECT_CALL(*syncer(), ConfigureSyncShare(_, _, _))
+      .WillRepeatedly(
+          DoAll(Invoke(sessions::test_util::SimulateConfigureConnectionFailure),
+                Return(true)));
   StartSyncConfiguration();
   connection()->SetServerNotReachable();
   connection()->UpdateConnectionStatus();
@@ -1326,7 +1327,7 @@
   scheduler()->OnReceivedLongPollIntervalUpdate(poll);
 
   ::testing::InSequence seq;
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
       .WillRepeatedly(
           DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
                 RecordSyncShareMultiple(&times, kMinNumSamples, true)));
@@ -1340,7 +1341,7 @@
   // Normally OnCredentialsUpdated calls TryCanaryJob that doesn't run Poll,
   // but after poll finished with auth error from poll timer it should retry
   // poll once more
-  EXPECT_CALL(*syncer(), PollSyncShare(_,_))
+  EXPECT_CALL(*syncer(), PollSyncShare(_, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
                       RecordSyncShare(&times, true)));
   scheduler()->OnCredentialsUpdated();
@@ -1357,10 +1358,9 @@
   scheduler()->OnReceivedGuRetryDelay(delay);
   EXPECT_EQ(delay, GetRetryTimerDelay());
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(
-          DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
-                RecordSyncShare(&times, true)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
+                      RecordSyncShare(&times, true)));
 
   // Run to wait for retrying.
   RunLoop();
@@ -1380,7 +1380,7 @@
   base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
   scheduler()->OnReceivedGuRetryDelay(delay);
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(
           DoAll(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed),
                 RecordSyncShare(&times, false)));
@@ -1389,10 +1389,9 @@
   RunLoop();
 
   EXPECT_TRUE(scheduler()->IsBackingOff());
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
-      .WillOnce(
-          DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
-                RecordSyncShare(&times, true)));
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
+      .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
+                      RecordSyncShare(&times, true)));
 
   // Run to wait for second retrying.
   RunLoop();
@@ -1415,7 +1414,7 @@
   scheduler()->OnReceivedGuRetryDelay(delay1);
   EXPECT_EQ(delay1, GetRetryTimerDelay());
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(
           WithoutArgs(VerifyRetryTimerDelay(this, delay1)),
           WithArg<2>(sessions::test_util::SimulateGuRetryDelayCommand(delay2)),
@@ -1425,7 +1424,7 @@
   RunLoop();
   EXPECT_EQ(delay2, GetRetryTimerDelay());
 
-  EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+  EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _))
       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
                       RecordSyncShare(&times, true)));
 
diff --git a/sync/engine/syncer_unittest.cc b/sync/engine/syncer_unittest.cc
index fff926c55..ccf3e2f0 100644
--- a/sync/engine/syncer_unittest.cc
+++ b/sync/engine/syncer_unittest.cc
@@ -176,7 +176,7 @@
   status_counters_map_[type] = counters;
 }
 
-} // namespace
+}  // namespace
 
 class SyncerTest : public testing::Test,
                    public SyncSession::Delegate,
@@ -185,7 +185,6 @@
   SyncerTest()
       : extensions_activity_(new ExtensionsActivity),
         syncer_(NULL),
-        saw_syncer_event_(false),
         last_client_invalidation_hint_buffer_size_(10) {
 }
 
@@ -237,14 +236,13 @@
     DVLOG(1) << "HandleSyncEngineEvent in unittest " << event.what_happened;
     // we only test for entry-specific events, not status changed ones.
     switch (event.what_happened) {
-      case SyncCycleEvent::SYNC_CYCLE_BEGIN: // Fall through.
+      case SyncCycleEvent::SYNC_CYCLE_BEGIN:  // Fall through.
       case SyncCycleEvent::STATUS_CHANGED:
       case SyncCycleEvent::SYNC_CYCLE_ENDED:
         return;
       default:
-        CHECK(false) << "Handling unknown error type in unit tests!!";
+        FAIL() << "Handling unknown error type in unit tests!!";
     }
-    saw_syncer_event_ = true;
   }
 
   void OnActionableError(const SyncProtocolError& error) override {}
@@ -319,7 +317,6 @@
     syncable::Directory::Metahandles children;
     directory()->GetChildHandlesById(&trans, trans.root_id(), &children);
     ASSERT_EQ(0u, children.size());
-    saw_syncer_event_ = false;
     root_id_ = TestIdFactory::root();
     parent_id_ = ids_.MakeServer("parent id");
     child_id_ = ids_.MakeServer("child id");
@@ -592,7 +589,6 @@
   scoped_ptr<ModelTypeRegistry> model_type_registry_;
   scoped_ptr<SyncSchedulerImpl> scheduler_;
   scoped_ptr<SyncSessionContext> context_;
-  bool saw_syncer_event_;
   base::TimeDelta last_short_poll_interval_received_;
   base::TimeDelta last_long_poll_interval_received_;
   base::TimeDelta last_sessions_commit_delay_;
@@ -604,6 +600,7 @@
   sessions::NudgeTracker nudge_tracker_;
   scoped_ptr<MockDebugInfoGetter> debug_info_getter_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(SyncerTest);
 };
 
@@ -689,8 +686,8 @@
     histogram_tester.ExpectUniqueSample("DataUse.Sync.Download.Count",
                                         BOOKMARKS, 1);
     samples = histogram_tester.GetAllSamples("DataUse.Sync.Download.Bytes");
-    EXPECT_EQ(samples.size(), 1u);
-    EXPECT_EQ(samples.at(0).min, BOOKMARKS);
+    EXPECT_EQ(1u, samples.size());
+    EXPECT_EQ(BOOKMARKS, samples.at(0).min);
     EXPECT_GE(samples.at(0).count, 0);
     download_bytes_bookmark = samples.at(0).count;
 
@@ -729,9 +726,9 @@
                                         BOOKMARKS, 1);
 
     samples = histogram_tester.GetAllSamples("DataUse.Sync.Download.Bytes");
-    EXPECT_EQ(samples.size(), 1u);
-    EXPECT_EQ(samples.at(0).min, BOOKMARKS);
-    EXPECT_EQ(samples.at(0).count, download_bytes_bookmark);
+    EXPECT_EQ(1u, samples.size());
+    EXPECT_EQ(BOOKMARKS, samples.at(0).min);
+    EXPECT_EQ(download_bytes_bookmark, samples.at(0).count);
 
     samples =
         histogram_tester.GetAllSamples("DataUse.Sync.ProgressMarker.Bytes");
@@ -753,14 +750,14 @@
     histogram_tester.ExpectUniqueSample("DataUse.Sync.Upload.Count", BOOKMARKS,
                                         1);
     samples = histogram_tester.GetAllSamples("DataUse.Sync.Upload.Bytes");
-    EXPECT_EQ(samples.size(), 1u);
-    EXPECT_EQ(samples.at(0).min, BOOKMARKS);
+    EXPECT_EQ(1u, samples.size());
+    EXPECT_EQ(BOOKMARKS, samples.at(0).min);
     EXPECT_GE(samples.at(0).count, 0);
 
     samples = histogram_tester.GetAllSamples("DataUse.Sync.Download.Bytes");
-    EXPECT_EQ(samples.size(), 1u);
-    EXPECT_EQ(samples.at(0).min, BOOKMARKS);
-    EXPECT_EQ(samples.at(0).count, download_bytes_bookmark);
+    EXPECT_EQ(1u, samples.size());
+    EXPECT_EQ(BOOKMARKS, samples.at(0).min);
+    EXPECT_EQ(download_bytes_bookmark, samples.at(0).count);
 
     histogram_tester.ExpectTotalCount("DataUse.Sync.Download.Count", 1);
 
@@ -777,22 +774,21 @@
 }
 
 // We use a macro so we can preserve the error location.
-#define VERIFY_ENTRY(id, is_unapplied, is_unsynced, prev_initialized, \
-                     parent_id, version, server_version, id_fac, rtrans) \
-  do { \
-    Entry entryA(rtrans, syncable::GET_BY_ID, id_fac.FromNumber(id)); \
-    ASSERT_TRUE(entryA.good()); \
-    /* We don't use EXPECT_EQ here because when the left side param is false,
-    gcc 4.6 warns about converting 'false' to pointer type for argument 1. */ \
-    EXPECT_TRUE(is_unsynced == entryA.GetIsUnsynced()); \
-    EXPECT_TRUE(is_unapplied == entryA.GetIsUnappliedUpdate()); \
-    EXPECT_TRUE(prev_initialized == \
-              IsRealDataType(GetModelTypeFromSpecifics( \
-                  entryA.GetBaseServerSpecifics()))); \
-    EXPECT_TRUE(parent_id == -1 || \
-                entryA.GetParentId()== id_fac.FromNumber(parent_id)); \
-    EXPECT_EQ(version, entryA.GetBaseVersion()); \
-    EXPECT_EQ(server_version, entryA.GetServerVersion()); \
+#define VERIFY_ENTRY(id, is_unapplied, is_unsynced, prev_initialized,         \
+                     parent_id, version, server_version, id_fac, rtrans)      \
+  do {                                                                        \
+    Entry entryA(rtrans, syncable::GET_BY_ID, id_fac.FromNumber(id));         \
+    ASSERT_TRUE(entryA.good());                                               \
+    /* We don't use EXPECT_EQ here because if the left side param is false,*/ \
+    /* gcc 4.6 warns converting 'false' to pointer type for argument 1.*/     \
+    EXPECT_TRUE(is_unsynced == entryA.GetIsUnsynced());                       \
+    EXPECT_TRUE(is_unapplied == entryA.GetIsUnappliedUpdate());               \
+    EXPECT_TRUE(prev_initialized == IsRealDataType(GetModelTypeFromSpecifics( \
+                                        entryA.GetBaseServerSpecifics())));   \
+    EXPECT_TRUE(parent_id == -1 ||                                            \
+                entryA.GetParentId() == id_fac.FromNumber(parent_id));        \
+    EXPECT_EQ(version, entryA.GetBaseVersion());                              \
+    EXPECT_EQ(server_version, entryA.GetServerVersion());                     \
   } while (0)
 
 TEST_F(SyncerTest, GetCommitIdsFiltersUnreadyEntries) {
@@ -899,7 +895,7 @@
   {
     const StatusController& status_controller = session_->status_controller();
     // Expect success.
-    EXPECT_EQ(status_controller.model_neutral_state().commit_result, SYNCER_OK);
+    EXPECT_EQ(SYNCER_OK, status_controller.model_neutral_state().commit_result);
     // None should be unsynced anymore.
     syncable::ReadTransaction rtrans(FROM_HERE, directory());
     VERIFY_ENTRY(1, false, false, false, 0, 21, 21, ids_, &rtrans);
@@ -1315,8 +1311,8 @@
   EXPECT_TRUE(SyncShareNudge());
   ASSERT_EQ(2u, mock_server_->committed_ids().size());
   // If this test starts failing, be aware other sort orders could be valid.
-  EXPECT_TRUE(parent_id_ == mock_server_->committed_ids()[0]);
-  EXPECT_TRUE(child_id_ == mock_server_->committed_ids()[1]);
+  EXPECT_EQ(parent_id_, mock_server_->committed_ids()[0]);
+  EXPECT_EQ(child_id_, mock_server_->committed_ids()[1]);
   {
     syncable::ReadTransaction rt(FROM_HERE, directory());
     Entry entry(&rt, syncable::GET_BY_ID, child_id_);
@@ -1363,8 +1359,8 @@
   EXPECT_TRUE(SyncShareNudge());
   ASSERT_EQ(2U, mock_server_->committed_ids().size());
   // If this test starts failing, be aware other sort orders could be valid.
-  EXPECT_TRUE(parent_id_ == mock_server_->committed_ids()[0]);
-  EXPECT_TRUE(child_id_ == mock_server_->committed_ids()[1]);
+  EXPECT_EQ(parent_id_, mock_server_->committed_ids()[0]);
+  EXPECT_EQ(child_id_, mock_server_->committed_ids()[1]);
   {
     syncable::ReadTransaction rt(FROM_HERE, directory());
     Entry entry(&rt, syncable::GET_BY_ID, child_id_);
@@ -1717,15 +1713,15 @@
   // This test will NOT unroll deletes because SERVER_PARENT_ID is not set.
   // It will treat these like moves.
   vector<syncable::Id> commit_ids(mock_server_->committed_ids());
-  EXPECT_TRUE(ids_.FromNumber(100) == commit_ids[0]);
-  EXPECT_TRUE(ids_.FromNumber(101) == commit_ids[1]);
-  EXPECT_TRUE(ids_.FromNumber(102) == commit_ids[2]);
+  EXPECT_EQ(ids_.FromNumber(100), commit_ids[0]);
+  EXPECT_EQ(ids_.FromNumber(101), commit_ids[1]);
+  EXPECT_EQ(ids_.FromNumber(102), commit_ids[2]);
   // We don't guarantee the delete orders in this test, only that they occur
   // at the end.
   std::sort(commit_ids.begin() + 3, commit_ids.end());
-  EXPECT_TRUE(ids_.FromNumber(103) == commit_ids[3]);
-  EXPECT_TRUE(ids_.FromNumber(104) == commit_ids[4]);
-  EXPECT_TRUE(ids_.FromNumber(105) == commit_ids[5]);
+  EXPECT_EQ(ids_.FromNumber(103), commit_ids[3]);
+  EXPECT_EQ(ids_.FromNumber(104), commit_ids[4]);
+  EXPECT_EQ(ids_.FromNumber(105), commit_ids[5]);
 }
 
 TEST_F(SyncerTest, TestCommitListOrderingWithNewItems) {
@@ -1838,14 +1834,14 @@
 
   EXPECT_TRUE(SyncShareNudge());
   ASSERT_EQ(3u, mock_server_->committed_ids().size());
-  EXPECT_TRUE(parent_id_ == mock_server_->committed_ids()[0]);
+  EXPECT_EQ(parent_id_, mock_server_->committed_ids()[0]);
   // There are two possible valid orderings.
   if (child2_id == mock_server_->committed_ids()[1]) {
-    EXPECT_TRUE(child2_id == mock_server_->committed_ids()[1]);
-    EXPECT_TRUE(child_id_ == mock_server_->committed_ids()[2]);
+    EXPECT_EQ(child2_id, mock_server_->committed_ids()[1]);
+    EXPECT_EQ(child_id_, mock_server_->committed_ids()[2]);
   } else {
-    EXPECT_TRUE(child_id_ == mock_server_->committed_ids()[1]);
-    EXPECT_TRUE(child2_id == mock_server_->committed_ids()[2]);
+    EXPECT_EQ(child_id_, mock_server_->committed_ids()[1]);
+    EXPECT_EQ(child2_id, mock_server_->committed_ids()[2]);
   }
 }
 
@@ -1891,14 +1887,14 @@
   EXPECT_TRUE(SyncShareNudge());
   ASSERT_EQ(3u, mock_server_->committed_ids().size());
   // If this test starts failing, be aware other sort orders could be valid.
-  EXPECT_TRUE(parent_id_ == mock_server_->committed_ids()[0]);
-  EXPECT_TRUE(parent2_id == mock_server_->committed_ids()[1]);
-  EXPECT_TRUE(child_id == mock_server_->committed_ids()[2]);
+  EXPECT_EQ(parent_id_, mock_server_->committed_ids()[0]);
+  EXPECT_EQ(parent2_id, mock_server_->committed_ids()[1]);
+  EXPECT_EQ(child_id, mock_server_->committed_ids()[2]);
   {
     syncable::ReadTransaction rtrans(FROM_HERE, directory());
     // Check that things committed correctly.
     Entry entry_1(&rtrans, syncable::GET_BY_ID, parent_id_);
-    EXPECT_EQ(entry_1.GetNonUniqueName(), parent1_name);
+    EXPECT_EQ(parent1_name, entry_1.GetNonUniqueName());
     // Check that parent2 is a subfolder of parent1.
     EXPECT_EQ(1, CountEntriesWithName(&rtrans,
                                       parent_id_,
@@ -1962,9 +1958,9 @@
   EXPECT_TRUE(SyncShareNudge());
   ASSERT_EQ(3u, mock_server_->committed_ids().size());
   // If this test starts failing, be aware other sort orders could be valid.
-  EXPECT_TRUE(parent_id_ == mock_server_->committed_ids()[0]);
-  EXPECT_TRUE(parent2_local_id == mock_server_->committed_ids()[1]);
-  EXPECT_TRUE(child_local_id == mock_server_->committed_ids()[2]);
+  EXPECT_EQ(parent_id_, mock_server_->committed_ids()[0]);
+  EXPECT_EQ(parent2_local_id, mock_server_->committed_ids()[1]);
+  EXPECT_EQ(child_local_id, mock_server_->committed_ids()[2]);
   {
     syncable::ReadTransaction rtrans(FROM_HERE, directory());
 
@@ -1986,7 +1982,7 @@
 
     Entry entry_b(&rtrans, syncable::GET_BY_HANDLE, meta_handle_b);
     EXPECT_TRUE(entry_b.GetId().ServerKnows());
-    EXPECT_TRUE(parent2.GetId()== entry_b.GetParentId());
+    EXPECT_TRUE(parent2.GetId() == entry_b.GetParentId());
   }
 }
 
@@ -2021,8 +2017,8 @@
                syncable::Id::CreateFromServerId("some_id"));
     ASSERT_TRUE(entry.good());
     EXPECT_TRUE(entry.GetIsDir());
-    EXPECT_TRUE(entry.GetServerVersion()== version);
-    EXPECT_TRUE(entry.GetBaseVersion()== version);
+    EXPECT_EQ(version, entry.GetServerVersion());
+    EXPECT_EQ(version, entry.GetBaseVersion());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
     EXPECT_FALSE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetServerIsDel());
@@ -2153,8 +2149,7 @@
 
     Entry ignored_old_version(&trans, GET_BY_ID, ids_.FromNumber(4));
     ASSERT_TRUE(ignored_old_version.good());
-    EXPECT_TRUE(
-        ignored_old_version.GetNonUniqueName()== "newer_version");
+    EXPECT_EQ("newer_version", ignored_old_version.GetNonUniqueName());
     EXPECT_FALSE(ignored_old_version.GetIsUnappliedUpdate());
     EXPECT_EQ(20u, ignored_old_version.GetBaseVersion());
 
@@ -2162,20 +2157,18 @@
     ASSERT_TRUE(circular_parent_issue.good());
     EXPECT_TRUE(circular_parent_issue.GetIsUnappliedUpdate())
         << "circular move should be in conflict";
-    EXPECT_TRUE(circular_parent_issue.GetParentId()== root_id_);
-    EXPECT_TRUE(circular_parent_issue.GetServerParentId()==
-                ids_.FromNumber(6));
+    EXPECT_EQ(root_id_, circular_parent_issue.GetParentId());
+    EXPECT_EQ(ids_.FromNumber(6), circular_parent_issue.GetServerParentId());
     EXPECT_EQ(10u, circular_parent_issue.GetBaseVersion());
 
     Entry circular_parent_target(&trans, GET_BY_ID, ids_.FromNumber(6));
     ASSERT_TRUE(circular_parent_target.good());
     EXPECT_FALSE(circular_parent_target.GetIsUnappliedUpdate());
-    EXPECT_TRUE(circular_parent_issue.GetId()==
-        circular_parent_target.GetParentId());
+    EXPECT_EQ(circular_parent_issue.GetId(),
+              circular_parent_target.GetParentId());
     EXPECT_EQ(10u, circular_parent_target.GetBaseVersion());
   }
 
-  EXPECT_FALSE(saw_syncer_event_);
   EXPECT_EQ(
       4,
       GetUpdateCounters(BOOKMARKS).num_hierarchy_conflict_application_failures);
@@ -2253,8 +2246,8 @@
     Entry folder(&trans, GET_BY_HANDLE, metahandle_folder);
     ASSERT_TRUE(folder.good());
     EXPECT_EQ("new_folder", folder.GetNonUniqueName());
-    EXPECT_TRUE(new_version == folder.GetBaseVersion());
-    EXPECT_TRUE(new_folder_id == folder.GetId());
+    EXPECT_EQ(new_version, folder.GetBaseVersion());
+    EXPECT_EQ(new_folder_id, folder.GetId());
     EXPECT_TRUE(folder.GetId().ServerKnows());
     EXPECT_EQ(trans.root_id(), folder.GetParentId());
 
@@ -2316,8 +2309,8 @@
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry entry(&trans, GET_BY_HANDLE, entry_metahandle);
     ASSERT_TRUE(entry.good());
-    EXPECT_TRUE(new_version == entry.GetBaseVersion());
-    EXPECT_TRUE(new_entry_id == entry.GetId());
+    EXPECT_EQ(new_version, entry.GetBaseVersion());
+    EXPECT_EQ(new_entry_id, entry.GetId());
     EXPECT_EQ("new_entry", entry.GetNonUniqueName());
   }
 }
@@ -2410,7 +2403,6 @@
     B.PutServerVersion(20);
   }
   EXPECT_TRUE(SyncShareNudge());
-  saw_syncer_event_ = false;
   mock_server_->set_conflict_all_commits(false);
 
   {
@@ -2418,15 +2410,15 @@
 
     Entry A(&trans, GET_BY_ID, ids_.FromNumber(1));
     ASSERT_TRUE(A.good());
-    EXPECT_TRUE(A.GetIsUnsynced()== false);
-    EXPECT_TRUE(A.GetIsUnappliedUpdate()== false);
-    EXPECT_TRUE(A.GetServerVersion()== 20);
+    EXPECT_FALSE(A.GetIsUnsynced());
+    EXPECT_FALSE(A.GetIsUnappliedUpdate());
+    EXPECT_EQ(20, A.GetServerVersion());
 
     Entry B(&trans, GET_BY_ID, ids_.FromNumber(2));
     ASSERT_TRUE(B.good());
-    EXPECT_TRUE(B.GetIsUnsynced()== false);
-    EXPECT_TRUE(B.GetIsUnappliedUpdate()== false);
-    EXPECT_TRUE(B.GetServerVersion()== 20);
+    EXPECT_FALSE(B.GetIsUnsynced());
+    EXPECT_FALSE(B.GetIsUnappliedUpdate());
+    EXPECT_EQ(20, B.GetServerVersion());
   }
 }
 
@@ -2452,7 +2444,6 @@
     B.PutServerVersion(20);
   }
   EXPECT_TRUE(SyncShareNudge());
-  saw_syncer_event_ = false;
   mock_server_->set_conflict_all_commits(false);
 
   {
@@ -2460,15 +2451,15 @@
 
     Entry A(&trans, GET_BY_ID, ids_.FromNumber(1));
     ASSERT_TRUE(A.good());
-    EXPECT_TRUE(A.GetIsUnsynced()== false);
-    EXPECT_TRUE(A.GetIsUnappliedUpdate()== false);
-    EXPECT_TRUE(A.GetServerVersion()== 20);
+    EXPECT_FALSE(A.GetIsUnsynced());
+    EXPECT_FALSE(A.GetIsUnappliedUpdate());
+    EXPECT_EQ(20, A.GetServerVersion());
 
     Entry B(&trans, GET_BY_ID, ids_.FromNumber(2));
     ASSERT_TRUE(B.good());
-    EXPECT_TRUE(B.GetIsUnsynced()== false);
-    EXPECT_TRUE(B.GetIsUnappliedUpdate()== false);
-    EXPECT_TRUE(B.GetServerVersion()== 20);
+    EXPECT_FALSE(B.GetIsUnsynced());
+    EXPECT_FALSE(B.GetIsUnappliedUpdate());
+    EXPECT_EQ(20, B.GetServerVersion());
   }
 }
 
@@ -2501,11 +2492,11 @@
                      GetOnlyEntryWithName(&trans,
                                           TestIdFactory::root(),
                                           "bob"));
-    CHECK(bob.good());
+    ASSERT_TRUE(bob.good());
 
     MutableEntry entry2(
         &trans, CREATE, BOOKMARKS, bob.GetId(), "bob");
-    CHECK(entry2.good());
+    ASSERT_TRUE(entry2.good());
     entry2.PutIsDir(true);
     entry2.PutIsUnsynced(true);
     entry2.PutSpecifics(DefaultBookmarkSpecifics());
@@ -2626,7 +2617,6 @@
 
   // Only one entry, since we just overwrite one.
   EXPECT_EQ(1u, children.size());
-  saw_syncer_event_ = false;
 }
 
 // We got this repro case when someone was editing bookmarks while sync was
@@ -2670,7 +2660,7 @@
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry entry(&trans, syncable::GET_BY_ID, id);
     ASSERT_TRUE(entry.good());
-    EXPECT_TRUE(entry.GetMtime()== test_time);
+    EXPECT_EQ(test_time, entry.GetMtime());
   }
 }
 
@@ -2729,7 +2719,6 @@
     syncable::Directory::Metahandles unsynced;
     directory()->GetUnsyncedMetaHandles(&trans, &unsynced);
     EXPECT_EQ(0u, unsynced.size());
-    saw_syncer_event_ = false;
   }
 }
 
@@ -2770,7 +2759,6 @@
   }
   EXPECT_TRUE(SyncShareNudge());
   EXPECT_EQ(1, session_->status_controller().TotalNumConflictingItems());
-  saw_syncer_event_ = false;
 }
 
 // Original problem synopsis:
@@ -2902,14 +2890,13 @@
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry id1(&trans, GET_BY_ID, ids_.FromNumber(7801));
     ASSERT_TRUE(id1.good());
-    EXPECT_TRUE("fred" == id1.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id1.GetParentId());
+    EXPECT_EQ("fred", id1.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id1.GetParentId());
     Entry id2(&trans, GET_BY_ID, ids_.FromNumber(1024));
     ASSERT_TRUE(id2.good());
-    EXPECT_TRUE("bob" == id2.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id2.GetParentId());
+    EXPECT_EQ("bob", id2.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id2.GetParentId());
   }
-  saw_syncer_event_ = false;
 }
 
 TEST_F(SyncerTest, NameCollidingFolderSwapWorksFine) {
@@ -2924,16 +2911,16 @@
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry id1(&trans, GET_BY_ID, ids_.FromNumber(7801));
     ASSERT_TRUE(id1.good());
-    EXPECT_TRUE("bob" == id1.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id1.GetParentId());
+    EXPECT_EQ("bob", id1.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id1.GetParentId());
     Entry id2(&trans, GET_BY_ID, ids_.FromNumber(1024));
     ASSERT_TRUE(id2.good());
-    EXPECT_TRUE("fred" == id2.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id2.GetParentId());
+    EXPECT_EQ("fred", id2.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id2.GetParentId());
     Entry id3(&trans, GET_BY_ID, ids_.FromNumber(4096));
     ASSERT_TRUE(id3.good());
-    EXPECT_TRUE("alice" == id3.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id3.GetParentId());
+    EXPECT_EQ("alice", id3.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id3.GetParentId());
   }
   mock_server_->AddUpdateDirectory(1024, 0, "bob", 2, 20,
                                    foreign_cache_guid(), "-1024");
@@ -2946,18 +2933,17 @@
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry id1(&trans, GET_BY_ID, ids_.FromNumber(7801));
     ASSERT_TRUE(id1.good());
-    EXPECT_TRUE("fred" == id1.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id1.GetParentId());
+    EXPECT_EQ("fred", id1.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id1.GetParentId());
     Entry id2(&trans, GET_BY_ID, ids_.FromNumber(1024));
     ASSERT_TRUE(id2.good());
-    EXPECT_TRUE("bob" == id2.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id2.GetParentId());
+    EXPECT_EQ("bob", id2.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id2.GetParentId());
     Entry id3(&trans, GET_BY_ID, ids_.FromNumber(4096));
     ASSERT_TRUE(id3.good());
-    EXPECT_TRUE("bob" == id3.GetNonUniqueName());
-    EXPECT_TRUE(root_id_ == id3.GetParentId());
+    EXPECT_EQ("bob", id3.GetNonUniqueName());
+    EXPECT_EQ(root_id_, id3.GetParentId());
   }
-  saw_syncer_event_ = false;
 }
 
 // Committing more than kDefaultMaxCommitBatchSize items requires that
@@ -3252,7 +3238,6 @@
   mock_server_->AddUpdateDirectory(1, 0, "BOB", 2, 20,
                                    foreign_cache_guid(), "-1");
   EXPECT_FALSE(SyncShareNudge());  // USED TO CAUSE AN ASSERT
-  saw_syncer_event_ = false;
 }
 
 TEST_F(SyncerTest, UnsyncedItemAndUpdate) {
@@ -3263,7 +3248,6 @@
   mock_server_->AddUpdateDirectory(2, 0, "bob", 2, 20,
                                    foreign_cache_guid(), "-2");
   EXPECT_TRUE(SyncShareNudge());  // USED TO CAUSE AN ASSERT
-  saw_syncer_event_ = false;
 }
 
 TEST_F(SyncerTest, NewEntryAndAlteredServerEntrySharePath) {
@@ -3289,7 +3273,6 @@
                                   foreign_cache_guid(), "-1");
   mock_server_->set_conflict_all_commits(true);
   EXPECT_FALSE(SyncShareNudge());
-  saw_syncer_event_ = false;
   {
     // Update #20 should have been dropped in favor of the local version.
     WriteTransaction wtrans(FROM_HERE, UNITTEST, directory());
@@ -3297,7 +3280,7 @@
     MutableEntry local(&wtrans, GET_BY_HANDLE, local_folder_handle);
     ASSERT_TRUE(server.good());
     ASSERT_TRUE(local.good());
-    EXPECT_TRUE(local.GetMetahandle()!= server.GetMetahandle());
+    EXPECT_NE(local.GetMetahandle(), server.GetMetahandle());
     EXPECT_FALSE(server.GetIsUnappliedUpdate());
     EXPECT_FALSE(local.GetIsUnappliedUpdate());
     EXPECT_TRUE(server.GetIsUnsynced());
@@ -3308,21 +3291,19 @@
   // Allow local changes to commit.
   mock_server_->set_conflict_all_commits(false);
   EXPECT_TRUE(SyncShareNudge());
-  saw_syncer_event_ = false;
 
   // Now add a server change to make the two names equal.  There should
   // be no conflict with that, since names are not unique.
   mock_server_->AddUpdateBookmark(1, 0, "Bar.htm", 30, 30,
                                   foreign_cache_guid(), "-1");
   EXPECT_TRUE(SyncShareNudge());
-  saw_syncer_event_ = false;
   {
     WriteTransaction wtrans(FROM_HERE, UNITTEST, directory());
     MutableEntry server(&wtrans, GET_BY_ID, ids_.FromNumber(1));
     MutableEntry local(&wtrans, GET_BY_HANDLE, local_folder_handle);
     ASSERT_TRUE(server.good());
     ASSERT_TRUE(local.good());
-    EXPECT_TRUE(local.GetMetahandle()!= server.GetMetahandle());
+    EXPECT_NE(local.GetMetahandle(), server.GetMetahandle());
     EXPECT_FALSE(server.GetIsUnappliedUpdate());
     EXPECT_FALSE(local.GetIsUnappliedUpdate());
     EXPECT_FALSE(server.GetIsUnsynced());
@@ -3359,7 +3340,6 @@
                                   foreign_cache_guid(), "-1");
   mock_server_->set_conflict_all_commits(true);
   EXPECT_FALSE(SyncShareNudge());
-  saw_syncer_event_ = false;
   {
     // Update #20 should have been dropped in favor of the local version.
     WriteTransaction wtrans(FROM_HERE, UNITTEST, directory());
@@ -3367,7 +3347,7 @@
     MutableEntry local(&wtrans, GET_BY_HANDLE, local_folder_handle);
     ASSERT_TRUE(server.good());
     ASSERT_TRUE(local.good());
-    EXPECT_TRUE(local.GetMetahandle()!= server.GetMetahandle());
+    EXPECT_NE(local.GetMetahandle(), server.GetMetahandle());
     EXPECT_FALSE(server.GetIsUnappliedUpdate());
     EXPECT_FALSE(local.GetIsUnappliedUpdate());
     EXPECT_TRUE(server.GetIsUnsynced());
@@ -3378,21 +3358,19 @@
   // Allow local changes to commit.
   mock_server_->set_conflict_all_commits(false);
   EXPECT_TRUE(SyncShareNudge());
-  saw_syncer_event_ = false;
 
   // Now add a server change to make the two names equal.  There should
   // be no conflict with that, since names are not unique.
   mock_server_->AddUpdateBookmark(1, 0, "Bar.htm", 30, 30,
                                   foreign_cache_guid(), "-1");
   EXPECT_TRUE(SyncShareNudge());
-  saw_syncer_event_ = false;
   {
     WriteTransaction wtrans(FROM_HERE, UNITTEST, directory());
     MutableEntry server(&wtrans, GET_BY_ID, ids_.FromNumber(1));
     MutableEntry local(&wtrans, GET_BY_HANDLE, local_folder_handle);
     ASSERT_TRUE(server.good());
     ASSERT_TRUE(local.good());
-    EXPECT_TRUE(local.GetMetahandle()!= server.GetMetahandle());
+    EXPECT_NE(local.GetMetahandle(), server.GetMetahandle());
     EXPECT_FALSE(server.GetIsUnappliedUpdate());
     EXPECT_FALSE(local.GetIsUnappliedUpdate());
     EXPECT_FALSE(server.GetIsUnsynced());
@@ -3424,15 +3402,14 @@
                                    foreign_cache_guid(), "-2");
   mock_server_->set_conflict_all_commits(true);
   EXPECT_FALSE(SyncShareNudge());
-  saw_syncer_event_ = false;
   {
     WriteTransaction wtrans(FROM_HERE, UNITTEST, directory());
     MutableEntry A(&wtrans, GET_BY_ID, ids_.FromNumber(1));
     ASSERT_TRUE(A.good());
     MutableEntry B(&wtrans, GET_BY_ID, ids_.FromNumber(2));
     ASSERT_TRUE(B.good());
-    EXPECT_TRUE(A.GetNonUniqueName()== "B");
-    EXPECT_TRUE(B.GetNonUniqueName()== "B");
+    EXPECT_EQ("B", A.GetNonUniqueName());
+    EXPECT_EQ("B", B.GetNonUniqueName());
   }
 }
 
@@ -3457,7 +3434,6 @@
     A.PutNonUniqueName("B");
   }
   EXPECT_FALSE(SyncShareNudge());
-  saw_syncer_event_ = false;
 }
 
 TEST_F(SyncerTest, DualDeletionWithNewItemNameClash) {
@@ -3485,7 +3461,6 @@
     EXPECT_FALSE(B.GetIsUnsynced());
     EXPECT_FALSE(B.GetIsUnappliedUpdate());
   }
-  saw_syncer_event_ = false;
 }
 
 // When we undelete an entity as a result of conflict resolution, we reuse the
@@ -3521,7 +3496,6 @@
     EXPECT_EQ(2, bob.GetServerVersion());
     EXPECT_EQ(2, bob.GetBaseVersion());
   }
-  saw_syncer_event_ = false;
 }
 
 // This test is to reproduce a check failure. Sometimes we would get a bad ID
@@ -3549,7 +3523,6 @@
   EXPECT_EQ(1u, directory()->unsynced_entity_count());
   EXPECT_TRUE(SyncShareNudge());  // another bad id in here.
   EXPECT_EQ(0u, directory()->unsynced_entity_count());
-  saw_syncer_event_ = false;
 }
 
 TEST_F(SyncerTest, DeletedEntryWithBadParentInLoopCalculation) {
@@ -3598,11 +3571,11 @@
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry local_deleted(&trans, GET_BY_ID, ids_.FromNumber(1));
-    EXPECT_TRUE(local_deleted.GetBaseVersion()== 10);
-    EXPECT_TRUE(local_deleted.GetIsUnappliedUpdate()== false);
-    EXPECT_TRUE(local_deleted.GetIsUnsynced()== true);
-    EXPECT_TRUE(local_deleted.GetIsDel()== true);
-    EXPECT_TRUE(local_deleted.GetIsDir()== false);
+    EXPECT_EQ(10, local_deleted.GetBaseVersion());
+    EXPECT_FALSE(local_deleted.GetIsUnappliedUpdate());
+    EXPECT_TRUE(local_deleted.GetIsUnsynced());
+    EXPECT_TRUE(local_deleted.GetIsDel());
+    EXPECT_FALSE(local_deleted.GetIsDir());
   }
 }
 
@@ -3637,11 +3610,11 @@
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry local_deleted(&trans, GET_BY_ID, ids_.FromNumber(1));
-    EXPECT_TRUE(local_deleted.GetBaseVersion()== 1);
-    EXPECT_TRUE(local_deleted.GetIsUnappliedUpdate()== false);
-    EXPECT_TRUE(local_deleted.GetIsUnsynced()== true);
-    EXPECT_TRUE(local_deleted.GetIsDel()== true);
-    EXPECT_TRUE(local_deleted.GetIsDir()== true);
+    EXPECT_EQ(1, local_deleted.GetBaseVersion());
+    EXPECT_FALSE(local_deleted.GetIsUnappliedUpdate());
+    EXPECT_TRUE(local_deleted.GetIsUnsynced());
+    EXPECT_TRUE(local_deleted.GetIsDel());
+    EXPECT_TRUE(local_deleted.GetIsDir());
   }
 }
 
@@ -3787,7 +3760,7 @@
     EXPECT_TRUE(entry.GetIsDel());
     EXPECT_FALSE(entry.GetServerIsDel());
     EXPECT_TRUE(entry.GetIsUnappliedUpdate());
-    EXPECT_NE(entry.GetMetahandle(), metahandle);
+    EXPECT_NE(metahandle, entry.GetMetahandle());
   }
 }
 
@@ -3887,12 +3860,12 @@
     Entry foo_entry(&trans, GET_BY_HANDLE, foo_metahandle);
     ASSERT_TRUE(foo_entry.good());
     EXPECT_EQ("foo", foo_entry.GetNonUniqueName());
-    EXPECT_NE(foo_entry.GetId(), in_root_id);
+    EXPECT_NE(in_root_id, foo_entry.GetId());
 
     Entry bar_entry(&trans, GET_BY_HANDLE, bar_metahandle);
     ASSERT_TRUE(bar_entry.good());
     EXPECT_EQ("bar", bar_entry.GetNonUniqueName());
-    EXPECT_NE(bar_entry.GetId(), in_dir_id);
+    EXPECT_NE(in_dir_id, bar_entry.GetId());
     EXPECT_EQ(foo_entry.GetId(), bar_entry.GetParentId());
   }
 }
@@ -4010,8 +3983,8 @@
   EXPECT_TRUE(SyncShareNudge());
   const sync_pb::CommitMessage& commit = mock_server_->last_sent_commit();
   ASSERT_EQ(2, commit.entries_size());
-  EXPECT_TRUE(commit.entries(0).parent_id_string() == "2");
-  EXPECT_TRUE(commit.entries(0).old_parent_id() == "0");
+  EXPECT_EQ("2", commit.entries(0).parent_id_string());
+  EXPECT_EQ("0", commit.entries(0).old_parent_id());
   EXPECT_FALSE(commit.entries(1).has_old_parent_id());
 }
 
@@ -4034,7 +4007,7 @@
   syncable::ReadTransaction rtrans(FROM_HERE, directory());
   Entry entry(&rtrans, syncable::GET_BY_HANDLE, item_metahandle);
   ASSERT_TRUE(entry.good());
-  EXPECT_TRUE(really_big_int == entry.GetBaseVersion());
+  EXPECT_EQ(really_big_int, entry.GetBaseVersion());
 }
 
 TEST_F(SyncerTest, TestSimpleUndelete) {
@@ -4174,8 +4147,8 @@
     EXPECT_FALSE(perm_folder.GetIsDel());
     EXPECT_FALSE(perm_folder.GetIsUnappliedUpdate());
     EXPECT_FALSE(perm_folder.GetIsUnsynced());
-    EXPECT_EQ(perm_folder.GetUniqueClientTag(), "permfolder");
-    EXPECT_EQ(perm_folder.GetNonUniqueName(), "permitem1");
+    EXPECT_EQ("permfolder", perm_folder.GetUniqueClientTag());
+    EXPECT_EQ("permitem1", perm_folder.GetNonUniqueName());
   }
 
   mock_server_->AddUpdateDirectory(1, 0, "permitem_renamed", 10, 100,
@@ -4191,8 +4164,8 @@
     EXPECT_FALSE(perm_folder.GetIsDel());
     EXPECT_FALSE(perm_folder.GetIsUnappliedUpdate());
     EXPECT_FALSE(perm_folder.GetIsUnsynced());
-    EXPECT_EQ(perm_folder.GetUniqueClientTag(), "permfolder");
-    EXPECT_EQ(perm_folder.GetNonUniqueName(), "permitem_renamed");
+    EXPECT_EQ("permfolder", perm_folder.GetUniqueClientTag());
+    EXPECT_EQ("permitem_renamed", perm_folder.GetNonUniqueName());
   }
 }
 
@@ -4209,8 +4182,8 @@
     ASSERT_TRUE(perm_folder.good());
     EXPECT_FALSE(perm_folder.GetIsUnappliedUpdate());
     EXPECT_FALSE(perm_folder.GetIsUnsynced());
-    EXPECT_EQ(perm_folder.GetUniqueClientTag(), "permfolder");
-    EXPECT_TRUE(perm_folder.GetNonUniqueName()== "permitem1");
+    EXPECT_EQ("permfolder", perm_folder.GetUniqueClientTag());
+    EXPECT_EQ("permitem1", perm_folder.GetNonUniqueName());
     EXPECT_TRUE(perm_folder.GetId().ServerKnows());
   }
 
@@ -4232,7 +4205,7 @@
     ASSERT_TRUE(perm_folder.good());
     EXPECT_FALSE(perm_folder.GetIsUnappliedUpdate());
     EXPECT_FALSE(perm_folder.GetIsUnsynced());
-    EXPECT_EQ(perm_folder.GetNonUniqueName(), "permitem1");
+    EXPECT_EQ("permitem1", perm_folder.GetNonUniqueName());
   }
 }
 
@@ -4287,7 +4260,7 @@
     EXPECT_FALSE(pref.GetIsDel());
     EXPECT_FALSE(pref.GetIsUnappliedUpdate());
     EXPECT_FALSE(pref.GetIsUnsynced());
-    EXPECT_TRUE(10 < pref.GetBaseVersion());
+    EXPECT_LT(10, pref.GetBaseVersion());
     // Entry should have been given the new ID while preserving the
     // metahandle; client should have won the conflict resolution.
     EXPECT_EQ(original_metahandle, pref.GetMetahandle());
@@ -4330,16 +4303,16 @@
     EXPECT_FALSE(pref.GetIsDel());
     EXPECT_FALSE(pref.GetIsUnappliedUpdate());
     EXPECT_FALSE(pref.GetIsUnsynced());
-    EXPECT_EQ(pref.GetBaseVersion(), 10);
-    EXPECT_EQ(pref.GetUniqueClientTag(), "tag");
+    EXPECT_EQ(10, pref.GetBaseVersion());
+    EXPECT_EQ("tag", pref.GetUniqueClientTag());
   }
 }
 
 TEST_F(SyncerTest, ClientTagUpdateClashesWithLocalEntry) {
   // This test is written assuming that ID comparison
   // will work out in a particular way.
-  EXPECT_TRUE(ids_.FromNumber(1) < ids_.FromNumber(2));
-  EXPECT_TRUE(ids_.FromNumber(3) < ids_.FromNumber(4));
+  EXPECT_LT(ids_.FromNumber(1), ids_.FromNumber(2));
+  EXPECT_LT(ids_.FromNumber(3), ids_.FromNumber(4));
 
   syncable::Id id1 = TestIdFactory::MakeServer("1");
   mock_server_->AddUpdatePref(id1.GetServerId(), "", "tag1", 10, 100);
@@ -4359,7 +4332,7 @@
     Entry tag1(&trans, GET_BY_CLIENT_TAG, "tag1");
     ASSERT_TRUE(tag1.good());
     ASSERT_TRUE(tag1.GetId().ServerKnows());
-    ASSERT_TRUE(id1 == tag1.GetId());
+    ASSERT_EQ(id1, tag1.GetId());
     EXPECT_FALSE(tag1.GetIsDel());
     EXPECT_FALSE(tag1.GetIsUnappliedUpdate());
     EXPECT_FALSE(tag1.GetIsUnsynced());
@@ -4370,7 +4343,7 @@
     Entry tag2(&trans, GET_BY_CLIENT_TAG, "tag2");
     ASSERT_TRUE(tag2.good());
     ASSERT_TRUE(tag2.GetId().ServerKnows());
-    ASSERT_TRUE(id4 == tag2.GetId());
+    ASSERT_EQ(id4, tag2.GetId());
     EXPECT_FALSE(tag2.GetIsDel());
     EXPECT_FALSE(tag2.GetIsUnappliedUpdate());
     EXPECT_FALSE(tag2.GetIsUnsynced());
@@ -4437,8 +4410,8 @@
 TEST_F(SyncerTest, ClientTagClashWithinBatchOfUpdates) {
   // This test is written assuming that ID comparison
   // will work out in a particular way.
-  EXPECT_TRUE(ids_.FromNumber(1) < ids_.FromNumber(4));
-  EXPECT_TRUE(ids_.FromNumber(201) < ids_.FromNumber(205));
+  EXPECT_LT(ids_.FromNumber(1), ids_.FromNumber(4));
+  EXPECT_LT(ids_.FromNumber(201), ids_.FromNumber(205));
 
   // Least ID: winner.
   mock_server_->AddUpdatePref(ids_.FromNumber(1).GetServerId(), "", "tag a", 1,
@@ -4589,7 +4562,7 @@
     ASSERT_TRUE(hurdle.good());
     ASSERT_TRUE(!hurdle.GetIsDel());
     ASSERT_TRUE(hurdle.GetUniqueServerTag().empty());
-    ASSERT_TRUE(hurdle.GetNonUniqueName()== "bob");
+    ASSERT_EQ("bob", hurdle.GetNonUniqueName());
 
     // Try to lookup by the tagname.  These should fail.
     Entry tag_alpha(&trans, GET_BY_SERVER_TAG, "alpha");
@@ -4615,19 +4588,19 @@
     Entry tag_alpha(&trans, GET_BY_SERVER_TAG, "alpha");
     ASSERT_TRUE(tag_alpha.good());
     ASSERT_TRUE(!tag_alpha.GetIsDel());
-    ASSERT_TRUE(tag_alpha.GetUniqueServerTag()== "alpha");
-    ASSERT_TRUE(tag_alpha.GetNonUniqueName()== "update1");
+    ASSERT_EQ("alpha", tag_alpha.GetUniqueServerTag());
+    ASSERT_EQ("update1", tag_alpha.GetNonUniqueName());
     Entry tag_bob(&trans, GET_BY_SERVER_TAG, "bob");
     ASSERT_TRUE(tag_bob.good());
     ASSERT_TRUE(!tag_bob.GetIsDel());
-    ASSERT_TRUE(tag_bob.GetUniqueServerTag()== "bob");
-    ASSERT_TRUE(tag_bob.GetNonUniqueName()== "update2");
+    ASSERT_EQ("bob", tag_bob.GetUniqueServerTag());
+    ASSERT_EQ("update2", tag_bob.GetNonUniqueName());
     // The old item should be unchanged.
     Entry hurdle(&trans, GET_BY_HANDLE, hurdle_handle);
     ASSERT_TRUE(hurdle.good());
     ASSERT_TRUE(!hurdle.GetIsDel());
     ASSERT_TRUE(hurdle.GetUniqueServerTag().empty());
-    ASSERT_TRUE(hurdle.GetNonUniqueName()== "bob");
+    ASSERT_EQ("bob", hurdle.GetNonUniqueName());
   }
 }
 
@@ -4798,7 +4771,7 @@
 
   SyncShareConfigure();
 
-  EXPECT_EQ(session_->status_controller().last_get_key_result(), SYNCER_OK);
+  EXPECT_EQ(SYNCER_OK, session_->status_controller().last_get_key_result());
   {
     syncable::ReadTransaction rtrans(FROM_HERE, directory());
     EXPECT_FALSE(directory()->GetNigoriHandler()->NeedKeystoreKey(&rtrans));
@@ -4814,7 +4787,7 @@
   mock_server_->SetKeystoreKey(std::string());
   SyncShareConfigure();
 
-  EXPECT_NE(session_->status_controller().last_get_key_result(), SYNCER_OK);
+  EXPECT_NE(SYNCER_OK, session_->status_controller().last_get_key_result());
   {
     syncable::ReadTransaction rtrans(FROM_HERE, directory());
     EXPECT_TRUE(directory()->GetNigoriHandler()->NeedKeystoreKey(&rtrans));
@@ -5034,8 +5007,8 @@
     EXPECT_FALSE(entry.GetServerIsDel());
     EXPECT_FALSE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
-    EXPECT_EQ(entry.GetBaseVersion(), -1);
-    EXPECT_EQ(entry.GetServerVersion(), 0);
+    EXPECT_EQ(-1, entry.GetBaseVersion());
+    EXPECT_EQ(0, entry.GetServerVersion());
   }
 }
 
@@ -5649,7 +5622,6 @@
     }
   }
 
-
   // Put some extenions activity records into the monitor.
   {
     ExtensionsActivity::Records records;
diff --git a/sync/engine/traffic_logger.h b/sync/engine/traffic_logger.h
index 0205395..39997de1 100644
--- a/sync/engine/traffic_logger.h
+++ b/sync/engine/traffic_logger.h
@@ -6,8 +6,8 @@
 // To get the log run a debug build of chrome with the flag
 // --vmodule=traffic_logger=1.
 
-#ifndef CHROME_BROWSER_SYNC_ENGINE_TRAFFIC_LOGGER_H_
-#define CHROME_BROWSER_SYNC_ENGINE_TRAFFIC_LOGGER_H_
+#ifndef SYNC_ENGINE_TRAFFIC_LOGGER_H_
+#define SYNC_ENGINE_TRAFFIC_LOGGER_H_
 
 namespace sync_pb {
 class ClientToServerResponse;
@@ -22,4 +22,4 @@
 
 }  // namespace syncer
 
-#endif  // CHROME_BROWSER_SYNC_ENGINE_TRAFFIC_LOGGER_H_
+#endif  // SYNC_ENGINE_TRAFFIC_LOGGER_H_
diff --git a/sync/engine/update_applicator.h b/sync/engine/update_applicator.h
index 55534ad1..1fc8bb80 100644
--- a/sync/engine/update_applicator.h
+++ b/sync/engine/update_applicator.h
@@ -11,6 +11,7 @@
 #ifndef SYNC_ENGINE_UPDATE_APPLICATOR_H_
 #define SYNC_ENGINE_UPDATE_APPLICATOR_H_
 
+#include <set>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -34,7 +35,7 @@
 
 class UpdateApplicator {
  public:
-  UpdateApplicator(Cryptographer* cryptographer);
+  explicit UpdateApplicator(Cryptographer* cryptographer);
   ~UpdateApplicator();
 
   // Attempt to apply the specified updates.
@@ -64,12 +65,12 @@
   // Used to decrypt sensitive sync nodes.
   Cryptographer* cryptographer_;
 
-  DISALLOW_COPY_AND_ASSIGN(UpdateApplicator);
-
   int updates_applied_;
   int encryption_conflicts_;
   int hierarchy_conflicts_;
   std::set<syncable::Id> simple_conflict_ids_;
+
+  DISALLOW_COPY_AND_ASSIGN(UpdateApplicator);
 };
 
 }  // namespace syncer
diff --git a/sync/internal_api/public/attachments/attachment_service_proxy.h b/sync/internal_api/public/attachments/attachment_service_proxy.h
index 9953b8d..f7d1b3c 100644
--- a/sync/internal_api/public/attachments/attachment_service_proxy.h
+++ b/sync/internal_api/public/attachments/attachment_service_proxy.h
@@ -81,10 +81,11 @@
     void UploadAttachments(const AttachmentIdList& attachment_ids) override;
 
    protected:
-    friend class base::RefCountedThreadSafe<Core>;
     ~Core() override;
 
    private:
+    friend class base::RefCountedThreadSafe<Core>;
+
     base::WeakPtr<AttachmentService> wrapped_;
 
     DISALLOW_COPY_AND_ASSIGN(Core);
diff --git a/sync/internal_api/public/attachments/task_queue.h b/sync/internal_api/public/attachments/task_queue.h
index fd92661e..c46ce85 100644
--- a/sync/internal_api/public/attachments/task_queue.h
+++ b/sync/internal_api/public/attachments/task_queue.h
@@ -279,4 +279,4 @@
 
 }  // namespace syncer
 
-#endif  //  SYNC_INTERNAL_API_PUBLIC_ATTACHMENTS_TASK_QUEUE_H_
+#endif  // SYNC_INTERNAL_API_PUBLIC_ATTACHMENTS_TASK_QUEUE_H_
diff --git a/sync/internal_api/public/engine/model_safe_worker.h b/sync/internal_api/public/engine/model_safe_worker.h
index bd78249..ee4e9a6 100644
--- a/sync/internal_api/public/engine/model_safe_worker.h
+++ b/sync/internal_api/public/engine/model_safe_worker.h
@@ -93,8 +93,6 @@
   void WillDestroyCurrentMessageLoop() override;
 
  protected:
-  friend class base::RefCountedThreadSafe<ModelSafeWorker>;
-
   explicit ModelSafeWorker(WorkerLoopDestructionObserver* observer);
   ~ModelSafeWorker() override;
 
@@ -115,6 +113,8 @@
   void SetWorkingLoopToCurrent();
 
  private:
+  friend class base::RefCountedThreadSafe<ModelSafeWorker>;
+
   void UnregisterForLoopDestructionAsync(
       base::Callback<void(ModelSafeGroup)> unregister_done_callback);
 
diff --git a/sync/internal_api/public/http_bridge.h b/sync/internal_api/public/http_bridge.h
index 2c25b5b..85ad32e 100644
--- a/sync/internal_api/public/http_bridge.h
+++ b/sync/internal_api/public/http_bridge.h
@@ -83,14 +83,13 @@
   net::URLRequestContextGetter* GetRequestContextGetterForTest() const;
 
  protected:
-  friend class base::RefCountedThreadSafe<HttpBridge>;
-
   ~HttpBridge() override;
 
   // Protected virtual so the unit test can override to shunt network requests.
   virtual void MakeAsynchronousPost();
 
  private:
+  friend class base::RefCountedThreadSafe<HttpBridge>;
   friend class SyncHttpBridgeTest;
   friend class ::HttpBridgeTest;
 
diff --git a/sync/internal_api/public/util/immutable.h b/sync/internal_api/public/util/immutable.h
index 23ac696..e11458c 100644
--- a/sync/internal_api/public/util/immutable.h
+++ b/sync/internal_api/public/util/immutable.h
@@ -97,10 +97,11 @@
   }
 
  private:
+  friend class base::RefCountedThreadSafe<ImmutableCore<T, Traits>>;
+
   ~ImmutableCore() {
     Traits::DestroyWrapper(&wrapper_);
   }
-  friend class base::RefCountedThreadSafe<ImmutableCore<T, Traits> >;
 
   // This is semantically const, but we can't mark it a such as we
   // modify it in the constructor.
diff --git a/sync/protocol/proto_enum_conversions_unittest.cc b/sync/protocol/proto_enum_conversions_unittest.cc
index db88a8f..247d918 100644
--- a/sync/protocol/proto_enum_conversions_unittest.cc
+++ b/sync/protocol/proto_enum_conversions_unittest.cc
@@ -88,7 +88,6 @@
       GetErrorTypeString,
       sync_pb::SyncEnums::UNKNOWN,
       sync_pb::SyncEnums::ErrorType_MAX);
-
 }
 
 TEST_F(ProtoEnumConversionsTest, GetActionString) {
diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc
index 154d2f7..ddafb9c 100644
--- a/sync/protocol/proto_value_conversions.cc
+++ b/sync/protocol/proto_value_conversions.cc
@@ -6,6 +6,7 @@
 
 #include "sync/protocol/proto_value_conversions.h"
 
+#include <algorithm>
 #include <string>
 
 #include "base/base64.h"
diff --git a/sync/protocol/proto_value_conversions_unittest.cc b/sync/protocol/proto_value_conversions_unittest.cc
index 9796c68d..7c2bb95 100644
--- a/sync/protocol/proto_value_conversions_unittest.cc
+++ b/sync/protocol/proto_value_conversions_unittest.cc
@@ -6,6 +6,8 @@
 
 #include "sync/protocol/proto_value_conversions.h"
 
+#include <string>
+
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
diff --git a/sync/protocol/sync_protocol_error.h b/sync/protocol/sync_protocol_error.h
index d65fd243..38c5f189 100644
--- a/sync/protocol/sync_protocol_error.h
+++ b/sync/protocol/sync_protocol_error.h
@@ -10,7 +10,7 @@
 #include "sync/base/sync_export.h"
 #include "sync/internal_api/public/base/model_type.h"
 
-namespace syncer{
+namespace syncer {
 
 enum SyncProtocolErrorType {
   // Success case.
diff --git a/sync/sessions/data_type_tracker.cc b/sync/sessions/data_type_tracker.cc
index 8103c003..b4d7bee 100644
--- a/sync/sessions/data_type_tracker.cc
+++ b/sync/sessions/data_type_tracker.cc
@@ -4,6 +4,8 @@
 
 #include "sync/sessions/data_type_tracker.h"
 
+#include <algorithm>
+
 #include "base/logging.h"
 #include "sync/internal_api/public/base/invalidation_interface.h"
 #include "sync/sessions/nudge_tracker.h"
diff --git a/sync/sessions/data_type_tracker.h b/sync/sessions/data_type_tracker.h
index 0842197..a01d7c6 100644
--- a/sync/sessions/data_type_tracker.h
+++ b/sync/sessions/data_type_tracker.h
@@ -24,7 +24,7 @@
 // A class to track the per-type scheduling data.
 class DataTypeTracker {
  public:
-  explicit DataTypeTracker();
+  DataTypeTracker();
   ~DataTypeTracker();
 
   // For STL compatibility, we do not forbid the creation of a default copy
diff --git a/sync/sessions/directory_type_debug_info_emitter.cc b/sync/sessions/directory_type_debug_info_emitter.cc
index e1a89e8..d6b8721 100644
--- a/sync/sessions/directory_type_debug_info_emitter.cc
+++ b/sync/sessions/directory_type_debug_info_emitter.cc
@@ -4,6 +4,8 @@
 
 #include "sync/sessions/directory_type_debug_info_emitter.h"
 
+#include <vector>
+
 #include "sync/internal_api/public/sessions/status_counters.h"
 #include "sync/internal_api/public/sessions/type_debug_info_observer.h"
 #include "sync/syncable/entry.h"
diff --git a/sync/sessions/nudge_tracker.cc b/sync/sessions/nudge_tracker.cc
index bd1f20f0..023e6e6 100644
--- a/sync/sessions/nudge_tracker.cc
+++ b/sync/sessions/nudge_tracker.cc
@@ -25,22 +25,22 @@
 base::TimeDelta GetDefaultDelayForType(ModelType model_type,
                                        base::TimeDelta minimum_delay) {
   switch (model_type) {
-   case AUTOFILL:
+    case AUTOFILL:
      // Accompany types rely on nudges from other types, and hence have long
      // nudge delays.
      return base::TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds);
-   case BOOKMARKS:
-   case PREFERENCES:
+    case BOOKMARKS:
+    case PREFERENCES:
      // Types with sometimes automatic changes get longer delays to allow more
      // coalescing.
      return base::TimeDelta::FromMilliseconds(kSlowNudgeDelayMilliseconds);
-   case SESSIONS:
-   case FAVICON_IMAGES:
-   case FAVICON_TRACKING:
+    case SESSIONS:
+    case FAVICON_IMAGES:
+    case FAVICON_TRACKING:
      // Types with navigation triggered changes get longer delays to allow more
      // coalescing.
      return base::TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds);
-   default:
+    default:
      return minimum_delay;
   }
 }
diff --git a/sync/sessions/nudge_tracker_unittest.cc b/sync/sessions/nudge_tracker_unittest.cc
index db2bc3e..43577a3 100644
--- a/sync/sessions/nudge_tracker_unittest.cc
+++ b/sync/sessions/nudge_tracker_unittest.cc
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "sync/sessions/nudge_tracker.h"
+
+#include <string>
+#include <vector>
+
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "sync/internal_api/public/base/model_type_test_util.h"
-#include "sync/sessions/nudge_tracker.h"
 #include "sync/test/mock_invalidation.h"
 #include "sync/test/mock_invalidation_tracker.h"
 #include "sync/test/trackable_mock_invalidation.h"
@@ -196,7 +200,7 @@
     ASSERT_EQ(2, bm_gu_trigger.notification_hint_size());
     EXPECT_EQ("bm_hint_1", bm_gu_trigger.notification_hint(0));
     EXPECT_EQ("bm_hint_2",
-              bm_gu_trigger.notification_hint(1)); // most recent last.
+              bm_gu_trigger.notification_hint(1));  // most recent last.
     EXPECT_FALSE(bm_gu_trigger.client_dropped_hints());
 
     // Verify the new type, too.
diff --git a/sync/sessions/test_util.cc b/sync/sessions/test_util.cc
index c226a12d..2b7fa0d 100644
--- a/sync/sessions/test_util.cc
+++ b/sync/sessions/test_util.cc
@@ -4,6 +4,8 @@
 
 #include "sync/sessions/test_util.h"
 
+#include <map>
+
 namespace syncer {
 namespace sessions {
 namespace test_util {
diff --git a/sync/syncable/dir_open_result.h b/sync/syncable/dir_open_result.h
index 0df3c6c..2ba8d66 100644
--- a/sync/syncable/dir_open_result.h
+++ b/sync/syncable/dir_open_result.h
@@ -7,16 +7,17 @@
 
 namespace syncer {
 namespace syncable {
-enum DirOpenResult { NOT_INITIALIZED,
-                     OPENED,   // success.
-                     FAILED_NEWER_VERSION,  // DB version is too new.
-                     FAILED_MAKE_REPOSITORY,  // Couldn't create subdir.
-                     FAILED_OPEN_DATABASE,  // sqlite_open() failed.
-                     FAILED_DISK_FULL,  // The disk is full.
-                     FAILED_DATABASE_CORRUPT,  // Something is wrong with the DB
-                     FAILED_LOGICAL_CORRUPTION, // Invalid database contents
-                     FAILED_IN_UNITTEST, // For tests.
-                     FAILED_INITIAL_WRITE,  // Early write to DB failed.
+enum DirOpenResult {
+  NOT_INITIALIZED,
+  OPENED,                     // success.
+  FAILED_NEWER_VERSION,       // DB version is too new.
+  FAILED_MAKE_REPOSITORY,     // Couldn't create subdir.
+  FAILED_OPEN_DATABASE,       // sqlite_open() failed.
+  FAILED_DISK_FULL,           // The disk is full.
+  FAILED_DATABASE_CORRUPT,    // Something is wrong with the DB
+  FAILED_LOGICAL_CORRUPTION,  // Invalid database contents
+  FAILED_IN_UNITTEST,         // For tests.
+  FAILED_INITIAL_WRITE,       // Early write to DB failed.
 };
 }  // namespace syncable
 }  // namespace syncer
diff --git a/sync/syncable/directory_backing_store.cc b/sync/syncable/directory_backing_store.cc
index e57f246e..55c99d3 100644
--- a/sync/syncable/directory_backing_store.cc
+++ b/sync/syncable/directory_backing_store.cc
@@ -4,8 +4,6 @@
 
 #include "sync/syncable/directory_backing_store.h"
 
-#include "build/build_config.h"
-
 #include <limits>
 
 #include "base/base64.h"
@@ -16,6 +14,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
 #include "sql/connection.h"
 #include "sql/error_delegate_util.h"
 #include "sql/statement.h"
@@ -1210,8 +1209,8 @@
 }
 
 bool DirectoryBackingStore::MigrateVersion80To81() {
-  if(!db_->Execute(
-         "ALTER TABLE metas ADD COLUMN server_ordinal_in_parent BLOB"))
+  if (!db_->Execute(
+          "ALTER TABLE metas ADD COLUMN server_ordinal_in_parent BLOB"))
     return false;
 
   sql::Statement get_positions(db_->GetUniqueStatement(
@@ -1221,7 +1220,7 @@
       "UPDATE metas SET server_ordinal_in_parent = ?"
       "WHERE metahandle = ?"));
 
-  while(get_positions.Step()) {
+  while (get_positions.Step()) {
     int64 metahandle = get_positions.ColumnInt64(0);
     int64 position = get_positions.ColumnInt64(1);
 
@@ -1229,7 +1228,7 @@
     put_ordinals.BindBlob(0, ordinal.data(), ordinal.length());
     put_ordinals.BindInt64(1, metahandle);
 
-    if(!put_ordinals.Run())
+    if (!put_ordinals.Run())
       return false;
     put_ordinals.Reset(true);
   }
@@ -1390,7 +1389,7 @@
         // when we see updates for this item.  That should ensure that commonly
         // modified items will end up with the proper tag values eventually.
         unique_bookmark_tag = syncable::GenerateSyncableBookmarkHash(
-            std::string(), // cache_guid left intentionally blank.
+            std::string(),  // cache_guid left intentionally blank.
             id_string.substr(1));
       }
 
@@ -1633,7 +1632,6 @@
 bool DirectoryBackingStore::VerifyReferenceIntegrity(
     const Directory::MetahandlesMap* handles_map) {
   TRACE_EVENT0("sync", "SyncDatabaseIntegrityCheck");
-  using namespace syncable;
   typedef base::hash_set<std::string> IdsSet;
 
   IdsSet ids_set;
diff --git a/sync/syncable/directory_unittest.cc b/sync/syncable/directory_unittest.cc
index a9d8058..c5eae7549 100644
--- a/sync/syncable/directory_unittest.cc
+++ b/sync/syncable/directory_unittest.cc
@@ -700,7 +700,7 @@
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
 
     dir()->GetUnsyncedMetaHandles(&trans, &handles);
-    ASSERT_TRUE(0 == handles.size());
+    ASSERT_EQ(0u, handles.size());
 
     MutableEntry e1(&trans, CREATE, BOOKMARKS, trans.root_id(), "abba");
     ASSERT_TRUE(e1.good());
@@ -720,7 +720,7 @@
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
 
     dir()->GetUnsyncedMetaHandles(&trans, &handles);
-    ASSERT_TRUE(0 == handles.size());
+    ASSERT_EQ(0u, handles.size());
 
     MutableEntry e3(&trans, GET_BY_HANDLE, handle1);
     ASSERT_TRUE(e3.good());
@@ -730,7 +730,7 @@
   {
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
     dir()->GetUnsyncedMetaHandles(&trans, &handles);
-    ASSERT_TRUE(1 == handles.size());
+    ASSERT_EQ(1u, handles.size());
     ASSERT_TRUE(handle1 == handles[0]);
 
     MutableEntry e4(&trans, GET_BY_HANDLE, handle2);
@@ -741,7 +741,7 @@
   {
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
     dir()->GetUnsyncedMetaHandles(&trans, &handles);
-    ASSERT_TRUE(2 == handles.size());
+    ASSERT_EQ(2u, handles.size());
     if (handle1 == handles[0]) {
       ASSERT_TRUE(handle2 == handles[1]);
     } else {
@@ -759,7 +759,7 @@
   {
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
     dir()->GetUnsyncedMetaHandles(&trans, &handles);
-    ASSERT_TRUE(1 == handles.size());
+    ASSERT_EQ(1u, handles.size());
     ASSERT_TRUE(handle2 == handles[0]);
   }
 }
@@ -772,7 +772,7 @@
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
 
     dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles);
-    ASSERT_TRUE(0 == handles.size());
+    ASSERT_EQ(0u, handles.size());
 
     MutableEntry e1(&trans, CREATE, BOOKMARKS, trans.root_id(), "abba");
     ASSERT_TRUE(e1.good());
@@ -794,7 +794,7 @@
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
 
     dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles);
-    ASSERT_TRUE(0 == handles.size());
+    ASSERT_EQ(0u, handles.size());
 
     MutableEntry e3(&trans, GET_BY_HANDLE, handle1);
     ASSERT_TRUE(e3.good());
@@ -804,7 +804,7 @@
   {
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
     dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles);
-    ASSERT_TRUE(1 == handles.size());
+    ASSERT_EQ(1u, handles.size());
     ASSERT_TRUE(handle1 == handles[0]);
 
     MutableEntry e4(&trans, GET_BY_HANDLE, handle2);
@@ -815,7 +815,7 @@
   {
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
     dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles);
-    ASSERT_TRUE(2 == handles.size());
+    ASSERT_EQ(2u, handles.size());
     if (handle1 == handles[0]) {
       ASSERT_TRUE(handle2 == handles[1]);
     } else {
@@ -831,7 +831,7 @@
   {
     WriteTransaction trans(FROM_HERE, UNITTEST, dir().get());
     dir()->GetUnappliedUpdateMetaHandles(&trans, all_types, &handles);
-    ASSERT_TRUE(1 == handles.size());
+    ASSERT_EQ(1u, handles.size());
     ASSERT_TRUE(handle2 == handles[0]);
   }
 }
@@ -1668,7 +1668,7 @@
       const int rand_action = rand() % 10;
       if (rand_action < 4 && !path_name.empty()) {
         ReadTransaction trans(FROM_HERE, dir_);
-        CHECK(1 == CountEntriesWithName(&trans, trans.root_id(), path_name));
+        EXPECT_EQ(1, CountEntriesWithName(&trans, trans.root_id(), path_name));
         base::PlatformThread::Sleep(
             base::TimeDelta::FromMilliseconds(rand() % 10));
       } else {
@@ -1677,7 +1677,7 @@
         path_name.assign(unique_name.begin(), unique_name.end());
         WriteTransaction trans(FROM_HERE, UNITTEST, dir_);
         MutableEntry e(&trans, CREATE, BOOKMARKS, trans.root_id(), path_name);
-        CHECK(e.good());
+        EXPECT_TRUE(e.good());
         base::PlatformThread::Sleep(
             base::TimeDelta::FromMilliseconds(rand() % 20));
         e.PutIsUnsynced(true);
@@ -2119,7 +2119,7 @@
   // Create the root node.
   ModelNeutralMutableEntry entry(&trans, syncable::CREATE_NEW_TYPE_ROOT,
                                  PREFERENCES);
-  DCHECK(entry.good());
+  ASSERT_TRUE(entry.good());
 
   entry.PutServerIsDir(true);
   entry.PutUniqueServerTag(ModelTypeToRootTag(PREFERENCES));
diff --git a/sync/syncable/entry.h b/sync/syncable/entry.h
index 47a7815..cf9b9af 100644
--- a/sync/syncable/entry.h
+++ b/sync/syncable/entry.h
@@ -5,6 +5,9 @@
 #ifndef SYNC_SYNCABLE_ENTRY_H_
 #define SYNC_SYNCABLE_ENTRY_H_
 
+#include <string>
+#include <vector>
+
 #include "sync/base/sync_export.h"
 #include "sync/syncable/entry_kernel.h"
 
@@ -216,7 +219,7 @@
   }
 
   bool GetSyncing() const;
-  bool GetDirtySync() const ;
+  bool GetDirtySync() const;
 
   ModelType GetServerModelType() const;
   ModelType GetModelType() const;
diff --git a/sync/syncable/entry_kernel.cc b/sync/syncable/entry_kernel.cc
index 8fb611f2..ec7575b 100644
--- a/sync/syncable/entry_kernel.cc
+++ b/sync/syncable/entry_kernel.cc
@@ -287,5 +287,5 @@
   return os;
 }
 
-}  // namespace syncer
 }  // namespace syncable
+}  // namespace syncer
diff --git a/sync/syncable/metahandle_set.h b/sync/syncable/metahandle_set.h
index 5b4e425..acb5c27 100644
--- a/sync/syncable/metahandle_set.h
+++ b/sync/syncable/metahandle_set.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 SYNC_SYNCABLE_METAHANDLE_SET_
-#define SYNC_SYNCABLE_METAHANDLE_SET_
+#ifndef SYNC_SYNCABLE_METAHANDLE_SET_H_
+#define SYNC_SYNCABLE_METAHANDLE_SET_H_
 
 #include <set>
 
@@ -17,4 +17,4 @@
 }  // namespace syncable
 }  // namespace syncer
 
-#endif // SYNC_SYNCABLE_METAHANDLE_SET_
+#endif  // SYNC_SYNCABLE_METAHANDLE_SET_H_
diff --git a/sync/syncable/model_neutral_mutable_entry.cc b/sync/syncable/model_neutral_mutable_entry.cc
index 1c75b64..46486f7 100644
--- a/sync/syncable/model_neutral_mutable_entry.cc
+++ b/sync/syncable/model_neutral_mutable_entry.cc
@@ -402,7 +402,7 @@
 void ModelNeutralMutableEntry::PutServerUniquePosition(
     const UniquePosition& value) {
   DCHECK(kernel_);
-  if(!kernel_->ref(SERVER_UNIQUE_POSITION).Equals(value)) {
+  if (!kernel_->ref(SERVER_UNIQUE_POSITION).Equals(value)) {
     base_write_transaction_->TrackChangesTo(kernel_);
     // We should never overwrite a valid position with an invalid one.
     DCHECK(value.IsValid());
diff --git a/sync/syncable/mutable_entry.cc b/sync/syncable/mutable_entry.cc
index 7c42b48..978bbe7 100644
--- a/sync/syncable/mutable_entry.cc
+++ b/sync/syncable/mutable_entry.cc
@@ -237,7 +237,7 @@
 
 void MutableEntry::PutUniquePosition(const UniquePosition& value) {
   DCHECK(kernel_);
-  if(!kernel_->ref(UNIQUE_POSITION).Equals(value)) {
+  if (!kernel_->ref(UNIQUE_POSITION).Equals(value)) {
     write_transaction()->TrackChangesTo(kernel_);
     // We should never overwrite a valid position with an invalid one.
     DCHECK(value.IsValid());
diff --git a/sync/syncable/nigori_handler.cc b/sync/syncable/nigori_handler.cc
index e193c893..fd8a9a3 100644
--- a/sync/syncable/nigori_handler.cc
+++ b/sync/syncable/nigori_handler.cc
@@ -10,5 +10,5 @@
 NigoriHandler::NigoriHandler() {}
 NigoriHandler::~NigoriHandler() {}
 
-}  // namespace syncer
 }  // namespace syncable
+}  // namespace syncer
diff --git a/sync/syncable/parent_child_index_unittest.cc b/sync/syncable/parent_child_index_unittest.cc
index 26ccb521..50aeca1 100644
--- a/sync/syncable/parent_child_index_unittest.cc
+++ b/sync/syncable/parent_child_index_unittest.cc
@@ -5,6 +5,7 @@
 #include "sync/syncable/parent_child_index.h"
 
 #include <list>
+#include <string>
 
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -176,10 +177,10 @@
   EntryKernel* b4 = MakeBookmark(4, 4, false);
 
   // Insert them out-of-order to test different cases.
-  index_.Insert(b3); // Only child.
-  index_.Insert(b4); // Right-most child.
-  index_.Insert(b1); // Left-most child.
-  index_.Insert(b2); // Between existing items.
+  index_.Insert(b3);  // Only child.
+  index_.Insert(b4);  // Right-most child.
+  index_.Insert(b1);  // Left-most child.
+  index_.Insert(b2);  // Between existing items.
 
   // Double-check they've been added.
   EXPECT_TRUE(index_.Contains(b1));
diff --git a/sync/syncable/scoped_kernel_lock.h b/sync/syncable/scoped_kernel_lock.h
index c684810c..942faef 100644
--- a/sync/syncable/scoped_kernel_lock.h
+++ b/sync/syncable/scoped_kernel_lock.h
@@ -20,6 +20,8 @@
 
   base::AutoLock scoped_lock_;
   const Directory* const dir_;
+
+ private:
   DISALLOW_COPY_AND_ASSIGN(ScopedKernelLock);
 };
 
diff --git a/sync/syncable/scoped_parent_child_index_updater.cc b/sync/syncable/scoped_parent_child_index_updater.cc
index 0dc3e953..dc48edd 100644
--- a/sync/syncable/scoped_parent_child_index_updater.cc
+++ b/sync/syncable/scoped_parent_child_index_updater.cc
@@ -10,9 +10,10 @@
 namespace syncable {
 
 ScopedParentChildIndexUpdater::ScopedParentChildIndexUpdater(
-    ScopedKernelLock& proof_of_lock,
+    const ScopedKernelLock& proof_of_lock,
     EntryKernel* entry,
-    ParentChildIndex* index) : entry_(entry), index_(index) {
+    ParentChildIndex* index)
+    : entry_(entry), index_(index) {
   if (ParentChildIndex::ShouldInclude(entry_)) {
     index_->Remove(entry_);
   }
@@ -24,5 +25,5 @@
   }
 }
 
-}  // namespace syncer
 }  // namespace syncable
+}  // namespace syncer
diff --git a/sync/syncable/scoped_parent_child_index_updater.h b/sync/syncable/scoped_parent_child_index_updater.h
index 89385feb..29bda16 100644
--- a/sync/syncable/scoped_parent_child_index_updater.h
+++ b/sync/syncable/scoped_parent_child_index_updater.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 SYNC_SYNCABLE_PARENT_CHILD_INDEX_UPDATER_H_
-#define SYNC_SYNCABLE_PARENT_CHILD_INDEX_UPDATER_H_
+#ifndef SYNC_SYNCABLE_SCOPED_PARENT_CHILD_INDEX_UPDATER_H_
+#define SYNC_SYNCABLE_SCOPED_PARENT_CHILD_INDEX_UPDATER_H_
 
 #include "base/basictypes.h"
 #include "sync/base/sync_export.h"
@@ -19,7 +19,7 @@
 // object goes out of scope.
 class ScopedParentChildIndexUpdater {
  public:
-  ScopedParentChildIndexUpdater(ScopedKernelLock& proof_of_lock,
+  ScopedParentChildIndexUpdater(const ScopedKernelLock& proof_of_lock,
                                 EntryKernel* entry,
                                 ParentChildIndex* index);
   ~ScopedParentChildIndexUpdater();
@@ -31,7 +31,7 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedParentChildIndexUpdater);
 };
 
-}  // namespace syncer
 }  // namespace syncable
+}  // namespace syncer
 
-#endif  // SYNC_SYNCABLE_PARENT_CHILD_INDEX_UPDATER_H_
+#endif  // SYNC_SYNCABLE_SCOPED_PARENT_CHILD_INDEX_UPDATER_H_
diff --git a/sync/syncable/syncable_base_transaction.h b/sync/syncable/syncable_base_transaction.h
index 58c7bfa..8921623 100644
--- a/sync/syncable/syncable_base_transaction.h
+++ b/sync/syncable/syncable_base_transaction.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_SYNCABLE_SYNCABLE_BASE_TRANSACTION_H_
 #define SYNC_SYNCABLE_SYNCABLE_BASE_TRANSACTION_H_
 
+#include <string>
+
 #include "base/location.h"
 #include "sync/base/sync_export.h"
 #include "sync/syncable/syncable_id.h"
diff --git a/sync/syncable/syncable_delete_journal.h b/sync/syncable/syncable_delete_journal.h
index b475850..bba53211 100644
--- a/sync/syncable/syncable_delete_journal.h
+++ b/sync/syncable/syncable_delete_journal.h
@@ -28,8 +28,6 @@
 // method requires a non-null |trans| parameter.
 class SYNC_EXPORT DeleteJournal {
  public:
-  FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, ManageDeleteJournals);
-
   // Initialize |delete_journals_| using |intitial_journal|, whose content is
   // destroyed during initialization.
   explicit DeleteJournal(JournalIndex* initial_journal);
@@ -81,6 +79,8 @@
   static bool IsDeleteJournalEnabled(ModelType type);
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, ManageDeleteJournals);
+
   // Contains deleted entries that may not be persisted in native models. And
   // in case of unrecoverable error, all purged entries are moved here for
   // bookkeeping to prevent back-from-dead entries that are deleted elsewhere
diff --git a/sync/syncable/syncable_enum_conversions.cc b/sync/syncable/syncable_enum_conversions.cc
index fe8cd5d4..6ac1fdc 100644
--- a/sync/syncable/syncable_enum_conversions.cc
+++ b/sync/syncable/syncable_enum_conversions.cc
@@ -151,7 +151,7 @@
   ASSERT_ENUM_BOUNDS(SERVER_UNIQUE_POSITION, UNIQUE_POSITION,
                      UNIQUE_POSITION_FIELDS_BEGIN,
                      UNIQUE_POSITION_FIELDS_END - 1);
-  switch(position_field) {
+  switch (position_field) {
     ENUM_CASE(SERVER_UNIQUE_POSITION);
     ENUM_CASE(UNIQUE_POSITION);
     case UNIQUE_POSITION_FIELDS_END: break;
@@ -166,7 +166,7 @@
                      SERVER_ATTACHMENT_METADATA,
                      ATTACHMENT_METADATA_FIELDS_BEGIN,
                      ATTACHMENT_METADATA_FIELDS_END - 1);
-  switch(attachment_metadata_field) {
+  switch (attachment_metadata_field) {
     ENUM_CASE(ATTACHMENT_METADATA);
     ENUM_CASE(SERVER_ATTACHMENT_METADATA);
     case ATTACHMENT_METADATA_FIELDS_END: break;
diff --git a/sync/syncable/syncable_model_neutral_write_transaction.cc b/sync/syncable/syncable_model_neutral_write_transaction.cc
index 9aaf740..d7981d2 100644
--- a/sync/syncable/syncable_model_neutral_write_transaction.cc
+++ b/sync/syncable/syncable_model_neutral_write_transaction.cc
@@ -29,5 +29,5 @@
   modified_handles_.insert(entry->ref(META_HANDLE));
 }
 
-}  // namespace syncer
 }  // namespace syncable
+}  // namespace syncer
diff --git a/sync/syncable/syncable_read_transaction.h b/sync/syncable/syncable_read_transaction.h
index a13f92f..4ee325f 100644
--- a/sync/syncable/syncable_read_transaction.h
+++ b/sync/syncable/syncable_read_transaction.h
@@ -21,9 +21,11 @@
   ~ReadTransaction() override;
 
  protected:  // Don't allow creation on heap, except by sync API wrapper.
-  friend class syncer::ReadTransaction;
   void* operator new(size_t size) { return (::operator new)(size); }
 
+ private:
+  friend class syncer::ReadTransaction;
+
   DISALLOW_COPY_AND_ASSIGN(ReadTransaction);
 };
 
diff --git a/sync/syncable/syncable_unittest.cc b/sync/syncable/syncable_unittest.cc
index 6430aab7..c4d5443 100644
--- a/sync/syncable/syncable_unittest.cc
+++ b/sync/syncable/syncable_unittest.cc
@@ -54,12 +54,10 @@
 
   bool SaveChanges(const Directory::SaveChangesSnapshot& snapshot) override;
 
-   void StartFailingSaveChanges() {
-     fail_save_changes_ = true;
-   }
+  void StartFailingSaveChanges() { fail_save_changes_ = true; }
 
  private:
-   bool fail_save_changes_;
+  bool fail_save_changes_;
 };
 
 TestBackingStore::TestBackingStore(const std::string& dir_name,
@@ -71,7 +69,7 @@
 TestBackingStore::~TestBackingStore() { }
 
 bool TestBackingStore::SaveChanges(
-    const Directory::SaveChangesSnapshot& snapshot){
+    const Directory::SaveChangesSnapshot& snapshot) {
   if (fail_save_changes_) {
     return false;
   } else {
@@ -84,7 +82,7 @@
  public:
   // A factory function used to work around some initialization order issues.
   static TestDirectory* Create(
-      Encryptor *encryptor,
+      Encryptor* encryptor,
       const WeakHandle<UnrecoverableErrorHandler>& handler,
       const std::string& dir_name,
       const base::FilePath& backing_filepath);
@@ -104,7 +102,7 @@
 };
 
 TestDirectory* TestDirectory::Create(
-    Encryptor *encryptor,
+    Encryptor* encryptor,
     const WeakHandle<UnrecoverableErrorHandler>& handler,
     const std::string& dir_name,
     const base::FilePath& backing_filepath) {
@@ -193,7 +191,7 @@
     test_directory_->StartFailingSaveChanges();
   }
 
-  TestDirectory *test_directory_;  // mirrors scoped_ptr<Directory> dir_
+  TestDirectory* test_directory_;  // mirrors scoped_ptr<Directory> dir_
   base::ScopedTempDir temp_dir_;
   base::FilePath file_path_;
 };
diff --git a/sync/syncable/syncable_util_unittest.cc b/sync/syncable/syncable_util_unittest.cc
index 8f818f0a..c94ead6 100644
--- a/sync/syncable/syncable_util_unittest.cc
+++ b/sync/syncable/syncable_util_unittest.cc
@@ -28,5 +28,5 @@
 }
 
 }  // namespace
-}  // namespace syncer
 }  // namespace syncable
+}  // namespace syncer
diff --git a/sync/syncable/syncable_write_transaction.cc b/sync/syncable/syncable_write_transaction.cc
index 6a5557f2..1e1ac56 100644
--- a/sync/syncable/syncable_write_transaction.cc
+++ b/sync/syncable/syncable_write_transaction.cc
@@ -4,6 +4,8 @@
 
 #include "sync/syncable/syncable_write_transaction.h"
 
+#include <string>
+
 #include "sync/syncable/directory.h"
 #include "sync/syncable/directory_change_delegate.h"
 #include "sync/syncable/mutable_entry.h"
@@ -177,7 +179,7 @@
     ENUM_CASE(HANDLE_SAVE_FAILURE);
     ENUM_CASE(PURGE_ENTRIES);
     ENUM_CASE(SYNCAPI);
-  };
+  }
   NOTREACHED();
   return std::string();
 }
diff --git a/sync/syncable/syncable_write_transaction.h b/sync/syncable/syncable_write_transaction.h
index 93942c7..f85b035 100644
--- a/sync/syncable/syncable_write_transaction.h
+++ b/sync/syncable/syncable_write_transaction.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_SYNCABLE_SYNCABLE_WRITE_TRANSACTION_H_
 #define SYNC_SYNCABLE_SYNCABLE_WRITE_TRANSACTION_H_
 
+#include <vector>
+
 #include "sync/base/sync_export.h"
 #include "sync/syncable/entry_kernel.h"
 #include "sync/syncable/syncable_base_write_transaction.h"
@@ -65,4 +67,4 @@
 }  // namespace syncable
 }  // namespace syncer
 
-#endif //  SYNC_SYNCABLE_SYNCABLE_WRITE_TRANSACTION_H_
+#endif  // SYNC_SYNCABLE_SYNCABLE_WRITE_TRANSACTION_H_
diff --git a/sync/syncable/write_transaction_info.h b/sync/syncable/write_transaction_info.h
index 823a66c4..0b571d2 100644
--- a/sync/syncable/write_transaction_info.h
+++ b/sync/syncable/write_transaction_info.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_SYNCABLE_WRITE_TRANSACTION_INFO_H_
 #define SYNC_SYNCABLE_WRITE_TRANSACTION_INFO_H_
 
+#include <string>
+
 #include "sync/syncable/entry_kernel.h"
 #include "sync/syncable/syncable_base_transaction.h"
 
diff --git a/sync/test/directory_backing_store_corruption_testing.cc b/sync/test/directory_backing_store_corruption_testing.cc
index 9350369f..7418465b 100644
--- a/sync/test/directory_backing_store_corruption_testing.cc
+++ b/sync/test/directory_backing_store_corruption_testing.cc
@@ -4,6 +4,8 @@
 
 #include "sync/test/directory_backing_store_corruption_testing.h"
 
+#include <string>
+
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 
@@ -32,6 +34,6 @@
   return num_written == 1U;
 }
 
-}  // namespace corruption_util
+}  // namespace corruption_testing
 }  // namespace syncable
 }  // namespace syncer
diff --git a/sync/test/directory_backing_store_corruption_testing.h b/sync/test/directory_backing_store_corruption_testing.h
index 5897ec04..cf87422 100644
--- a/sync/test/directory_backing_store_corruption_testing.h
+++ b/sync/test/directory_backing_store_corruption_testing.h
@@ -20,7 +20,7 @@
 // Returns true if the database was successfully corrupted.
 bool CorruptDatabase(const base::FilePath& backing_file_path);
 
-}  // namespace corruption_util
+}  // namespace corruption_testing
 }  // namespace syncable
 }  // namespace syncer
 
diff --git a/sync/test/engine/fake_sync_scheduler.cc b/sync/test/engine/fake_sync_scheduler.cc
index f1667547..894c01f 100644
--- a/sync/test/engine/fake_sync_scheduler.cc
+++ b/sync/test/engine/fake_sync_scheduler.cc
@@ -48,11 +48,9 @@
 }
 
 void FakeSyncScheduler::OnCredentialsUpdated() {
-
 }
 
 void FakeSyncScheduler::OnConnectionStatusChange() {
-
 }
 
 void FakeSyncScheduler::OnThrottled(
diff --git a/sync/test/engine/fake_sync_scheduler.h b/sync/test/engine/fake_sync_scheduler.h
index 09b7d70..0fe9438 100644
--- a/sync/test/engine/fake_sync_scheduler.h
+++ b/sync/test/engine/fake_sync_scheduler.h
@@ -9,6 +9,8 @@
 #ifndef SYNC_TEST_ENGINE_FAKE_SYNC_SCHEDULER_H_
 #define SYNC_TEST_ENGINE_FAKE_SYNC_SCHEDULER_H_
 
+#include <map>
+
 #include "base/message_loop/message_loop.h"
 #include "sync/engine/sync_scheduler.h"
 
diff --git a/sync/test/engine/mock_commit_queue.cc b/sync/test/engine/mock_commit_queue.cc
index 347d40b..e3a9a122 100644
--- a/sync/test/engine/mock_commit_queue.cc
+++ b/sync/test/engine/mock_commit_queue.cc
@@ -176,4 +176,4 @@
   server_versions_[tag_hash] = version;
 }
 
-}  // namespace syncer
+}  // namespace syncer_v2
diff --git a/sync/test/engine/mock_commit_queue.h b/sync/test/engine/mock_commit_queue.h
index 25dd8f7..65a6e114 100644
--- a/sync/test/engine/mock_commit_queue.h
+++ b/sync/test/engine/mock_commit_queue.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TEST_ENGINE_MOCK_COMMIT_QUEUE_H_
 #define SYNC_TEST_ENGINE_MOCK_COMMIT_QUEUE_H_
 
+#include <map>
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
@@ -83,6 +85,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockCommitQueue);
 };
 
-}  // namespace syncer
+}  // namespace syncer_v2
 
 #endif  // SYNC_TEST_ENGINE_MOCK_COMMIT_QUEUE_H_
diff --git a/sync/test/engine/mock_model_type_processor.cc b/sync/test/engine/mock_model_type_processor.cc
index ec4e2fe..8f2f947 100644
--- a/sync/test/engine/mock_model_type_processor.cc
+++ b/sync/test/engine/mock_model_type_processor.cc
@@ -271,4 +271,4 @@
   assigned_ids_[tag_hash] = id;
 }
 
-}  // namespace syncer
+}  // namespace syncer_v2
diff --git a/sync/test/engine/mock_model_type_processor.h b/sync/test/engine/mock_model_type_processor.h
index 8efc50b..d926dfe6 100644
--- a/sync/test/engine/mock_model_type_processor.h
+++ b/sync/test/engine/mock_model_type_processor.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TEST_ENGINE_MOCK_MODEL_TYPE_PROCESSOR_H_
 #define SYNC_TEST_ENGINE_MOCK_MODEL_TYPE_PROCESSOR_H_
 
+#include <map>
+#include <string>
 #include <vector>
 
 #include "base/callback.h"
@@ -84,7 +86,6 @@
   CommitResponseData GetCommitResponse(const std::string& tag_hash) const;
 
  private:
-
   // Process a received commit response.
   //
   // Implemented as an Impl method so we can defer its execution in some cases.
@@ -136,6 +137,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockModelTypeProcessor);
 };
 
-}  // namespace syncer
+}  // namespace syncer_v2
 
 #endif  // SYNC_TEST_ENGINE_MOCK_MODEL_TYPE_PROCESSOR_H_
diff --git a/sync/test/engine/mock_update_handler.cc b/sync/test/engine/mock_update_handler.cc
index b4e1bd2..7863f60 100644
--- a/sync/test/engine/mock_update_handler.cc
+++ b/sync/test/engine/mock_update_handler.cc
@@ -4,6 +4,8 @@
 
 #include "sync/test/engine/mock_update_handler.h"
 
+#include <string>
+
 #include "sync/internal_api/public/base/model_type.h"
 
 namespace syncer {
diff --git a/sync/test/engine/single_type_mock_server.h b/sync/test/engine/single_type_mock_server.h
index 2e3684c..53ec5755 100644
--- a/sync/test/engine/single_type_mock_server.h
+++ b/sync/test/engine/single_type_mock_server.h
@@ -5,6 +5,10 @@
 #ifndef SYNC_TEST_ENGINE_SINGLE_TYPE_MOCK_SERVER_H_
 #define SYNC_TEST_ENGINE_SINGLE_TYPE_MOCK_SERVER_H_
 
+#include <map>
+#include <string>
+#include <vector>
+
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/internal_api/public/non_blocking_sync_common.h"
 
diff --git a/sync/test/engine/test_syncable_utils.cc b/sync/test/engine/test_syncable_utils.cc
index aeb4c66..a2c36f41 100644
--- a/sync/test/engine/test_syncable_utils.cc
+++ b/sync/test/engine/test_syncable_utils.cc
@@ -61,7 +61,7 @@
 Id GetOnlyEntryWithName(BaseTransaction* rtrans,
                         const syncable::Id& parent_id,
                         const string& name) {
-  CHECK(1 == CountEntriesWithName(rtrans, parent_id, name));
+  CHECK_EQ(1, CountEntriesWithName(rtrans, parent_id, name));
   return GetFirstEntryWithName(rtrans, parent_id, name);
 }
 
diff --git a/sync/test/fake_encryptor.h b/sync/test/fake_encryptor.h
index a168999..c61207a 100644
--- a/sync/test/fake_encryptor.h
+++ b/sync/test/fake_encryptor.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TEST_FAKE_ENCRYPTOR_H_
 #define SYNC_TEST_FAKE_ENCRYPTOR_H_
 
+#include <string>
+
 #include "base/compiler_specific.h"
 #include "sync/util/encryptor.h"
 
diff --git a/sync/test/fake_server/android/fake_server_helper_android.cc b/sync/test/fake_server/android/fake_server_helper_android.cc
index 434d280..919f3a6f 100644
--- a/sync/test/fake_server/android/fake_server_helper_android.cc
+++ b/sync/test/fake_server/android/fake_server_helper_android.cc
@@ -5,6 +5,8 @@
 #include "sync/test/fake_server/android/fake_server_helper_android.h"
 
 #include <jni.h>
+#include <set>
+#include <vector>
 
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
@@ -142,7 +144,7 @@
 
   sync_pb::EntitySpecifics entity_specifics;
   DeserializeEntitySpecifics(env, serialized_entity_specifics,
-                             entity_specifics);
+                             &entity_specifics);
 
   fake_server_ptr->InjectEntity(
       fake_server::UniqueClientEntity::CreateForInjection(
@@ -160,7 +162,7 @@
 
   sync_pb::EntitySpecifics entity_specifics;
   DeserializeEntitySpecifics(env, serialized_entity_specifics,
-                             entity_specifics);
+                             &entity_specifics);
 
   fake_server_ptr->ModifyEntitySpecifics(
       base::android::ConvertJavaStringToUTF8(env, id), entity_specifics);
@@ -169,14 +171,14 @@
 void FakeServerHelperAndroid::DeserializeEntitySpecifics(
     JNIEnv* env,
     jbyteArray serialized_entity_specifics,
-    sync_pb::EntitySpecifics& entity_specifics) {
+    sync_pb::EntitySpecifics* entity_specifics) {
   int specifics_bytes_length = env->GetArrayLength(serialized_entity_specifics);
   jbyte* specifics_bytes =
       env->GetByteArrayElements(serialized_entity_specifics, NULL);
   std::string specifics_string(reinterpret_cast<char *>(specifics_bytes),
                                specifics_bytes_length);
 
-  if (!entity_specifics.ParseFromString(specifics_string))
+  if (!entity_specifics->ParseFromString(specifics_string))
     NOTREACHED() << "Could not deserialize EntitySpecifics";
 }
 
diff --git a/sync/test/fake_server/android/fake_server_helper_android.h b/sync/test/fake_server/android/fake_server_helper_android.h
index 0f4ed346..497b2e02 100644
--- a/sync/test/fake_server/android/fake_server_helper_android.h
+++ b/sync/test/fake_server/android/fake_server_helper_android.h
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SYNC_TEST_FAKE_SERVER_ANDROID_FAKE_SERVER_HELPER_ANDROID
-#define SYNC_TEST_FAKE_SERVER_ANDROID_FAKE_SERVER_HELPER_ANDROID
+#ifndef SYNC_TEST_FAKE_SERVER_ANDROID_FAKE_SERVER_HELPER_ANDROID_H_
+#define SYNC_TEST_FAKE_SERVER_ANDROID_FAKE_SERVER_HELPER_ANDROID_H_
 
 #include <jni.h>
+#include <string>
 
 #include "base/android/scoped_java_ref.h"
 #include "base/basictypes.h"
@@ -139,7 +140,7 @@
   // Deserializes |serialized_entity_specifics| into |entity_specifics|.
   void DeserializeEntitySpecifics(JNIEnv* env,
                                   jbyteArray serialized_entity_specifics,
-                                  sync_pb::EntitySpecifics& entity_specifics);
+                                  sync_pb::EntitySpecifics* entity_specifics);
 
   // Creates a bookmark entity.
   scoped_ptr<fake_server::FakeServerEntity> CreateBookmarkEntity(
@@ -149,4 +150,4 @@
       jstring parent_id);
 };
 
-#endif  // SYNC_TEST_FAKE_SERVER_ANDROID_FAKE_SERVER_HELPER_ANDROID
+#endif  // SYNC_TEST_FAKE_SERVER_ANDROID_FAKE_SERVER_HELPER_ANDROID_H_
diff --git a/sync/test/fake_server/fake_server.cc b/sync/test/fake_server/fake_server.cc
index e342e62..d5e39af 100644
--- a/sync/test/fake_server/fake_server.cc
+++ b/sync/test/fake_server/fake_server.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <limits>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
diff --git a/sync/test/fake_server/fake_server_http_post_provider.h b/sync/test/fake_server/fake_server_http_post_provider.h
index 3ee4d42..b9f5e4d 100644
--- a/sync/test/fake_server/fake_server_http_post_provider.h
+++ b/sync/test/fake_server/fake_server_http_post_provider.h
@@ -41,10 +41,11 @@
       const std::string& name) const override;
 
  protected:
-  friend class base::RefCountedThreadSafe<FakeServerHttpPostProvider>;
   ~FakeServerHttpPostProvider() override;
 
  private:
+  friend class base::RefCountedThreadSafe<FakeServerHttpPostProvider>;
+
   // |fake_server_| should only be dereferenced on the same thread as
   // |fake_server_task_runner_| runs on.
   base::WeakPtr<FakeServer> fake_server_;
diff --git a/sync/test/fake_server/fake_server_verifier.cc b/sync/test/fake_server/fake_server_verifier.cc
index b968d0f..9d2e49c 100644
--- a/sync/test/fake_server/fake_server_verifier.cc
+++ b/sync/test/fake_server/fake_server_verifier.cc
@@ -4,6 +4,10 @@
 
 #include "sync/test/fake_server/fake_server_verifier.h"
 
+#include <map>
+#include <set>
+#include <vector>
+
 #include "base/json/json_writer.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
diff --git a/sync/test/fake_sync_encryption_handler.h b/sync/test/fake_sync_encryption_handler.h
index 7853947..2b9f753 100644
--- a/sync/test/fake_sync_encryption_handler.h
+++ b/sync/test/fake_sync_encryption_handler.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 SYNC_SYNCABLE_TEST_FAKE_SYNC_ENCRYPTION_HANDLER_H_
-#define SYNC_SYNCABLE_TEST_FAKE_SYNC_ENCRYPTION_HANDLER_H_
+#ifndef SYNC_TEST_FAKE_SYNC_ENCRYPTION_HANDLER_H_
+#define SYNC_TEST_FAKE_SYNC_ENCRYPTION_HANDLER_H_
 
 #include <string>
 
@@ -67,4 +67,4 @@
 
 }  // namespace syncer
 
-#endif  // SYNC_INTERNAL_API_PUBLIC_TEST_FAKE_SYNC_ENCRYPTION_HANDLER_H_
+#endif  // SYNC_TEST_FAKE_SYNC_ENCRYPTION_HANDLER_H_
diff --git a/sync/test/local_sync_test_server.cc b/sync/test/local_sync_test_server.cc
index 791fe09..e5f0a38 100644
--- a/sync/test/local_sync_test_server.cc
+++ b/sync/test/local_sync_test_server.cc
@@ -4,6 +4,8 @@
 
 #include "sync/test/local_sync_test_server.h"
 
+#include <string>
+
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/sync/test/mock_invalidation.h b/sync/test/mock_invalidation.h
index 65d1bcef..2aea01b 100644
--- a/sync/test/mock_invalidation.h
+++ b/sync/test/mock_invalidation.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TEST_MOCK_INVALIDATION_H_
 #define SYNC_TEST_MOCK_INVALIDATION_H_
 
+#include <string>
+
 #include "base/memory/scoped_ptr.h"
 #include "sync/internal_api/public/base/invalidation_interface.h"
 
diff --git a/sync/test/mock_invalidation_tracker.h b/sync/test/mock_invalidation_tracker.h
index 9f0e5bd..ee1f740 100644
--- a/sync/test/mock_invalidation_tracker.h
+++ b/sync/test/mock_invalidation_tracker.h
@@ -6,6 +6,7 @@
 #define SYNC_TEST_MOCK_INVALIDATION_TRACKER_H_
 
 #include <set>
+#include <string>
 
 #include "base/memory/scoped_ptr.h"
 #include "sync/test/trackable_mock_invalidation.h"
diff --git a/sync/test/null_directory_change_delegate.h b/sync/test/null_directory_change_delegate.h
index a37e6708..4c52f3c 100644
--- a/sync/test/null_directory_change_delegate.h
+++ b/sync/test/null_directory_change_delegate.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TEST_NULL_DIRECTORY_CHANGE_DELEGATE_H_
 #define SYNC_TEST_NULL_DIRECTORY_CHANGE_DELEGATE_H_
 
+#include <vector>
+
 #include "base/compiler_specific.h"
 #include "sync/syncable/directory_change_delegate.h"
 
diff --git a/sync/test/sessions/mock_debug_info_getter.h b/sync/test/sessions/mock_debug_info_getter.h
index 1ca833e5..85cb6f9d 100644
--- a/sync/test/sessions/mock_debug_info_getter.h
+++ b/sync/test/sessions/mock_debug_info_getter.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 SYNC_SESSIONS_MOCK_DEBUG_INFO_GETTER_H_
-#define SYNC_SESSIONS_MOCK_DEBUG_INFO_GETTER_H_
+#ifndef SYNC_TEST_SESSIONS_MOCK_DEBUG_INFO_GETTER_H_
+#define SYNC_TEST_SESSIONS_MOCK_DEBUG_INFO_GETTER_H_
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
@@ -36,4 +36,4 @@
 }  // namespace sessions
 }  // namespace syncer
 
-#endif  // SYNC_SESSIONS_MOCK_DEBUG_INFO_GETTER_H_
+#endif  // SYNC_TEST_SESSIONS_MOCK_DEBUG_INFO_GETTER_H_
diff --git a/sync/test/test_directory_backing_store.h b/sync/test/test_directory_backing_store.h
index 53f89e56..013cbfa 100644
--- a/sync/test/test_directory_backing_store.h
+++ b/sync/test/test_directory_backing_store.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TEST_TEST_DIRECTORY_BACKING_STORE_H_
 #define SYNC_TEST_TEST_DIRECTORY_BACKING_STORE_H_
 
+#include <string>
+
 #include "base/gtest_prod_util.h"
 #include "sync/syncable/directory_backing_store.h"
 
diff --git a/sync/test/test_transaction_observer.h b/sync/test/test_transaction_observer.h
index b341d1e..005479e9e 100644
--- a/sync/test/test_transaction_observer.h
+++ b/sync/test/test_transaction_observer.h
@@ -5,6 +5,7 @@
 #ifndef SYNC_TEST_TEST_TRANSACTION_OBSERVER_H_
 #define SYNC_TEST_TEST_TRANSACTION_OBSERVER_H_
 
+#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/syncable/transaction_observer.h"
@@ -33,9 +34,9 @@
   int transactions_observed();
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(TestTransactionObserver);
-
   int transactions_observed_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestTransactionObserver);
 };
 
 }  // namespace syncable
diff --git a/sync/test/trackable_mock_invalidation.h b/sync/test/trackable_mock_invalidation.h
index 758ff08..832088980 100644
--- a/sync/test/trackable_mock_invalidation.h
+++ b/sync/test/trackable_mock_invalidation.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TEST_TRACKABLE_MOCK_INVALIDATION_H_
 #define SYNC_TEST_TRACKABLE_MOCK_INVALIDATION_H_
 
+#include <string>
+
 #include "sync/test/mock_invalidation.h"
 
 namespace syncer {
diff --git a/sync/tools/null_invalidation_state_tracker.h b/sync/tools/null_invalidation_state_tracker.h
index c444fd36..5525b8e 100644
--- a/sync/tools/null_invalidation_state_tracker.h
+++ b/sync/tools/null_invalidation_state_tracker.h
@@ -5,6 +5,8 @@
 #ifndef SYNC_TOOLS_NULL_INVALIDATION_STATE_TRACKER_H_
 #define SYNC_TOOLS_NULL_INVALIDATION_STATE_TRACKER_H_
 
+#include <string>
+
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "components/invalidation/impl/invalidation_state_tracker.h"
diff --git a/sync/tools/sync_listen_notifications.cc b/sync/tools/sync_listen_notifications.cc
index 1903f7fc..5c8db574 100644
--- a/sync/tools/sync_listen_notifications.cc
+++ b/sync/tools/sync_listen_notifications.cc
@@ -136,7 +136,6 @@
 }
 
 int SyncListenNotificationsMain(int argc, char* argv[]) {
-  using namespace syncer;
 #if defined(OS_MACOSX)
   base::mac::ScopedNSAutoreleasePool pool;
 #endif
diff --git a/sync/tools/testserver/run_sync_testserver.cc b/sync/tools/testserver/run_sync_testserver.cc
index 3ae89fc..414076a 100644
--- a/sync/tools/testserver/run_sync_testserver.cc
+++ b/sync/tools/testserver/run_sync_testserver.cc
@@ -25,7 +25,7 @@
     const base::FilePath::StringType& sync_test_script_name) {
   scoped_ptr<syncer::LocalSyncTestServer> test_server(
       new syncer::LocalSyncTestServer());
- if (!test_server->SetPythonPath()) {
+  if (!test_server->SetPythonPath()) {
     LOG(ERROR) << "Error trying to set python path. Exiting.";
     return false;
   }
diff --git a/sync/util/get_session_name_win.cc b/sync/util/get_session_name_win.cc
index 58980a3a..80df90b 100644
--- a/sync/util/get_session_name_win.cc
+++ b/sync/util/get_session_name_win.cc
@@ -4,12 +4,12 @@
 
 #include "sync/util/get_session_name_win.h"
 
+#include <windows.h>
+
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 
-#include <windows.h>
-
 namespace syncer {
 namespace internal {
 
diff --git a/sync/util/nigori.cc b/sync/util/nigori.cc
index 7a9702de..225e0744 100644
--- a/sync/util/nigori.cc
+++ b/sync/util/nigori.cc
@@ -31,7 +31,8 @@
   // followed by |value| itself to the stream.
   NigoriStream& operator<<(const std::string& value) {
     uint32 size = base::HostToNet32(value.size());
-    stream_.write((char *) &size, sizeof(uint32));
+
+    stream_.write(reinterpret_cast<char*>(&size), sizeof(uint32));
     stream_ << value;
     return *this;
   }
@@ -41,9 +42,9 @@
   // bits, to the stream.
   NigoriStream& operator<<(const Nigori::Type type) {
     uint32 size = base::HostToNet32(sizeof(uint32));
-    stream_.write((char *) &size, sizeof(uint32));
+    stream_.write(reinterpret_cast<char*>(&size), sizeof(uint32));
     uint32 value = base::HostToNet32(type);
-    stream_.write((char *) &value, sizeof(uint32));
+    stream_.write(reinterpret_cast<char*>(&value), sizeof(uint32));
     return *this;
   }
 
diff --git a/sync/util/nigori.h b/sync/util/nigori.h
index cd67bf9..40e9692 100644
--- a/sync/util/nigori.h
+++ b/sync/util/nigori.h
@@ -24,7 +24,7 @@
 // for your secret (basically a map key), and |Encrypt| and |Decrypt| to store
 // and retrieve the secret.
 //
-// TODO: Link to doc.
+// https://www.cl.cam.ac.uk/~drt24/nigori/nigori-overview.pdf
 class SYNC_EXPORT Nigori {
  public:
   enum Type {
diff --git a/sync/util/test_unrecoverable_error_handler.h b/sync/util/test_unrecoverable_error_handler.h
index 1546783..ec045067 100644
--- a/sync/util/test_unrecoverable_error_handler.h
+++ b/sync/util/test_unrecoverable_error_handler.h
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SYNC_INTERNAL_API_INCLUDES_TEST_UNRECOVERABLE_ERROR_HANDLER_H_
-#define SYNC_INTERNAL_API_INCLUDES_TEST_UNRECOVERABLE_ERROR_HANDLER_H_
+#ifndef SYNC_UTIL_TEST_UNRECOVERABLE_ERROR_HANDLER_H_
+#define SYNC_UTIL_TEST_UNRECOVERABLE_ERROR_HANDLER_H_
+
+#include <string>
 
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
@@ -29,5 +31,4 @@
 
 }  // namespace syncer
 
-#endif  // SYNC_INTERNAL_API_INCLUDES_TEST_UNRECOVERABLE_ERROR_HANDLER_H_
-
+#endif  // SYNC_UTIL_TEST_UNRECOVERABLE_ERROR_HANDLER_H_
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index d0bc091..0b38d605 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -317,7 +317,7 @@
     "type": "unknown",
   },
   "nacl_loader_unittests": {
-    "label": "//components/nacl:nacl_loader_unittests",
+    "label": "//components/nacl/loader:nacl_loader_unittests",
     "type": "raw",
     "args": [],
   },
diff --git a/testing/chromoting/browser_tests_launcher.py b/testing/chromoting/browser_tests_launcher.py
index bb222b7..0b549f3 100644
--- a/testing/chromoting/browser_tests_launcher.py
+++ b/testing/chromoting/browser_tests_launcher.py
@@ -8,6 +8,7 @@
 import time
 
 from chromoting_test_utilities import CleanupUserProfileDir
+from chromoting_test_utilities import GetJidFromHostLog
 from chromoting_test_utilities import GetJidListFromTestResults
 from chromoting_test_utilities import InitialiseTestMachineForLinux
 from chromoting_test_utilities import PrintHostLogContents
@@ -55,15 +56,7 @@
     else:
       host_log_file_names.append(TestCaseSetup(args))
       # Parse the me2me host log to obtain the JID that the host registered.
-      host_jid = None
-      with open(host_log_file_names[retries], 'r') as host_log_file:
-        for line in host_log_file:
-          # The host JID will be recorded in a line saying 'Signaling
-          # connected'.
-          if 'Signaling connected. ' in line:
-            components = line.split('/')
-            host_jid = components[-1]
-            break
+      host_jid = GetJidFromHostLog(host_log_file_names[retries])
 
     results = RunCommandInSubProcess(command)
 
diff --git a/testing/chromoting/chromoting_test_driver_launcher.py b/testing/chromoting/chromoting_test_driver_launcher.py
index 66058e7..186adb9 100644
--- a/testing/chromoting/chromoting_test_driver_launcher.py
+++ b/testing/chromoting/chromoting_test_driver_launcher.py
@@ -6,6 +6,7 @@
 
 import argparse
 
+from chromoting_test_utilities import GetJidFromHostLog
 from chromoting_test_utilities import InitialiseTestMachineForLinux
 from chromoting_test_utilities import PrintHostLogContents
 from chromoting_test_utilities import PROD_DIR_ID
@@ -31,6 +32,18 @@
   host_log_file_names = []
 
   host_log_file_names.append(TestCaseSetup(args))
+  # Parse the me2me host log to obtain the JID that the host registered.
+  host_jid = GetJidFromHostLog(host_log_file_names[-1])
+
+  if not host_jid:
+    # Host-JID not found in log. Let's not attempt to run this test.
+    print 'Host-JID not found in log %s.' % host_log_file_names[-1]
+    return '[Command failed]: %s, %s' % (command, host_log_file_names)
+
+  # In order to ensure the host is online with the expected JID, pass in the
+  # jid obtained from the host-log as a command-line parameter.
+  command = command.replace('\n', '') + ' --hostjid=%s' % host_jid
+
   results = RunCommandInSubProcess(command)
 
   tear_down_index = results.find(TEST_ENVIRONMENT_TEAR_DOWN_INDICATOR)
diff --git a/testing/chromoting/chromoting_test_utilities.py b/testing/chromoting/chromoting_test_utilities.py
index bcc84d07..9d2d7a2 100644
--- a/testing/chromoting/chromoting_test_utilities.py
+++ b/testing/chromoting/chromoting_test_utilities.py
@@ -46,6 +46,7 @@
 
   cmd_line = [command]
   try:
+    print 'Going to run:\n%s' % command
     results = subprocess.check_output(cmd_line, stderr=subprocess.STDOUT,
                                       shell=True)
   except subprocess.CalledProcessError, e:
@@ -225,7 +226,7 @@
   """
 
   # Reg-ex defining the JID information in the string being parsed.
-  jid_re = '(Connecting to .*.gserviceaccount.com/)(chromoting.*)(. Local.*)'
+  jid_re = '(Connecting to )(.*.gserviceaccount.com/chromoting.*)(. Local.*)'
   jids_used = []
   for line in results.split('\n'):
     match = re.search(jid_re, line)
@@ -235,3 +236,25 @@
         jids_used.append(jid_used)
 
   return jids_used
+
+
+def GetJidFromHostLog(host_log_file):
+  """Parse the me2me host log to obtain the JID that the host registered.
+
+  Args:
+    host_log_file: path to host-log file that should be parsed for a JID.
+
+  Returns:
+    host_jid: host-JID if found in host-log, else None
+  """
+  host_jid = None
+  with open(host_log_file, 'r') as log_file:
+    for line in log_file:
+      # The host JID will be recorded in a line saying 'Signaling
+      # connected'.
+      if 'Signaling connected. ' in line:
+        components = line.split(':')
+        host_jid = components[-1].lstrip()
+        break
+
+  return host_jid
diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni
new file mode 100644
index 0000000..db5e4386
--- /dev/null
+++ b/testing/libfuzzer/fuzzer_test.gni
@@ -0,0 +1,83 @@
+# Copyright 2015 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("//testing/test.gni")
+
+# fuzzer_test is used to define individual libfuzzer tests.
+#
+# Supported attributes:
+# - (required) sources - fuzzer test source files
+# - data - test data files.
+# - deps - test dependencies
+# - additional_configs - additional configs to be used for compilation
+# - dict - a dictionary file for the fuzzer.
+#
+# The template wraps test() target with appropriate dependencies.
+# If any test run-time options are present (dict), then a launcher
+# file would be generated with <fuzzer_name>.sh name in root output
+# dir (next to test).
+template("fuzzer_test") {
+  assert(defined(invoker.sources), "Need sources in $target_name.")
+
+  test_deps = [ "//testing/libfuzzer:libfuzzer_main" ]
+
+  if (defined(invoker.deps)) {
+    test_deps += invoker.deps
+  }
+
+  test_data = []
+  if (defined(invoker.data)) {
+    test_data += invoker.data
+  }
+
+  if (defined(invoker.dict)) {
+    fuzzer_name = target_name
+    launcher_name = target_name + ".sh"
+    generated_script = "$root_build_dir/$launcher_name"
+
+    # Copy dictionary to output
+    copy(target_name + "_dict_copy") {
+      sources = [
+        invoker.dict,
+      ]
+      outputs = [
+        "$target_out_dir/{{source_file_part}}",
+      ]
+    }
+
+    # Generate test launcher
+    action(launcher_name) {
+      script = "//testing/libfuzzer/gen_fuzzer_runner.py"
+      args = [
+        "--fuzzer",
+        fuzzer_name,
+        "--launcher",
+        rebase_path(generated_script, root_build_dir),
+        "--dict",
+        rebase_path("$target_out_dir/" + invoker.dict, root_build_dir),
+      ]
+      outputs = [
+        generated_script,
+      ]
+    }
+    test_deps += [
+      ":$launcher_name",
+      ":" + fuzzer_name + "_dict_copy",
+    ]
+    test_data += [
+      invoker.dict,
+      ":$launcher_name",
+    ]
+  }
+
+  test(target_name) {
+    forward_variables_from(invoker, [ "sources" ])
+    deps = test_deps
+    data = test_data
+
+    if (defined(invoker.additional_configs)) {
+      configs += invoker.additional_configs
+    }
+  }
+}
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index c708a45..7e5acae 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -5,52 +5,48 @@
 # Individual libfuzzer tests that didn't find their home yet.
 
 import("//build/config/features.gni")
-import("//testing/test.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
 
-test("brotli_fuzzer") {
+fuzzer_test("brotli_fuzzer") {
   sources = [
     "brotli_fuzzer.cc",
   ]
   deps = [
-    "//testing/libfuzzer:libfuzzer_main",
     "//third_party/brotli:brotli",
   ]
 }
 
-test("courgette_fuzzer") {
+fuzzer_test("courgette_fuzzer") {
   sources = [
     "courgette_fuzzer.cc",
   ]
   deps = [
     "//base",
     "//courgette:courgette_lib",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("dns_record_fuzzer") {
+fuzzer_test("dns_record_fuzzer") {
   sources = [
     "dns_record_fuzzer.cc",
   ]
   deps = [
     "//base",
     "//net",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("ftp_ctrl_response_fuzzer") {
+fuzzer_test("ftp_ctrl_response_fuzzer") {
   sources = [
     "ftp_ctrl_response_fuzzer.cc",
   ]
   deps = [
     "//base",
     "//net",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("ftp_directory_listing_fuzzer") {
+fuzzer_test("ftp_directory_listing_fuzzer") {
   sources = [
     "ftp_directory_listing_fuzzer.cc",
   ]
@@ -58,136 +54,123 @@
     "//base",
     "//base:i18n",
     "//net",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("language_detection_fuzzer") {
+fuzzer_test("language_detection_fuzzer") {
   sources = [
     "language_detection_fuzzer.cc",
   ]
   deps = [
     "//base",
     "//components/translate/core/language_detection:language_detection",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
 if (proprietary_codecs) {
-  test("mp4_box_reader_fuzzer") {
+  fuzzer_test("mp4_box_reader_fuzzer") {
     sources = [
       "mp4_box_reader_fuzzer.cc",
     ]
     deps = [
       "//base",
       "//media",
-      "//testing/libfuzzer:libfuzzer_main",
     ]
   }
 
-  test("es_parser_adts_fuzzer") {
+  fuzzer_test("es_parser_adts_fuzzer") {
     sources = [
       "es_parser_adts_fuzzer.cc",
     ]
     deps = [
       "//base",
       "//media",
-      "//testing/libfuzzer:libfuzzer_main",
     ]
   }
 
-  test("es_parser_h264_fuzzer") {
+  fuzzer_test("es_parser_h264_fuzzer") {
     sources = [
       "es_parser_h264_fuzzer.cc",
     ]
     deps = [
       "//base",
       "//media",
-      "//testing/libfuzzer:libfuzzer_main",
     ]
   }
 
-  test("es_parser_mpeg1audio_fuzzer") {
+  fuzzer_test("es_parser_mpeg1audio_fuzzer") {
     sources = [
       "es_parser_mpeg1audio_fuzzer.cc",
     ]
     deps = [
       "//base",
       "//media",
-      "//testing/libfuzzer:libfuzzer_main",
     ]
   }
 }
 
-test("snappy_fuzzer") {
+fuzzer_test("snappy_fuzzer") {
   sources = [
     "snappy_fuzzer.cc",
   ]
   deps = [
-    "//testing/libfuzzer:libfuzzer_main",
     "//third_party/snappy:snappy",
   ]
 }
 
-test("string_tokenizer_fuzzer") {
+fuzzer_test("string_tokenizer_fuzzer") {
   sources = [
     "string_tokenizer_fuzzer.cc",
   ]
   deps = [
     "//base",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("string_to_int_fuzzer") {
+fuzzer_test("string_to_int_fuzzer") {
   sources = [
     "string_to_int_fuzzer.cc",
   ]
   deps = [
     "//base",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("unescape_url_component_fuzzer") {
+fuzzer_test("unescape_url_component_fuzzer") {
   sources = [
     "unescape_url_component_fuzzer.cc",
   ]
   deps = [
     "//base",
     "//net",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("url_parse_fuzzer") {
+fuzzer_test("url_parse_fuzzer") {
   sources = [
     "url_parse_fuzzer.cc",
   ]
   deps = [
     "//base",
     "//base:i18n",
-    "//testing/libfuzzer:libfuzzer_main",
     "//url:url",
   ]
 }
 
-test("vp9_parser_fuzzer") {
+fuzzer_test("vp9_parser_fuzzer") {
   sources = [
     "vp9_parser_fuzzer.cc",
   ]
   deps = [
     "//media",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("v8_json_parser_fuzzer") {
+fuzzer_test("v8_json_parser_fuzzer") {
   sources = [
     "v8_json_parser_fuzzer.cc",
   ]
   deps = [
-    "//testing/libfuzzer:libfuzzer_main",
     "//v8",
     "//v8:v8_libplatform",
   ]
@@ -197,69 +180,65 @@
   ]
 }
 
-test("base_json_reader_fuzzer") {
+fuzzer_test("base_json_reader_fuzzer") {
   sources = [
     "base_json_reader_fuzzer.cc",
   ]
   deps = [
     "//base",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("gfx_png_image_fuzzer") {
+fuzzer_test("gfx_png_image_fuzzer") {
   sources = [
     "gfx_png_image_fuzzer.cc",
   ]
   deps = [
     "//base",
-    "//testing/libfuzzer:libfuzzer_main",
     "//ui/gfx",
   ]
 }
 
-test("zlib_uncompress_fuzzer") {
+fuzzer_test("zlib_uncompress_fuzzer") {
   sources = [
     "zlib_uncompress_fuzzer.cc",
   ]
   deps = [
-    "//testing/libfuzzer:libfuzzer_main",
     "//third_party/zlib",
   ]
 }
 
-test("pdfium_fuzzer") {
+fuzzer_test("pdfium_fuzzer") {
   sources = [
     "pdfium_fuzzer.cc",
   ]
   deps = [
-    "//testing/libfuzzer:libfuzzer_main",
     "//third_party/pdfium",
     "//third_party/pdfium:test_support",
     "//v8",
     "//v8:v8_libplatform",
   ]
-  configs += [ "//third_party/pdfium:pdfium_config" ]
-  configs += [ "//v8:external_startup_data" ]
+  additional_configs = [
+    "//third_party/pdfium:pdfium_config",
+    "//v8:external_startup_data",
+  ]
 }
 
-test("websocket_frame_parser_fuzzer") {
+fuzzer_test("websocket_frame_parser_fuzzer") {
   sources = [
     "websocket_frame_parser_fuzzer.cc",
   ]
   deps = [
     "//net",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
-test("http_chunked_decoder_fuzzer") {
+fuzzer_test("http_chunked_decoder_fuzzer") {
   sources = [
     "http_chunked_decoder_fuzzer.cc",
   ]
   deps = [
     "//net",
-    "//testing/libfuzzer:libfuzzer_main",
   ]
 }
 
diff --git a/testing/libfuzzer/gen_fuzzer_runner.py b/testing/libfuzzer/gen_fuzzer_runner.py
new file mode 100755
index 0000000..516bd64
--- /dev/null
+++ b/testing/libfuzzer/gen_fuzzer_runner.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2015 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.
+
+"""Generate .sh runner for libfuzzer test.
+
+Invoked by GN from fuzzer_test.gni.
+"""
+
+import argparse
+import os
+import sys
+
+
+parser = argparse.ArgumentParser(description="Generate fuzzer launcher.")
+parser.add_argument('--fuzzer', required=True)
+parser.add_argument('--launcher', required=True)
+parser.add_argument('--dict', required=True)
+args = parser.parse_args()
+
+out = open(args.launcher, 'w')
+out.write("""#!/bin/bash
+set -ue
+DIR=$(dirname $0)
+$DIR/%(fuzzer)s -dict=$DIR/%(dict)s $*
+""" % { "fuzzer": args.fuzzer, "dict": args.dict })
+out.close()
+
+os.chmod(args.launcher, os.stat(args.launcher).st_mode | 0o111) # chmod a+x
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index bbd3874b..2503c8f 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -187,6 +187,7 @@
 crbug.com/445100 fast/block/float/marquee-shrink-to-avoid-floats.html [ Failure Pass ]
 crbug.com/469657 fast/events/mouse-event-buttons-attribute.html [ Failure Pass ]
 crbug.com/469657 virtual/pointerevent/fast/events/mouse-event-buttons-attribute.html [ Failure Pass ]
+crbug.com/469657 virtual/trustedeventsdefaultaction/fast/events/mouse-event-buttons-attribute.html [ Failure Pass ]
 
 crbug.com/548226 [ Win ] fast/events/pointerevents/mouse-pointer-event-properties.html [ Failure Pass ]
 crbug.com/548226 [ Win ] virtual/pointerevent/fast/events/pointerevents/mouse-pointer-event-properties.html [ Failure Pass ]
@@ -1219,6 +1220,7 @@
 
 crbug.com/527270 accessibility/name-calc-img.html [ Failure Pass Timeout ]
 
+
 # This test has different results in Debug and Release.
 crbug.com/529038 [ Debug ] virtual/gpu/fast/canvas/canvas-composite-repaint-by-all-imagesource.html [ Failure ]
 
@@ -1298,3 +1300,9 @@
 
 crbug.com/568867 [ Win7 Debug ] transforms/3d/point-mapping/3d-point-mapping-deep.html [ Failure ]
 crbug.com/568867 [ Win7 Debug ] transforms/3d/point-mapping/3d-point-mapping-preserve-3d.html [ Failure ]
+
+crbug.com/569514 inspector/sources/debugger-step/debugger-step-into-document-write.html [ NeedsManualRebaseline ]
+crbug.com/569514 inspector/sources/debugger-step/debugger-step-into-inlined-scripts.html [ NeedsManualRebaseline ]
+crbug.com/569514 inspector/sources/debugger-step/debugger-step-over-document-write.html [ NeedsManualRebaseline ]
+crbug.com/569514 inspector/sources/debugger-step/debugger-step-over-inlined-scripts.html [ NeedsManualRebaseline ]
+crbug.com/569514 inspector/sources/debugger/debugger-scripts.html [ NeedsManualRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/fixed-descendants-of-overflow-hidden-stacking-contexts-expected.html b/third_party/WebKit/LayoutTests/compositing/overflow/fixed-descendants-of-overflow-hidden-stacking-contexts-expected.html
deleted file mode 100644
index 30b3880..0000000
--- a/third_party/WebKit/LayoutTests/compositing/overflow/fixed-descendants-of-overflow-hidden-stacking-contexts-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-#hidden {
-    overflow: hidden;
-    position: relative;
-    z-index: 1;
-    width: 1px;
-    height: 1px;
-}
-
-#fixed-inner {
-    position: fixed;
-    width: 100px;
-    height: 100px;
-    background: green;
-}
-</style>
-<div id="hidden">
-    <div id="fixed-inner"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/fixed-descendants-of-overflow-hidden-stacking-contexts.html b/third_party/WebKit/LayoutTests/compositing/overflow/fixed-descendants-of-overflow-hidden-stacking-contexts.html
deleted file mode 100644
index 8fef70c..0000000
--- a/third_party/WebKit/LayoutTests/compositing/overflow/fixed-descendants-of-overflow-hidden-stacking-contexts.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE HTML>
-<!--
-  This test creates div with hidden overflow that is also a stacking context.
-  The fixed position element that is a descendant of this div should not be
-  clipped by it.
-
-  This test is working if you can see a 100px by 100px green box. If it fails,
-  you will see a single green pixel.
--->
-<style>
-#hidden {
-    overflow: hidden;
-    position: relative;
-    z-index: 1;
-    width: 1px;
-    height: 1px;
-}
-
-#fixed-inner {
-    position: fixed;
-    width: 100px;
-    height: 100px;
-    background: green;
-    will-change: transform;
-}
-</style>
-<div id="hidden">
-    <div id="fixed-inner"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/css3/filters/feoffset-region-zoom-expected.html b/third_party/WebKit/LayoutTests/css3/filters/feoffset-region-zoom-expected.html
index 9115dad..1f9e79f 100644
--- a/third_party/WebKit/LayoutTests/css3/filters/feoffset-region-zoom-expected.html
+++ b/third_party/WebKit/LayoutTests/css3/filters/feoffset-region-zoom-expected.html
@@ -1,7 +1,7 @@
 <body style="margin: 0px;">
 <div style="zoom: 2; margin: 30px;">
   <div style="background: blue; filter: url(#offset-flood); -webkit-filter: url(#offset-flood); width:200px; height:100px;" src="resources/reference.png">
-    <div style="position: absolute; left:200px; top:30px; width:30px; height:40px; background:green;"/>
+    <div style="position: absolute; left:200px; top:20px; width:50px; height:50px; background:green;"/>
   </div>
 </div>
 </body>
diff --git a/third_party/WebKit/LayoutTests/cssom/cssXGetComputedStyle-deprecated-expected.txt b/third_party/WebKit/LayoutTests/cssom/cssXGetComputedStyle-deprecated-expected.txt
new file mode 100644
index 0000000..9b2674d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/cssom/cssXGetComputedStyle-deprecated-expected.txt
@@ -0,0 +1,2 @@
+CONSOLE WARNING: 'getComputedStyle(e).cssXx' (except .cssFloat) is deprecated and will be removed in M50, around April 2016. Please use 'getComputedStyle(e).xx' instead.
+[auto]
diff --git a/third_party/WebKit/LayoutTests/cssom/cssXGetComputedStyle-deprecated.html b/third_party/WebKit/LayoutTests/cssom/cssXGetComputedStyle-deprecated.html
new file mode 100644
index 0000000..c03d081
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/cssom/cssXGetComputedStyle-deprecated.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<div id="d"></div>
+<script>
+if (window.testRunner)
+     testRunner.dumpAsText();
+d.innerHTML = "[" + getComputedStyle(d).cssLeft + "]";
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-constructor-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-constructor-expected.txt
new file mode 100644
index 0000000..aaea896
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-constructor-expected.txt
@@ -0,0 +1,13 @@
+Tests that the constructor of the OffScreenCanvas can be called on the main thread
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS aCanvas.width is 50
+PASS aCanvas.height is 50
+PASS aCanvas.width is 100
+PASS aCanvas.height is 100
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-constructor.html b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-constructor.html
new file mode 100644
index 0000000..119a9f5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-constructor.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script src="../../resources/js-test.js"></script>
+<script>
+description("Tests that the constructor of the OffScreenCanvas can be called on the main thread");
+
+var aCanvas = new OffScreenCanvas(50, 50);
+shouldBe("aCanvas.width", "50");
+shouldBe("aCanvas.height", "50");
+
+aCanvas.width = 100;
+aCanvas.height = 100;
+shouldBe("aCanvas.width", "100");
+shouldBe("aCanvas.height", "100");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-invalid-args-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-invalid-args-expected.txt
new file mode 100644
index 0000000..9b251fc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-invalid-args-expected.txt
@@ -0,0 +1,23 @@
+Tests that the OffScreenCanvas can handle invalid arguments
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS canvas1.width is setWidth-1
+PASS canvas1.height is setHeight-1
+PASS canvas1.width is 0
+PASS canvas1.height is 0
+PASS new OffScreenCanvas(-1, -1) threw exception TypeError: Failed to construct 'OffScreenCanvas': Value is outside the 'unsigned long' value range..
+PASS canvas2.width is 0
+PASS canvas2.height is 0
+PASS canvas2.width is setWidth-1
+PASS canvas2.height is setHeight-1
+PASS canvas2.width = -1 threw exception TypeError: Failed to set the 'width' property on 'OffScreenCanvas': Value is outside the 'unsigned long' value range..
+PASS canvas2.height = -1 threw exception TypeError: Failed to set the 'height' property on 'OffScreenCanvas': Value is outside the 'unsigned long' value range..
+PASS canvas2.width = obj threw exception TypeError: Failed to set the 'width' property on 'OffScreenCanvas': Value is not of type 'unsigned long'..
+PASS canvas2.height = obj threw exception TypeError: Failed to set the 'height' property on 'OffScreenCanvas': Value is not of type 'unsigned long'..
+PASS new OffScreenCanvas(obj, obj) threw exception TypeError: Failed to construct 'OffScreenCanvas': Value is not of type 'unsigned long'..
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-invalid-args.html b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-invalid-args.html
new file mode 100644
index 0000000..9ce02a7c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/OffScreenCanvas-invalid-args.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<script src="../../resources/js-test.js"></script>
+<script>
+description("Tests that the OffScreenCanvas can handle invalid arguments");
+
+// Since blink uses signed int internally, this case tests how the constructor
+// responds to the arguments that are larger than INT_MAX which would cause
+// overflow. The current implementation is expected to clamp.
+var setWidth = Math.pow(2, 31);
+var setHeight = Math.pow(2, 31);
+var obj = {Name: "John Doe", Age: 30};
+
+var canvas1 = new OffScreenCanvas(setWidth, setHeight);
+shouldBe("canvas1.width", "setWidth-1");
+shouldBe("canvas1.height", "setHeight-1");
+
+canvas1.width = null;
+canvas1.height = null;
+shouldBe("canvas1.width", "0");
+shouldBe("canvas1.height", "0");
+
+shouldThrow("new OffScreenCanvas(-1, -1)");
+
+var canvas2 = new OffScreenCanvas(null, null);
+shouldBe("canvas2.width", "0");
+shouldBe("canvas2.height", "0");
+
+canvas2.width = setWidth;
+canvas2.height = setHeight;
+shouldBe("canvas2.width", "setWidth-1");
+shouldBe("canvas2.height", "setHeight-1");
+
+shouldThrow("canvas2.width = -1");
+shouldThrow("canvas2.height = -1");
+
+shouldThrow("canvas2.width = obj");
+shouldThrow("canvas2.height = obj");
+
+shouldThrow("new OffScreenCanvas(obj, obj)");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-properties-case-sensitive-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-properties-case-sensitive-expected.txt
index ce1b05df7c..2d8853a 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-properties-case-sensitive-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-properties-case-sensitive-expected.txt
@@ -1,19 +1,20 @@
-This test checks that access to CSS properties via JavaScript properties on DOM elements is case sensitive.
+CONSOLE WARNING: 'getComputedStyle(e).cssXx' (except .cssFloat) is deprecated and will be removed in M50, around April 2016. Please use 'getComputedStyle(e).xx' instead.
+This test checks that access to the CSS float property via JavaScript properties on DOM elements is case sensitive. The use of .CssFloat is deprecated and will be removed in M50.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
 normal cases
 
-PASS element.style.zIndex is '1'
-PASS element.style.ZIndex is undefined.
+PASS element.style.float is 'left'
+PASS element.style.Float is undefined.
 
 "css" prefix
 
-PASS element.style.cssZIndex is '1'
-PASS element.style.CssZIndex is '1'
-PASS element.style.CsszIndex is undefined.
-PASS element.style.csszIndex is undefined.
+PASS element.style.cssFloat is 'left'
+PASS element.style.CssFloat is 'left'
+PASS element.style.Cssfloat is undefined.
+PASS element.style.cssfloat is undefined.
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-style-declaration-named-getter-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-style-declaration-named-getter-expected.txt
index 16c2f68..9218ef9 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-style-declaration-named-getter-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/css-style-declaration-named-getter-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: 'getComputedStyle(e).cssXx' (except .cssFloat) is deprecated and will be removed in M50, around April 2016. Please use 'getComputedStyle(e).xx' instead.
 PASS document.body.style['BorderTopWidth'] is undefined.
 PASS document.body.style['borderTopWidth'] is "1px"
 PASS document.body.style['border-topWidth'] is undefined.
diff --git a/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/script-tests/css-properties-case-sensitive.js b/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/script-tests/css-properties-case-sensitive.js
index 923d74b..c2a541f 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/script-tests/css-properties-case-sensitive.js
+++ b/third_party/WebKit/LayoutTests/fast/dom/CSSStyleDeclaration/script-tests/css-properties-case-sensitive.js
@@ -1,21 +1,21 @@
 description(
-'This test checks that access to CSS properties via JavaScript properties on DOM elements is case sensitive.'
+'This test checks that access to the CSS float property via JavaScript properties on DOM elements is case sensitive. The use of .CssFloat is deprecated and will be removed in M50.'
 );
 
 var element = document.createElement('a');
-element.style.zIndex = 1;
+element.style.float = 'left';
 
 debug('normal cases');
 debug('');
 
-shouldBe("element.style.zIndex", "'1'");
-shouldBeUndefined("element.style.ZIndex");
+shouldBe("element.style.float", "'left'");
+shouldBeUndefined("element.style.Float");
 
 debug('');
 debug('"css" prefix');
 debug('');
 
-shouldBe("element.style.cssZIndex", "'1'");
-shouldBe("element.style.CssZIndex", "'1'");
-shouldBeUndefined("element.style.CsszIndex");
-shouldBeUndefined("element.style.csszIndex");
+shouldBe("element.style.cssFloat", "'left'");
+shouldBe("element.style.CssFloat", "'left'");
+shouldBeUndefined("element.style.Cssfloat");
+shouldBeUndefined("element.style.cssfloat");
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/images/green-2x2.png b/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/images/green-2x2.png
deleted file mode 100644
index adc0594..0000000
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/images/green-2x2.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/relevant-mutations.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/relevant-mutations.html
deleted file mode 100644
index 97d16b9e..0000000
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLImageElement/relevant-mutations.html
+++ /dev/null
@@ -1,386 +0,0 @@
-<!doctype html>
-<!-- TODO(yoav): this test is imported from web-platform-tests, but is here due to crbug.com/498120 -->
-<title>img relevant mutations</title>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<div id=log></div>
-
-<!-- should invoke update the image data -->
-
-<img data-desc="src set">
-<img src="images/green-2x2.png" data-desc="src changed">
-<img src="images/green-2x2.png" data-desc="src removed">
-
-<img data-desc="srcset set">
-<img srcset="images/green-2x2.png" data-desc="srcset changed">
-<img srcset="images/green-2x2.png" data-desc="srcset removed">
-
-<img data-desc="sizes set">
-<img sizes="" data-desc="sizes changed">
-<img sizes="" data-desc="sizes removed">
-
-<img src="images/green-2x2.png" data-desc="src set to same value">
-
-<img data-desc="crossorigin absent to empty">
-<img data-desc="crossorigin absent to anonymous">
-<img data-desc="crossorigin absent to use-credentials">
-<img crossorigin data-desc="crossorigin empty to absent">
-<img crossorigin data-desc="crossorigin empty to use-credentials">
-<img crossorigin=anonymous data-desc="crossorigin anonymous to absent">
-<img crossorigin=anonymous data-desc="crossorigin anonymous to use-credentials">
-<img crossorigin=use-credentials data-desc="crossorigin use-credentials to absent">
-<img crossorigin=use-credentials data-desc="crossorigin use-credentials to empty">
-<img crossorigin=use-credentials data-desc="crossorigin use-credentials to anonymous">
-
-<img src="images/green-2x2.png" data-desc="inserted into picture"><picture></picture>
-
-<picture><img src="images/green-2x2.png" data-desc="removed from picture"></picture>
-
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, previous source inserted"></picture>
-
-<picture><source><img src="images/green-2x2.png" data-desc="parent is picture, previous source removed"></picture>
-
-<picture><source><img src="images/green-2x2.png" data-desc="parent is picture, previous source has srcset set"></picture>
-<picture><source srcset=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has srcset changed"></picture>
-<picture><source srcset=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has srcset removed"></picture>
-
-<picture><source><img src="images/green-2x2.png" data-desc="parent is picture, previous source has sizes set"></picture>
-<picture><source sizes=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has sizes changed"></picture>
-<picture><source sizes=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has sizes removed"></picture>
-
-<picture><source><img src="images/green-2x2.png" data-desc="parent is picture, previous source has media set"></picture>
-<picture><source media=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has media changed"></picture>
-<picture><source media=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has media removed"></picture>
-
-<picture><source><img src="images/green-2x2.png" data-desc="parent is picture, previous source has type set"></picture>
-<picture><source type=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has type changed"></picture>
-<picture><source type=""><img src="images/green-2x2.png" data-desc="parent is picture, previous source has type removed"></picture>
-
-<!-- should not invoke update the image data -->
-
-<img srcset="images/green-2x2.png" data-desc="srcset is set to same value">
-<img srcset="images/green-2x2.png" sizes data-desc="sizes is set to same value">
-
-<img src="images/green-2x2.png" data-desc="crossorigin state not changed: absent, removeAttribute">
-<img src="images/green-2x2.png" crossorigin data-desc="crossorigin state not changed: empty to anonymous">
-<img src="images/green-2x2.png" crossorigin=anonymous data-desc="crossorigin state not changed: anonymous to foobar">
-<img src="images/green-2x2.png" crossorigin=use-credentials data-desc="crossorigin state not changed: use-credentials to USE-CREDENTIALS">
-
-<img src="images/green-2x2.png" data-desc="inserted into picture ancestor"><picture><span></span></picture>
-<picture><span><img src="images/green-2x2.png" data-desc="removed from picture ancestor"></span></picture>
-
-<picture><span><img src="images/green-2x2.png" data-desc="ancestor picture has a source inserted"></span></picture>
-<picture><source><span><img src="images/green-2x2.png" data-desc="ancestor picture has a source removed"></span></picture>
-
-<picture><span><img src="images/green-2x2.png" data-desc="ancestor picture; previous sibling source inserted"></span></picture>
-<picture><span><source><img src="images/green-2x2.png" data-desc="ancestor picture; previous sibling source removed"></span></picture>
-
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following sibling source inserted"></picture>
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following sibling source removed"><source></picture>
-
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following sibling source has srcset set"><source></picture>
-
-<img src="images/green-2x2.png" data-desc="media on img set">
-<img src="images/green-2x2.png" data-desc="type on img set">
-<img src="images/green-2x2.png" data-desc="class on img set">
-<img src="images/green-2x2.png" data-desc="alt on img set">
-
-<picture><source><img src="images/green-2x2.png" data-desc="src on previous sibling source set"></picture>
-<picture><source><img src="images/green-2x2.png" data-desc="class on previous sibling source set"></picture>
-
-<img src="images/green-2x2.png" data-desc="inserted/removed children of img">
-
-<picture><img src="images/green-2x2.png" data-desc="picture is inserted"></picture><span></span>
-<picture><img src="images/green-2x2.png" data-desc="picture is removed"></picture>
-
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following img inserted"></picture>
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following img removed"><img></picture>
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following img has src set"><img></picture>
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following img has srcset set"><img></picture>
-<picture><img src="images/green-2x2.png" data-desc="parent is picture, following img has sizes set"><img></picture>
-
-
-<script>
-setup({explicit_done:true});
-
-function t(desc, func, expect) {
-  async_test(function() {
-    var img = document.querySelector('[data-desc="' + desc + '"]');
-    img.onload = img.onerror = this.unreached_func('update the image data was run');
-    if (expect == 'timeout') {
-      setTimeout(this.step_func_done(), 1000);
-    } else {
-      img['on' + expect] = this.step_func_done(function() {});
-    }
-    func.call(this, img);
-  }, desc);
-}
-
-onload = function() {
-
-  t('src set', function(img) {
-    img.src = 'images/green-2x2.png';
-  }, 'load');
-
-  t('src changed', function(img) {
-    img.src = 'images/green-2x2.png ';
-  }, 'load');
-
-  t('src removed', function(img) {
-    img.removeAttribute('src');
-  }, 'timeout');
-
-  t('srcset set', function(img) {
-    img.srcset = 'images/green-2x2.png';
-  }, 'load');
-
-  t('srcset changed', function(img) {
-    img.srcset = 'images/green-2x2.png ';
-  }, 'load');
-
-  t('srcset removed', function(img) {
-    img.removeAttribute('srcset');
-  }, 'timeout');
-
-  t('sizes set', function(img) {
-    img.sizes = '';
-  }, 'timeout');
-
-  t('sizes changed', function(img) {
-    img.sizes = ' ';
-  }, 'timeout');
-
-  t('sizes removed', function(img) {
-    img.removeAttribute('sizes');
-  }, 'timeout');
-
-  t('src set to same value', function(img) {
-    img.src = 'images/green-2x2.png';
-  }, 'load');
-
-  t('crossorigin absent to empty', function(img) {
-    img.crossOrigin = '';
-  }, 'timeout');
-
-  t('crossorigin absent to anonymous', function(img) {
-    img.crossOrigin = 'anonymous';
-  }, 'timeout');
-
-  t('crossorigin absent to use-credentials', function(img) {
-    img.crossOrigin = 'use-credentials';
-  }, 'timeout');
-
-  t('crossorigin empty to absent', function(img) {
-    img.removeAttribute('crossorigin');
-  }, 'timeout');
-
-  t('crossorigin empty to use-credentials', function(img) {
-    img.crossOrigin = 'use-credentials';
-  }, 'timeout');
-
-  t('crossorigin anonymous to absent', function(img) {
-    img.removeAttribute('crossorigin');
-  }, 'timeout');
-
-  t('crossorigin anonymous to use-credentials', function(img) {
-    img.crossOrigin = 'use-credentials';
-  }, 'timeout');
-
-  t('crossorigin use-credentials to absent', function(img) {
-    img.removeAttribute('crossorigin');
-  }, 'timeout');
-
-  t('crossorigin use-credentials to empty', function(img) {
-    img.crossOrigin = '';
-  }, 'timeout');
-
-  t('crossorigin use-credentials to anonymous', function(img) {
-    img.crossOrigin = 'anonymous';
-  }, 'timeout');
-
-  t('inserted into picture', function(img) {
-    img.nextSibling.appendChild(img);
-  }, 'load');
-
-  t('removed from picture', function(img) {
-    img.parentNode.removeChild(img);
-  }, 'load');
-
-  t('parent is picture, previous source inserted', function(img) {
-    img.parentNode.insertBefore(document.createElement('source'), img);
-  }, 'load');
-
-  t('parent is picture, previous source removed', function(img) {
-    img.parentNode.removeChild(img.previousSibling);
-  }, 'load');
-
-  t('parent is picture, previous source has srcset set', function(img) {
-    img.previousSibling.srcset = '';
-  }, 'load');
-
-  t('parent is picture, previous source has srcset changed', function(img) {
-    img.previousSibling.srcset = ' ';
-  }, 'load');
-
-  t('parent is picture, previous source has srcset removed', function(img) {
-    img.previousSibling.removeAttribute('srcset');
-  }, 'load');
-
-  t('parent is picture, previous source has sizes set', function(img) {
-    img.previousSibling.sizes = '';
-  }, 'load');
-
-  t('parent is picture, previous source has sizes changed', function(img) {
-    img.previousSibling.sizes = ' ';
-  }, 'load');
-
-  t('parent is picture, previous source has sizes removed', function(img) {
-    img.previousSibling.removeAttribute('sizes');
-  }, 'load');
-
-  t('parent is picture, previous source has media set', function(img) {
-    img.previousSibling.media = '';
-  }, 'load');
-
-  t('parent is picture, previous source has media changed', function(img) {
-    img.previousSibling.media = ' ';
-  }, 'load');
-
-  t('parent is picture, previous source has media removed', function(img) {
-    img.previousSibling.removeAttribute('media');
-  }, 'load');
-
-  t('parent is picture, previous source has type set', function(img) {
-    img.previousSibling.type = '';
-  }, 'load');
-
-  t('parent is picture, previous source has type changed', function(img) {
-    img.previousSibling.type = ' ';
-  }, 'load');
-
-  t('parent is picture, previous source has type removed', function(img) {
-    img.previousSibling.removeAttribute('type');
-  }, 'load');
-
-  t('srcset is set to same value', function(img) {
-    img.srcset = "images/green-2x2.png";
-  }, 'timeout');
-
-  t('sizes is set to same value', function(img) {
-    img.sizes = '';
-  }, 'timeout');
-
-  t('crossorigin state not changed: absent, removeAttribute', function(img) {
-    img.removeAttribute('crossorigin');
-  }, 'timeout');
-
-  t('crossorigin state not changed: empty to anonymous', function(img) {
-    img.crossOrigin = 'anonymous';
-  }, 'timeout');
-
-  t('crossorigin state not changed: anonymous to foobar', function(img) {
-    img.crossOrigin = 'foobar';
-  }, 'timeout');
-
-  t('crossorigin state not changed: use-credentials to USE-CREDENTIALS', function(img) {
-    img.crossOrigin = 'USE-CREDENTIALS';
-  }, 'timeout');
-
-  t('inserted into picture ancestor', function(img) {
-    img.nextSibling.firstChild.appendChild(img);
-  }, 'timeout');
-
-  t('removed from picture ancestor', function(img) {
-    img.parentNode.removeChild(img);
-  }, 'timeout');
-
-  t('ancestor picture has a source inserted', function(img) {
-    img.parentNode.parentNode.insertBefore(document.createElement('source'), img.parentNode);
-  }, 'timeout');
-
-  t('ancestor picture has a source removed', function(img) {
-    img.parentNode.parentNode.removeChild(img.parentNode.previousSibling);
-  }, 'timeout');
-
-  t('ancestor picture; previous sibling source inserted', function(img) {
-    img.parentNode.insertBefore(document.createElement('source'), img);
-  }, 'timeout');
-
-  t('ancestor picture; previous sibling source removed', function(img) {
-    img.parentNode.removeChild(img.previousSibling);
-  }, 'timeout');
-
-  t('parent is picture, following sibling source inserted', function(img) {
-    img.parentNode.appendChild(document.createElement('source'));
-  }, 'timeout');
-
-  t('parent is picture, following sibling source removed', function(img) {
-    img.parentNode.removeChild(img.nextSibling);
-  }, 'timeout');
-
-  t('parent is picture, following sibling source has srcset set', function(img) {
-    img.nextSibling.srcset = '';
-  }, 'timeout');
-
-  t('media on img set', function(img) {
-    img.setAttribute('media', '');
-  }, 'timeout');
-
-  t('type on img set', function(img) {
-    img.setAttribute('type', '');
-  }, 'timeout');
-
-  t('class on img set', function(img) {
-    img.className = '';
-  }, 'timeout');
-
-  t('alt on img set', function(img) {
-    img.alt = '';
-  }, 'timeout');
-
-  t('src on previous sibling source set', function(img) {
-    img.previousSibling.setAttribute('src', '');
-  }, 'timeout');
-
-  t('class on previous sibling source set', function(img) {
-    img.previousSibling.className = '';
-  }, 'timeout');
-
-  t('inserted/removed children of img', function(img) {
-    img.appendChild(document.createElement('source'));
-    setTimeout(this.step_func(function() {
-      img.removeChild(img.firstChild);
-    }), 0);
-  }, 'timeout');
-
-  t('picture is inserted', function(img) {
-    img.parentNode.nextSibling.appendChild(img.parentNode);
-  }, 'timeout');
-
-  t('picture is removed', function(img) {
-    img.parentNode.parentNode.removeChild(img.parentNode);
-  }, 'timeout');
-
-  t('parent is picture, following img inserted', function(img) {
-    img.parentNode.appendChild(document.createElement('img'));
-  }, 'timeout');
-
-  t('parent is picture, following img removed', function(img) {
-    img.parentNode.removeChild(img.nextSibling);
-  }, 'timeout');
-
-  t('parent is picture, following img has src set', function(img) {
-    img.nextSibling.src = '';
-  }, 'timeout');
-
-  t('parent is picture, following img has srcset set', function(img) {
-    img.nextSibling.srcset = '';
-  }, 'timeout');
-
-  t('parent is picture, following img has sizes set', function(img) {
-    img.nextSibling.sizes = '';
-  }, 'timeout');
-
-  done();
-};
-</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-chorded-buttons.html b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-chorded-buttons.html
new file mode 100644
index 0000000..7705cd492
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-chorded-buttons.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<style>
+div.box {
+  margin: 10px;
+  padding: 50px;
+  float: left;
+}
+</style>
+
+<script>
+var receivedEvents = [];
+
+function testReceivedEvents(expectedEvents, testLabel) {
+  test(function() {
+    assert_array_equals(receivedEvents, expectedEvents);
+  }, testLabel);
+  receivedEvents = [];
+}
+
+function init() {
+  var targetDiv = document.getElementById("target");
+  targetEvents = ["mousedown", "mouseup", "pointerdown", "pointerup", "mousemove", "pointermove"];
+
+  targetEvents.forEach(function(eventName) {
+    targetDiv.addEventListener(eventName, function(event) {
+      receivedEvents.push(event.type + " " + event.button + "," + event.buttons);
+      if (event.type.startsWith("mouse"))
+        event.preventDefault();
+    });
+  });
+}
+
+function runTests() {
+  var rect = document.getElementById("target").getBoundingClientRect();
+  eventSender.mouseMoveTo(rect.left + 5, rect.top + 5);
+  receivedEvents = [];
+
+  eventSender.mouseDown(0, ["leftButton"]);
+  eventSender.mouseDown(1, ["leftButton", "middleButton"]);
+  eventSender.mouseUp(1, ["leftButton"]);
+  eventSender.mouseUp(0);
+  testReceivedEvents([
+    "pointerdown 0,1", "mousedown 0,1",
+    "pointermove 1,5", "mousedown 1,5",
+    "pointermove 1,1", "mouseup 1,1",
+    "pointerup 0,0", "mouseup 0,0"
+  ], "LM button sequence A");
+
+  eventSender.mouseDown(0, ["leftButton"]);
+  eventSender.mouseDown(1, ["leftButton", "middleButton"]);
+  eventSender.mouseUp(0, ["middleButton"]);
+  eventSender.mouseUp(1);
+  testReceivedEvents([
+    "pointerdown 0,1", "mousedown 0,1",
+    "pointermove 1,5", "mousedown 1,5",
+    "pointermove 0,4", "mouseup 0,4",
+    "pointerup 1,0", "mouseup 1,0"
+  ], "LM button sequence B");
+
+  eventSender.mouseDown(1, ["middleButton"]);
+  eventSender.mouseDown(0, ["middleButton", "leftButton"]);
+  eventSender.mouseUp(1, ["leftButton"]);
+  eventSender.mouseUp(0);
+  testReceivedEvents([
+    "pointerdown 1,4", "mousedown 1,4",
+    "pointermove 0,5", "mousedown 0,5",
+    "pointermove 1,1", "mouseup 1,1",
+    "pointerup 0,0", "mouseup 0,0"
+  ], "LM button sequence C");
+
+  eventSender.mouseDown(0, ["leftButton"]);
+  eventSender.mouseDown(2, ["leftButton", "rightButton"]);
+  eventSender.mouseDown(1, ["leftButton", "rightButton", "middleButton"]);
+  eventSender.mouseUp(0, ["rightButton", "middleButton"]);
+  eventSender.mouseUp(1, ["rightButton"]);
+  eventSender.mouseUp(2);
+  testReceivedEvents([
+    "pointerdown 0,1", "mousedown 0,1",
+    "pointermove 2,3", "mousedown 2,3",
+    "pointermove 1,7", "mousedown 1,7",
+    "pointermove 0,6", "mouseup 0,6",
+    "pointermove 1,2", "mouseup 1,2",
+    "pointerup 2,0", "mouseup 2,0"
+  ], "LMR button sequence");
+
+  eventSender.mouseDown(1, ["middleButton"]);
+  eventSender.mouseMoveTo(rect.left + 6, rect.top + 6, ["middleButton"]);
+  eventSender.mouseUp(1);
+  eventSender.mouseMoveTo(rect.left + 5, rect.top + 5);
+  testReceivedEvents([
+    "pointerdown 1,4", "mousedown 1,4",
+    "pointermove 1,4", "mousemove 1,4",
+    "pointerup 1,0", "mouseup 1,0",
+    "pointermove -1,0", "mousemove 0,0",
+  ], "Move with & without button");
+}
+
+function run() {
+  setup({explicit_done: true});
+
+  if (!window.eventSender)
+    assert_true(true, "No eventSender, skipped tests");
+  else if (!window.PointerEvent)
+    assert_true(true, "No PointerEvent, skipped tests");
+  else {
+    init();
+    runTests();
+  }
+
+  done();
+}
+</script>
+
+<body onload="run()">
+  <h1>PointerEvent: Verifies that chorded buttons fire appropriate events</h1>
+
+  <div id="target" class="box" style="background-color:red"></div>
+
+  <div id="log"></div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html
index c463150..3a8f644e 100644
--- a/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html
+++ b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html
@@ -73,7 +73,10 @@
           shouldBeTrue("lastPointerEvent.isPrimary");
 
           numericAttributes.forEach(function(attribute) {
-            shouldBeEqualToNumber("lastPointerEvent." + attribute, eval("event." + attribute));
+            var expectedValue = eval("event." + attribute);
+            if (attribute == "button" && event.type != "mousedown" && event.type != "mouseup")
+              expectedValue = -1;
+            shouldBeEqualToNumber("lastPointerEvent." + attribute, expectedValue);
           });
 
         } else {
@@ -109,7 +112,7 @@
 
   debug("--- click each button ---");
   for (var button = 0; button <=2; button++) {
-    eventSender.mouseDown(button);
+    eventSender.mouseDown(button, [button == 0 ? "leftButton" : button == 2 ? "rightButton" : "middleButton"]);
     eventSender.mouseUp(button);
     // TODO(crbug.com/548226): Investigate missing events in win_chromium_rel_ng on 3rd down/up.
   }
diff --git a/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-preventdefault.html b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-preventdefault.html
index 5139784..c3dd399 100644
--- a/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-preventdefault.html
+++ b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-preventdefault.html
@@ -68,9 +68,9 @@
 
     debug("- drag out of and into target & release within target -");
     eventSender.mouseDown();
-    eventSender.mouseMoveTo(x2+5, y2+5);
-    eventSender.mouseMoveTo(x1, y1);
-    eventSender.mouseMoveTo(x2, y2);
+    eventSender.mouseMoveTo(x2+5, y2+5, ["leftButton"]);
+    eventSender.mouseMoveTo(x1, y1, ["leftButton"]);
+    eventSender.mouseMoveTo(x2, y2, ["leftButton"]);
     eventSender.mouseUp();
 
     debug("- move outside target again -");
diff --git a/third_party/WebKit/LayoutTests/hittesting/image-with-border-radius-expected.txt b/third_party/WebKit/LayoutTests/hittesting/image-with-border-radius-expected.txt
new file mode 100644
index 0000000..a579403e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/hittesting/image-with-border-radius-expected.txt
@@ -0,0 +1,16 @@
+The border radius clip should be respected when hit testing images.
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS document.elementFromPoint(x + 20, y + 20).id is 'container'
+PASS document.elementFromPoint(x + 35, y + 35).id is 'roundedImage'
+PASS document.elementFromPoint(x + 60, y + 60).id is 'roundedImage'
+PASS document.elementFromPoint(x + 68, y + 68).id is 'roundedImage'
+PASS document.elementFromPoint(x + 80, y + 80).id is 'roundedImage'
+PASS document.elementFromPoint(x + 230, y + 230).id is 'roundedImage'
+PASS document.elementFromPoint(x + 240, y + 240).id is 'roundedImage'
+PASS document.elementFromPoint(x + 265, y + 265).id is 'roundedImage'
+PASS document.elementFromPoint(x + 275, y + 275).id is 'container'
+
diff --git a/third_party/WebKit/LayoutTests/hittesting/image-with-border-radius.html b/third_party/WebKit/LayoutTests/hittesting/image-with-border-radius.html
new file mode 100644
index 0000000..92fd4c5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/hittesting/image-with-border-radius.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<script src="../resources/js-test.js"></script>
+<script>
+var x, y;
+function test() {
+    var rect = roundedImage.getBoundingClientRect();
+    x = rect.left;
+    y = rect.top;
+
+    // At top-left corner, outside the outer border radius.
+    shouldBe("document.elementFromPoint(x + 20, y + 20).id", "'container'");
+
+    // At top-left corner, inside outer border radius.
+    shouldBe("document.elementFromPoint(x + 35, y + 35).id", "'roundedImage'");
+    shouldBe("document.elementFromPoint(x + 60, y + 60).id", "'roundedImage'");
+
+    // Fully inside border.
+    shouldBe("document.elementFromPoint(x + 68, y + 68).id", "'roundedImage'");
+    shouldBe("document.elementFromPoint(x + 80, y + 80).id", "'roundedImage'");
+    shouldBe("document.elementFromPoint(x + 230, y + 230).id", "'roundedImage'");
+
+    // At bottom-right corner, insider inner border radius.
+    shouldBe("document.elementFromPoint(x + 240, y + 240).id", "'roundedImage'");
+    shouldBe("document.elementFromPoint(x + 265, y + 265).id", "'roundedImage'");
+
+    // At bottom-right corner, outside the outer border radius.
+    shouldBe("document.elementFromPoint(x + 275, y + 275).id", "'container'");
+}
+</script>
+<style>
+    #container {
+        display: inline-block;
+        background-color: black;
+    }
+    #roundedImage {
+        width: 200px;
+        height: 200px;
+        border-radius: 100px;
+        background-color: blue;
+        border: 50px solid orange;
+        display: block;
+    }
+    #roundedImage:hover {
+        border-color: green;
+        background-color: green;
+    }
+</style>
+<body onload="test()">
+    <p>The border radius clip should be respected when hit testing images.</p>
+    <div id="container">
+        <img id="roundedImage" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
+    </div>
+    <div id="console"></div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/hittesting/image-with-clip-path-expected.txt b/third_party/WebKit/LayoutTests/hittesting/image-with-clip-path-expected.txt
new file mode 100644
index 0000000..1f485b8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/hittesting/image-with-clip-path-expected.txt
@@ -0,0 +1,19 @@
+Image hit testing should not include clipped-out regions.
+
+ 
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS document.elementFromPoint(75, 125).id is not 'imageWithReferenceClipPath'
+PASS document.elementFromPoint(125, 75).id is 'imageWithReferenceClipPath'
+PASS document.elementFromPoint(75+100, 125).id is not 'imageWithShapeClipPath'
+PASS document.elementFromPoint(125+100, 75).id is 'imageWithShapeClipPath'
+PASS document.elementFromPoint(100, 225).id is not 'transformedWithReferenceClipPath'
+PASS document.elementFromPoint(135, 175).id is not 'transformedWithReferenceClipPath'
+PASS document.elementFromPoint(115, 175).id is 'transformedWithReferenceClipPath'
+PASS document.elementFromPoint(120, 225).id is 'transformedWithReferenceClipPath'
+PASS document.elementFromPoint(100+100, 225).id is not 'transformedWithShapeClipPath'
+PASS document.elementFromPoint(135+100, 175).id is not 'transformedWithShapeClipPath'
+PASS document.elementFromPoint(115+100, 175).id is 'transformedWithShapeClipPath'
+PASS document.elementFromPoint(120+100, 225).id is 'transformedWithShapeClipPath'
+
diff --git a/third_party/WebKit/LayoutTests/hittesting/image-with-clip-path.html b/third_party/WebKit/LayoutTests/hittesting/image-with-clip-path.html
new file mode 100644
index 0000000..3018f2b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/hittesting/image-with-clip-path.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<script src="../resources/js-test.js"></script>
+<script>
+    function test() {
+        // Check that clip path affects hit testing for the first row of images.
+        // These images are offset with top/left.
+        // (75,125) is outside the triangular clip path, (125,75) is inside it.
+        shouldNotBe("document.elementFromPoint(75, 125).id", "'imageWithReferenceClipPath'");
+        shouldBe("document.elementFromPoint(125, 75).id", "'imageWithReferenceClipPath'");
+        // Same test as above but for a shape-based clip path offset by 100px.
+        shouldNotBe("document.elementFromPoint(75+100, 125).id", "'imageWithShapeClipPath'");
+        shouldBe("document.elementFromPoint(125+100, 75).id", "'imageWithShapeClipPath'");
+
+        // Check that clip path affects hit testing for the second row. These
+        // images are transformed by a container by (25,25) and each has a
+        // 3d rotation causing the images to be horizontally squished. The test
+        // coordinates are tight and will fail without the Y rotation.
+        // (100,255) and (135,175) are outside the triangular clip path.
+        // (115,175) and (120,225) are inside the triangular clip path.
+        shouldNotBe("document.elementFromPoint(100, 225).id", "'transformedWithReferenceClipPath'");
+        shouldNotBe("document.elementFromPoint(135, 175).id", "'transformedWithReferenceClipPath'");
+        shouldBe("document.elementFromPoint(115, 175).id", "'transformedWithReferenceClipPath'");
+        shouldBe("document.elementFromPoint(120, 225).id", "'transformedWithReferenceClipPath'");
+        // Same test as above but for a shape-based clip path offset by 100px.
+        shouldNotBe("document.elementFromPoint(100+100, 225).id", "'transformedWithShapeClipPath'");
+        shouldNotBe("document.elementFromPoint(135+100, 175).id", "'transformedWithShapeClipPath'");
+        shouldBe("document.elementFromPoint(115+100, 175).id", "'transformedWithShapeClipPath'");
+        shouldBe("document.elementFromPoint(120+100, 225).id", "'transformedWithShapeClipPath'");
+    }
+</script>
+<style>
+    .referenceClipPath {
+        -webkit-clip-path: url(#referenceClipPathTopLeft);
+        clip-path: url(#referenceClipPathTopLeft);
+        width: 100px;
+        height: 100px;
+        position: absolute;
+    }
+    .referenceClipPath:hover {
+        background: green;
+    }
+    .shapeClipPath {
+        -webkit-clip-path: polygon(0% 0%, 100% 100%, 100% 0%);
+        clip-path: polygon(0% 0%, 100% 100%, 100% 0%);
+        width: 100px;
+        height: 100px;
+        position: absolute;
+    }
+    .shapeClipPath:hover {
+        background: green;
+    }
+    #imageWithReferenceClipPath {
+        top: 50px;
+        left: 50px;
+    }
+    #imageWithShapeClipPath {
+        top: 50px;
+        left: 150px;
+    }
+    #transformedDivContainer {
+        position: absolute;
+        top: 0;
+        left: 0;
+        transform: translate3d(25px, 25px, 0);
+    }
+    #transformedWithReferenceClipPath {
+        top: 125px;
+        left: 25px;
+        transform: rotateY(60deg);
+    }
+    #transformedWithShapeClipPath {
+        top: 125px;
+        left: 125px;
+        transform: rotateY(60deg);
+    }
+</style>
+<body onload="test()">
+    <p>Image hit testing should not include clipped-out regions.</p>
+    <svg width="100" height="0">
+        <defs>
+            <clipPath id="referenceClipPathTopLeft" clipPathUnits="objectBoundingBox">
+                <path id="path" d="M 0 0 L 100 100 L 100 0Z" />
+            </clipPath>
+        </defs>
+    </svg>
+    <img id="imageWithReferenceClipPath" class="referenceClipPath" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
+    <img id="imageWithShapeClipPath" class="shapeClipPath" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
+    <div id="transformedDivContainer">
+        <img id="transformedWithReferenceClipPath" class="referenceClipPath" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
+        <img id="transformedWithShapeClipPath" class="shapeClipPath" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
+    </div>
+    <div id="console"></div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
index f74f4bb..2ca60bd 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
@@ -34,7 +34,7 @@
     {
         InspectorTest.addResult("Stylesheet was added, dumping location:");
         var header = event.data;
-        var cssLocation = new WebInspector.CSSLocation(header.cssModel(), header.id, header.sourceURL, 0, 1);
+        var cssLocation = new WebInspector.CSSLocation(header, 0, 1);
         liveLocation = WebInspector.cssWorkspaceBinding.createLiveLocation(cssLocation, function() {});
         InspectorTest.addSniffer(WebInspector.CSSWorkspaceBinding.prototype, "pushSourceMapping", afterBind);
         dumpLiveLocation();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html b/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html
index e82b82c..3ec87597 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stylesheet-source-mapping.html
@@ -23,7 +23,8 @@
 
     function locationsUpdated()
     {
-        var uiLocation = InspectorTest.testCSSWorkspaceBinding.rawLocationToUILocation(new WebInspector.CSSLocation(cssModel, styleSheetId, styleSheetURL, 2, 3));
+        var header = cssModel.styleSheetHeaderForId(styleSheetId);
+        var uiLocation = InspectorTest.testCSSWorkspaceBinding.rawLocationToUILocation(new WebInspector.CSSLocation(header, 2, 3));
         var networkURL = InspectorTest.testNetworkMapping.networkURL(uiLocation.uiSourceCode);
         if (networkURL.indexOf(".scss") === -1)
             return;
@@ -73,7 +74,8 @@
 
     function rawLocationToUILocation(line, column)
     {
-        return InspectorTest.testCSSWorkspaceBinding.rawLocationToUILocation(new WebInspector.CSSLocation(cssModel, styleSheetId, styleSheetURL, line, column));
+        var header = cssModel.styleSheetHeaderForId(styleSheetId);
+        return InspectorTest.testCSSWorkspaceBinding.rawLocationToUILocation(new WebInspector.CSSLocation(header, line, column));
     }
 
     function afterStyleSheetAdded()
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-1/disable-property-workingcopy-update.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-1/disable-property-workingcopy-update.html
index 74554ab..609c650d0 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-1/disable-property-workingcopy-update.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-1/disable-property-workingcopy-update.html
@@ -22,7 +22,7 @@
             var headers = InspectorTest.cssModel.styleSheetHeaders();
             for (var i = 0; i < headers.length; ++i) {
                 if (headers[i].sourceURL.endsWith(".css")) {
-                    var cssLocation = new WebInspector.CSSLocation(InspectorTest.cssModel, headers[i].id, headers[i].sourceURL, 0);
+                    var cssLocation = new WebInspector.CSSLocation(headers[i], 0);
                     InspectorTest.showUISourceCode(WebInspector.cssWorkspaceBinding.rawLocationToUILocation(cssLocation).uiSourceCode, callback);
                     break;
                 }
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/culling/filter-occlusion-blur-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/culling/filter-occlusion-blur-expected.png
new file mode 100644
index 0000000..639f197
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/compositing/culling/filter-occlusion-blur-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/culling/filter-occlusion-blur-large-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/culling/filter-occlusion-blur-large-expected.png
new file mode 100644
index 0000000..ae5d33e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/compositing/culling/filter-occlusion-blur-large-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-blur-hw-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-blur-hw-expected.png
new file mode 100644
index 0000000..457bde8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-blur-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-drop-shadow-hw-expected.png
new file mode 100644
index 0000000..9d48932
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-drop-shadow-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-reference-colorspace-hw-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-reference-colorspace-hw-expected.png
new file mode 100644
index 0000000..b5bb8f2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-reference-colorspace-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-reference-hidpi-hw-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-reference-hidpi-hw-expected.png
new file mode 100644
index 0000000..ee793a2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/css3/filters/effect-reference-hidpi-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/filters/filter-repaint-composited-fallback-crash-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/filters/filter-repaint-composited-fallback-crash-expected.png
new file mode 100644
index 0000000..e011fc7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/css3/filters/filter-repaint-composited-fallback-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/filters/filter-repaint-composited-fallback-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/filters/filter-repaint-composited-fallback-expected.png
new file mode 100644
index 0000000..e011fc7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/css3/filters/filter-repaint-composited-fallback-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/batik/text/textFeatures-expected.png
new file mode 100644
index 0000000..3762f0c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr-expected.png
new file mode 100644
index 0000000..1aec90c2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop-expected.png
new file mode 100644
index 0000000..1aec90c2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-expected.png
index 639f197..2ce436b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-large-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-large-expected.png
index ae5d33e..147f72f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-large-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/culling/filter-occlusion-blur-large-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-blur-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-blur-hw-expected.png
index 457bde8..3f46d5f0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-blur-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-blur-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-drop-shadow-hw-expected.png
index 9d48932..f31c447 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-drop-shadow-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-drop-shadow-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-colorspace-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-colorspace-hw-expected.png
index b5bb8f2..6cf8dc02 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-colorspace-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-colorspace-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-expected.png
index c0c9480..b57c377 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.png
index ee793a2..9e7ac9713 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hw-expected.png
index 76fd0f5a..f3ec84b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-ordering-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-ordering-hw-expected.png
index b83d4025..c93da704 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-ordering-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-ordering-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-subregion-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-subregion-hw-expected.png
index 250bdfb..b59c4e4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-subregion-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-subregion-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-expected.png
index 9399321..617bf047 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-hw-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-hw-expected.png
index 92a4f058..f53115e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-zoom-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-crash-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-crash-expected.png
index e011fc7..ad0a3dc6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-expected.png
index e011fc7..ad0a3dc6 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/filter-repaint-composited-fallback-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png
index 7d63053..3adefc37 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png
index 50d3d800..ff40f47d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png
index 3762f0c..6bc8c07 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
index 7d63053..3adefc37 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 3af638f..a75ec0f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index e3731d5..ba514cc 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-expected.png
index d53fba9..2ce436b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-large-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-large-expected.png
index ae5d33e..147f72f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-large-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/culling/filter-occlusion-blur-large-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-blur-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-blur-hw-expected.png
index c9f53fb..ee41467 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-blur-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-blur-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-drop-shadow-hw-expected.png
index 4465c1846d..40882e2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-drop-shadow-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-drop-shadow-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-colorspace-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-colorspace-hw-expected.png
index 384ea576..ff0a6ab1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-colorspace-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-colorspace-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-expected.png
index c2bb1239..ffc95df 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hidpi-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hidpi-hw-expected.png
index 9dd5574bd..e63a493 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hidpi-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hidpi-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hw-expected.png
index 0e401171..700e0f01 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-ordering-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-ordering-hw-expected.png
index 25015e727..ef7669c9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-ordering-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-ordering-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-subregion-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-subregion-hw-expected.png
index 740725f..e167877 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-subregion-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-subregion-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-expected.png
index 2d8e5ef9..3721f87 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-hw-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-hw-expected.png
index bfcb3f0..8b2df9b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/effect-reference-zoom-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-crash-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-crash-expected.png
index e011fc7..ad0a3dc6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-expected.png
index e011fc7..ad0a3dc6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/css3/filters/filter-repaint-composited-fallback-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png
index 47e5a36..9d06ae3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png
index c3d1c2c..8bb440a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png
index 12ed9685..624331a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
index 47e5a36..9d06ae3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 635d1144..1f88ce5 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 2423c30..2b992d5a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-drop-shadow-hw-expected.png
index d0b94ea..7b8daa7 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-drop-shadow-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-drop-shadow-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-colorspace-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-colorspace-hw-expected.png
index 164e9ce6..d265963c 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-colorspace-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-colorspace-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-expected.png
index 0402e03..b22aa171 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-hw-expected.png
index 65caad7..0187b0f 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-subregion-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-subregion-hw-expected.png
index a92ce04..b42350e 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-subregion-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/css3/filters/effect-reference-subregion-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png
index 93a2e0a9..99cab5b 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/filters/feTile-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/filters/feTile-expected.png
index 4401c6c..44b946e9 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/filters/feTile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/filters/feTile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/text/textFeatures-expected.png
index 74d8dbd..905bc9e 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
index 93a2e0a9..99cab5b 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 3eff631..d0248ffc2 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 67cdce5..7daba94 100644
--- a/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win-xp/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-expected.png
index 44b3f599..36d82c9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-large-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-large-expected.png
index b026062..fa534224 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-large-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/culling/filter-occlusion-blur-large-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-blur-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-blur-hw-expected.png
index d647b2be..d08ba62a5 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-blur-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-blur-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-drop-shadow-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-drop-shadow-hw-expected.png
index 197ec9e..388bf27 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-drop-shadow-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-drop-shadow-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-colorspace-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-colorspace-hw-expected.png
index a290a8c1..dd44520 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-colorspace-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-colorspace-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-expected.png
index ae0061457..57859a5 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.png
index deb6aeb4..86654837 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hw-expected.png
index 802c74c..1b92c544 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-ordering-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-ordering-hw-expected.png
index 1fe42ad..03b56e0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-ordering-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-ordering-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-subregion-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-subregion-hw-expected.png
index 204a5f9..77b7e29 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-subregion-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-subregion-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-expected.png
index 0587d500..275c770 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png
index 6d7ee510..9760b3d1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-zoom-hw-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-crash-expected.png
index c282bdf..13a33de 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-expected.png
index c282bdf..13a33de 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/filter-repaint-composited-fallback-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png
index 71a985ba..a023a9d0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png
index d6efa74e..7c72384 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
index 51e96d1f..d5e65f9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
index 71a985ba..a023a9d0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 40c38fc..d9b91a17 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 965e3cc..de66f18 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/css/path-gradient-stroke-shadow-expected.png b/third_party/WebKit/LayoutTests/svg/css/path-gradient-stroke-shadow-expected.png
index ab94a76c..858cb44 100644
--- a/third_party/WebKit/LayoutTests/svg/css/path-gradient-stroke-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/css/path-gradient-stroke-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/css/rect-gradient-stroke-shadow-expected.png b/third_party/WebKit/LayoutTests/svg/css/rect-gradient-stroke-shadow-expected.png
index ab94a76c..858cb44 100644
--- a/third_party/WebKit/LayoutTests/svg/css/rect-gradient-stroke-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/css/rect-gradient-stroke-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr-expected.png
index 1aec90c2..79659c2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-dom-in-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop-expected.png
index 1aec90c2..79659c2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGFEMergeNodeElement-svgdom-in-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/pointerevent/fast/events/pointerevents/mouse-pointer-event-properties-expected.txt b/third_party/WebKit/LayoutTests/virtual/pointerevent/fast/events/pointerevents/mouse-pointer-event-properties-expected.txt
index d78ebb9..324a65b 100644
--- a/third_party/WebKit/LayoutTests/virtual/pointerevent/fast/events/pointerevents/mouse-pointer-event-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/pointerevent/fast/events/pointerevents/mouse-pointer-event-properties-expected.txt
@@ -26,7 +26,7 @@
 PASS lastPointerEvent.screenY is 31
 PASS lastPointerEvent.x is 23
 PASS lastPointerEvent.y is 31
-PASS lastPointerEvent.button is 0
+PASS lastPointerEvent.button is -1
 PASS lastPointerEvent.buttons is 0
 Received pointerenter
 Received mouseenter
@@ -50,7 +50,7 @@
 PASS lastPointerEvent.screenY is 31
 PASS lastPointerEvent.x is 23
 PASS lastPointerEvent.y is 31
-PASS lastPointerEvent.button is 0
+PASS lastPointerEvent.button is -1
 PASS lastPointerEvent.buttons is 0
 Received pointermove
 Received mousemove
@@ -74,7 +74,7 @@
 PASS lastPointerEvent.screenY is 31
 PASS lastPointerEvent.x is 23
 PASS lastPointerEvent.y is 31
-PASS lastPointerEvent.button is 0
+PASS lastPointerEvent.button is -1
 PASS lastPointerEvent.buttons is 0
 
 --- move within target ---
@@ -100,7 +100,7 @@
 PASS lastPointerEvent.screenY is 41
 PASS lastPointerEvent.x is 25
 PASS lastPointerEvent.y is 41
-PASS lastPointerEvent.button is 0
+PASS lastPointerEvent.button is -1
 PASS lastPointerEvent.buttons is 0
 Received pointermove
 Received mousemove
@@ -124,7 +124,7 @@
 PASS lastPointerEvent.screenY is 31
 PASS lastPointerEvent.x is 23
 PASS lastPointerEvent.y is 31
-PASS lastPointerEvent.button is 0
+PASS lastPointerEvent.button is -1
 PASS lastPointerEvent.buttons is 0
 
 --- click each button ---
@@ -628,7 +628,7 @@
 PASS lastPointerEvent.screenY is 21
 PASS lastPointerEvent.x is 13
 PASS lastPointerEvent.y is 21
-PASS lastPointerEvent.button is 0
+PASS lastPointerEvent.button is -1
 PASS lastPointerEvent.buttons is 0
 Received pointerleave
 Received mouseleave
@@ -652,7 +652,7 @@
 PASS lastPointerEvent.screenY is 21
 PASS lastPointerEvent.x is 13
 PASS lastPointerEvent.y is 21
-PASS lastPointerEvent.button is 0
+PASS lastPointerEvent.button is -1
 PASS lastPointerEvent.buttons is 0
 PASS successfullyParsed is true
 
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 5c2df7b1..bb290086 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3630,6 +3630,12 @@
     getter value
     method constructor
     setter value
+interface OffScreenCanvas
+    getter height
+    getter width
+    method constructor
+    setter height
+    setter width
 interface OfflineAudioCompletionEvent : Event
     getter renderedBuffer
     method constructor
diff --git a/third_party/WebKit/LayoutTests/whitespace.txt b/third_party/WebKit/LayoutTests/whitespace.txt
index cbf1507..26041a0 100644
--- a/third_party/WebKit/LayoutTests/whitespace.txt
+++ b/third_party/WebKit/LayoutTests/whitespace.txt
@@ -9,3 +9,5 @@
 Her retort: "I implemented <blink> in Blink using Javscript!"
 
 "Amaze balls. You should visit a doctor.", said he.
+
+A PNG image exploded nearby, "Aw Snap!". What was that?
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
index fb9dc2d2..a6c43d71 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -96,7 +96,7 @@
         i += 3;
         // getComputedStyle(elem).cssX is a non-standard behaviour
         // Measure this behaviour as CSSXGetComputedStyleQueries.
-        UseCounter::countIfNotPrivateScript(isolate, callingExecutionContext(isolate), UseCounter::CSSXGetComputedStyleQueries);
+        UseCounter::countDeprecationIfNotPrivateScript(isolate, callingExecutionContext(isolate), UseCounter::CSSXGetComputedStyleQueries);
     } else if (hasCSSPropertyNamePrefix(propertyName, "webkit"))
         builder.append('-');
     else if (isASCIIUpper(propertyName[0]))
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index bb84f8767..a9098c02 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -231,6 +231,7 @@
             'html/TimeRanges.idl',
             'html/ValidityState.idl',
             'html/VoidCallback.idl',
+            'html/canvas/OffScreenCanvas.idl',
             'html/track/AudioTrack.idl',
             'html/track/AudioTrackList.idl',
             'html/track/TextTrack.idl',
@@ -2926,6 +2927,8 @@
             'html/canvas/CanvasRenderingContext.cpp',
             'html/canvas/CanvasRenderingContext.h',
             'html/canvas/CanvasRenderingContextFactory.h',
+            'html/canvas/OffScreenCanvas.cpp',
+            'html/canvas/OffScreenCanvas.h',
             'html/forms/BaseButtonInputType.cpp',
             'html/forms/BaseButtonInputType.h',
             'html/forms/BaseCheckableInputType.cpp',
diff --git a/third_party/WebKit/Source/core/css/SelectorChecker.cpp b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
index 5398b4f7..4740117 100644
--- a/third_party/WebKit/Source/core/css/SelectorChecker.cpp
+++ b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
@@ -1160,27 +1160,27 @@
         return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
     case CSSSelector::PseudoDoubleButton:
         {
-            ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme().buttonsPlacement();
+            WebScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme().buttonsPlacement();
             if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
-                return buttonsPlacement == ScrollbarButtonsPlacementDoubleStart || buttonsPlacement == ScrollbarButtonsPlacementDoubleBoth;
+                return buttonsPlacement == WebScrollbarButtonsPlacementDoubleStart || buttonsPlacement == WebScrollbarButtonsPlacementDoubleBoth;
             if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
-                return buttonsPlacement == ScrollbarButtonsPlacementDoubleEnd || buttonsPlacement == ScrollbarButtonsPlacementDoubleBoth;
+                return buttonsPlacement == WebScrollbarButtonsPlacementDoubleEnd || buttonsPlacement == WebScrollbarButtonsPlacementDoubleBoth;
             return false;
         }
     case CSSSelector::PseudoSingleButton:
         {
-            ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme().buttonsPlacement();
+            WebScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme().buttonsPlacement();
             if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
-                return buttonsPlacement == ScrollbarButtonsPlacementSingle;
+                return buttonsPlacement == WebScrollbarButtonsPlacementSingle;
             return false;
         }
     case CSSSelector::PseudoNoButton:
         {
-            ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme().buttonsPlacement();
+            WebScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme().buttonsPlacement();
             if (part == BackTrackPart)
-                return buttonsPlacement == ScrollbarButtonsPlacementNone || buttonsPlacement == ScrollbarButtonsPlacementDoubleEnd;
+                return buttonsPlacement == WebScrollbarButtonsPlacementNone || buttonsPlacement == WebScrollbarButtonsPlacementDoubleEnd;
             if (part == ForwardTrackPart)
-                return buttonsPlacement == ScrollbarButtonsPlacementNone || buttonsPlacement == ScrollbarButtonsPlacementDoubleStart;
+                return buttonsPlacement == WebScrollbarButtonsPlacementNone || buttonsPlacement == WebScrollbarButtonsPlacementDoubleStart;
             return false;
         }
     case CSSSelector::PseudoCornerPresent:
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
index 2ed82aa..fa4aca1 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -532,7 +532,7 @@
             RefPtrWillBeRawPtr<Node> protect(n); // removedFromDocument may remove all references to this node.
             container.document().adoptIfNeeded(*n);
             if (n->inDocument())
-                container.notifyNodeRemoved(*n, next);
+                container.notifyNodeRemoved(*n);
         }
     }
 
@@ -591,7 +591,7 @@
         Node* prev = child->previousSibling();
         Node* next = child->nextSibling();
         removeBetween(prev, next, *child);
-        notifyNodeRemoved(*child, next);
+        notifyNodeRemoved(*child);
         childrenChanged(ChildrenChange::forRemoval(*child, prev, next, ChildrenChangeSourceAPI));
     }
     dispatchSubtreeModifiedEvent();
@@ -643,7 +643,7 @@
     Node* next = oldChild.nextSibling();
     removeBetween(prev, next, oldChild);
 
-    notifyNodeRemoved(oldChild, next);
+    notifyNodeRemoved(oldChild);
     childrenChanged(ChildrenChange::forRemoval(oldChild, prev, next, ChildrenChangeSourceParser));
 }
 
@@ -695,12 +695,11 @@
             removedChildren.reserveInitialCapacity(countChildren());
 #endif
             while (RefPtrWillBeRawPtr<Node> child = m_firstChild) {
-                Node* next = child->nextSibling();
-                removeBetween(nullptr, next, *child);
+                removeBetween(0, child->nextSibling(), *child);
 #if !ENABLE(OILPAN)
                 removedChildren.append(child.get());
 #endif
-                notifyNodeRemoved(*child, next);
+                notifyNodeRemoved(*child);
             }
         }
 
@@ -848,7 +847,7 @@
     }
 }
 
-void ContainerNode::notifyNodeRemoved(Node& root, Node* next)
+void ContainerNode::notifyNodeRemoved(Node& root)
 {
     ScriptForbiddenScope forbidScript;
     EventDispatchForbiddenScope assertNoEventDispatch;
@@ -859,9 +858,9 @@
         // call to removedFrom is not needed.
         if (!node.isContainerNode() && !node.isInTreeScope())
             continue;
-        node.removedFrom(this, node == root ? next : node.nextSibling());
+        node.removedFrom(this);
         for (ShadowRoot* shadowRoot = node.youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
-            notifyNodeRemoved(*shadowRoot, next);
+            notifyNodeRemoved(*shadowRoot);
     }
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.h b/third_party/WebKit/Source/core/dom/ContainerNode.h
index 87989667..44f1f4e 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.h
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.h
@@ -247,7 +247,7 @@
 
     void notifyNodeInserted(Node&, ChildrenChangeSource = ChildrenChangeSourceAPI);
     void notifyNodeInsertedInternal(Node&, NodeVector& postInsertionNotificationTargets);
-    void notifyNodeRemoved(Node& root, Node* next);
+    void notifyNodeRemoved(Node&);
 
     bool hasRestyleFlag(DynamicRestyleFlags mask) const { return hasRareData() && hasRestyleFlagInternal(mask); }
     bool hasRestyleFlags() const { return hasRareData() && hasRestyleFlagsInternal(); }
diff --git a/third_party/WebKit/Source/core/dom/DocumentType.cpp b/third_party/WebKit/Source/core/dom/DocumentType.cpp
index fb182a2..78c5c4e 100644
--- a/third_party/WebKit/Source/core/dom/DocumentType.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentType.cpp
@@ -68,10 +68,10 @@
     return InsertionDone;
 }
 
-void DocumentType::removedFrom(ContainerNode* insertionPoint, Node* next)
+void DocumentType::removedFrom(ContainerNode* insertionPoint)
 {
     document().setDoctype(nullptr);
-    Node::removedFrom(insertionPoint, next);
+    Node::removedFrom(insertionPoint);
 }
 
 }
diff --git a/third_party/WebKit/Source/core/dom/DocumentType.h b/third_party/WebKit/Source/core/dom/DocumentType.h
index 6ec5916..86549b2 100644
--- a/third_party/WebKit/Source/core/dom/DocumentType.h
+++ b/third_party/WebKit/Source/core/dom/DocumentType.h
@@ -49,7 +49,7 @@
     PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     String m_name;
     String m_publicId;
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 7f70c23e..22a345e 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -1492,7 +1492,7 @@
     return InsertionDone;
 }
 
-void Element::removedFrom(ContainerNode* insertionPoint, Node* next)
+void Element::removedFrom(ContainerNode* insertionPoint)
 {
     bool wasInDocument = insertionPoint->inDocument();
 
@@ -1524,7 +1524,7 @@
             updateName(nameValue, nullAtom);
     }
 
-    ContainerNode::removedFrom(insertionPoint, next);
+    ContainerNode::removedFrom(insertionPoint);
     if (wasInDocument) {
         if (this == document().cssTarget())
             document().setCSSTarget(nullptr);
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index 8366710..3226de50 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -565,7 +565,7 @@
     void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>);
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void childrenChanged(const ChildrenChange&) override;
 
     virtual void willRecalcStyle(StyleRecalcChange);
@@ -848,7 +848,7 @@
     return InsertionDone;
 }
 
-inline void Node::removedFrom(ContainerNode* insertionPoint, Node* next)
+inline void Node::removedFrom(ContainerNode* insertionPoint)
 {
     ASSERT(insertionPoint->inDocument() || isContainerNode() || isInShadowTree());
     if (insertionPoint->inDocument()) {
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index 0de7d55b..9383f6b 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -579,7 +579,7 @@
     // This is a dual of insertedInto(), and is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
     // dispatching, and is called _after_ the node is removed from the tree.
     //
-    virtual void removedFrom(ContainerNode* insertionPoint, Node* next);
+    virtual void removedFrom(ContainerNode* insertionPoint);
 
     // FIXME(dominicc): This method is not debug-only--it is used by
     // Tracing--rename it to something indicative.
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
index fd3c13f..d540c302 100644
--- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
+++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
@@ -274,9 +274,9 @@
     return InsertionDone;
 }
 
-void ProcessingInstruction::removedFrom(ContainerNode* insertionPoint, Node* next)
+void ProcessingInstruction::removedFrom(ContainerNode* insertionPoint)
 {
-    CharacterData::removedFrom(insertionPoint, next);
+    CharacterData::removedFrom(insertionPoint);
     if (!insertionPoint->inDocument())
         return;
 
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h
index b0a5a66..48c3c64 100644
--- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.h
+++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.h
@@ -85,7 +85,7 @@
     PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     bool checkStyleSheet(String& href, String& charset);
     void process(const String& href, const String& charset);
diff --git a/third_party/WebKit/Source/core/dom/PseudoElement.cpp b/third_party/WebKit/Source/core/dom/PseudoElement.cpp
index be6e5cc..c8aba370 100644
--- a/third_party/WebKit/Source/core/dom/PseudoElement.cpp
+++ b/third_party/WebKit/Source/core/dom/PseudoElement.cpp
@@ -112,7 +112,7 @@
     RefPtrWillBeRawPtr<Element> parent = parentOrShadowHostElement();
     document().adoptIfNeeded(*this);
     setParentOrShadowHostNode(0);
-    removedFrom(parent.get(), nullptr);
+    removedFrom(parent.get());
 }
 
 void PseudoElement::attach(const AttachContext& context)
diff --git a/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.cpp b/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.cpp
index af68373..16d919d 100644
--- a/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.cpp
+++ b/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.cpp
@@ -223,7 +223,7 @@
     return InsertionDone;
 }
 
-void InsertionPoint::removedFrom(ContainerNode* insertionPoint, Node* next)
+void InsertionPoint::removedFrom(ContainerNode* insertionPoint)
 {
     ShadowRoot* root = containingShadowRoot();
     if (!root)
@@ -250,7 +250,7 @@
         }
     }
 
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
 }
 
 DEFINE_TRACE(InsertionPoint)
diff --git a/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.h b/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.h
index 528f1ca..7717a75 100644
--- a/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.h
+++ b/third_party/WebKit/Source/core/dom/shadow/InsertionPoint.h
@@ -75,7 +75,7 @@
     bool layoutObjectIsNeeded(const ComputedStyle&) override;
     void childrenChanged(const ChildrenChange&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void willRecalcStyle(StyleRecalcChange) override;
 
 private:
diff --git a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp
index 0d243d7f..0ad8b55 100644
--- a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp
+++ b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp
@@ -177,7 +177,7 @@
     return InsertionDone;
 }
 
-void ShadowRoot::removedFrom(ContainerNode* insertionPoint, Node* next)
+void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
 {
     if (insertionPoint->inDocument()) {
         document().styleEngine().shadowRootRemovedFromDocument(this);
@@ -191,7 +191,7 @@
         }
     }
 
-    DocumentFragment::removedFrom(insertionPoint, next);
+    DocumentFragment::removedFrom(insertionPoint);
 }
 
 void ShadowRoot::childrenChanged(const ChildrenChange& change)
diff --git a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h
index 93818ae6..c8591f002 100644
--- a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h
+++ b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h
@@ -87,7 +87,7 @@
     void attach(const AttachContext& = AttachContext()) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     void registerScopedHTMLStyleChild();
     void unregisterScopedHTMLStyleChild();
diff --git a/third_party/WebKit/Source/core/events/MouseEvent.cpp b/third_party/WebKit/Source/core/events/MouseEvent.cpp
index 519e0df6..8dd7480 100644
--- a/third_party/WebKit/Source/core/events/MouseEvent.cpp
+++ b/third_party/WebKit/Source/core/events/MouseEvent.cpp
@@ -148,15 +148,31 @@
     unsigned short buttons = 0;
 
     if (modifiers & PlatformEvent::LeftButtonDown)
-        buttons |= 1;
+        buttons |= static_cast<unsigned short>(Buttons::Left);
     if (modifiers & PlatformEvent::RightButtonDown)
-        buttons |= 2;
+        buttons |= static_cast<unsigned short>(Buttons::Right);
     if (modifiers & PlatformEvent::MiddleButtonDown)
-        buttons |= 4;
+        buttons |= static_cast<unsigned short>(Buttons::Middle);
 
     return buttons;
 }
 
+unsigned short MouseEvent::buttonToButtons(short button)
+{
+    switch (button) {
+    case NoButton:
+        return static_cast<unsigned short>(Buttons::None);
+    case LeftButton:
+        return static_cast<unsigned short>(Buttons::Left);
+    case RightButton:
+        return static_cast<unsigned short>(Buttons::Right);
+    case MiddleButton:
+        return static_cast<unsigned short>(Buttons::Middle);
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
 void MouseEvent::initMouseEvent(ScriptState* scriptState, const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView> view,
                                 int detail, int screenX, int screenY, int clientX, int clientY,
                                 bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
diff --git a/third_party/WebKit/Source/core/events/MouseEvent.h b/third_party/WebKit/Source/core/events/MouseEvent.h
index bc142d4..b3c5735c 100644
--- a/third_party/WebKit/Source/core/events/MouseEvent.h
+++ b/third_party/WebKit/Source/core/events/MouseEvent.h
@@ -60,6 +60,7 @@
     ~MouseEvent() override;
 
     static unsigned short platformModifiersToButtons(unsigned modifiers);
+    static unsigned short buttonToButtons(short button);
 
     void initMouseEvent(ScriptState*, const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView>,
         int detail, int screenX, int screenY, int clientX, int clientY,
@@ -68,7 +69,7 @@
 
     // WinIE uses 1,4,2 for left/middle/right but not for click (just for mousedown/up, maybe others),
     // but we will match the standard DOM.
-    short button() const { return m_button == -1 ? 0 : m_button; }
+    virtual short button() const { return m_button == -1 ? 0 : m_button; }
     unsigned short buttons() const { return m_buttons; }
     bool buttonDown() const { return m_button != -1; }
     EventTarget* relatedTarget() const { return m_relatedTarget.get(); }
@@ -89,6 +90,13 @@
 
     PassRefPtrWillBeRawPtr<EventDispatchMediator> createMediator() override;
 
+    enum class Buttons : unsigned {
+        None = 0,
+        Left = 1 << 0,
+        Right = 1 << 1,
+        Middle = 1 << 2
+    };
+
     DECLARE_VIRTUAL_TRACE();
 
 protected:
@@ -104,6 +112,8 @@
 
     MouseEvent();
 
+    short rawButton() const { return m_button; }
+
 private:
     friend class MouseEventDispatchMediator;
     void initMouseEventInternal(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView>,
diff --git a/third_party/WebKit/Source/core/events/PointerEvent.h b/third_party/WebKit/Source/core/events/PointerEvent.h
index ebbb789..0dcdbcda 100644
--- a/third_party/WebKit/Source/core/events/PointerEvent.h
+++ b/third_party/WebKit/Source/core/events/PointerEvent.h
@@ -34,6 +34,7 @@
     const String& pointerType() const { return m_pointerType; }
     bool isPrimary() const { return m_isPrimary; }
 
+    short button() const override { return rawButton(); }
     bool isMouseEvent() const override;
     bool isPointerEvent() const override;
 
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp
index 058e47d..e303d571 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.cpp
+++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -936,6 +936,9 @@
     case MediaStreamTrackGetSources:
         return "MediaStreamTrack.getSources is deprecated. See https://www.chromestatus.com/feature/4765305641369600 for more details.";
 
+    case CSSXGetComputedStyleQueries:
+        return "'getComputedStyle(e).cssXx' (except .cssFloat) is deprecated and will be removed in M50, around April 2016. Please use 'getComputedStyle(e).xx' instead.";
+
     // Features that aren't deprecated don't have a deprecation message.
     default:
         return String();
diff --git a/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp b/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp
index 2f1b3f9..d98ae0a 100644
--- a/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp
+++ b/third_party/WebKit/Source/core/html/FormAssociatedElement.cpp
@@ -96,7 +96,7 @@
         resetFormAttributeTargetObserver();
 }
 
-void FormAssociatedElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void FormAssociatedElement::removedFrom(ContainerNode* insertionPoint)
 {
     HTMLElement* element = toHTMLElement(this);
     if (insertionPoint->inDocument() && element->fastHasAttribute(formAttr)) {
diff --git a/third_party/WebKit/Source/core/html/FormAssociatedElement.h b/third_party/WebKit/Source/core/html/FormAssociatedElement.h
index 9b83025..73ce908 100644
--- a/third_party/WebKit/Source/core/html/FormAssociatedElement.h
+++ b/third_party/WebKit/Source/core/html/FormAssociatedElement.h
@@ -99,7 +99,7 @@
     FormAssociatedElement();
 
     void insertedInto(ContainerNode*);
-    void removedFrom(ContainerNode* insertionPoint, Node* next);
+    void removedFrom(ContainerNode*);
     void didMoveToNewDocument(Document& oldDocument);
 
     // FIXME: Remove usage of setForm. resetFormOwner should be enough, and
diff --git a/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp b/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp
index 0d6a2827..3348998 100644
--- a/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLBaseElement.cpp
@@ -56,9 +56,9 @@
     return InsertionDone;
 }
 
-void HTMLBaseElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLBaseElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
     if (insertionPoint->inDocument())
         document().processBaseElement();
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLBaseElement.h b/third_party/WebKit/Source/core/html/HTMLBaseElement.h
index d14bbd9..6d5d16af 100644
--- a/third_party/WebKit/Source/core/html/HTMLBaseElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLBaseElement.h
@@ -41,7 +41,7 @@
     bool isURLAttribute(const Attribute&) const override;
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp b/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp
index 8496675..03fb8129 100644
--- a/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp
@@ -171,9 +171,9 @@
     setFocusForDialog(this);
 }
 
-void HTMLDialogElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLDialogElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
     setNotCentered();
     // FIXME: We should call inertSubtreesChanged() here.
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLDialogElement.h b/third_party/WebKit/Source/core/html/HTMLDialogElement.h
index 52e9369..4a20fcc 100644
--- a/third_party/WebKit/Source/core/html/HTMLDialogElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLDialogElement.h
@@ -43,7 +43,7 @@
     void closeDialog(const String& returnValue = String());
     void show();
     void showModal(ExceptionState&);
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     // NotCentered means do not center the dialog. Centered means the dialog has
     // been centered and centeredPosition() is set. NeedsCentering means attempt
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
index 92e5d93..7847d89 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp
@@ -285,7 +285,7 @@
     return InsertionDone;
 }
 
-void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint)
 {
     fieldSetAncestorsSetNeedsValidityCheck(insertionPoint);
     hideVisibleValidationMessage();
@@ -293,8 +293,8 @@
     m_ancestorDisabledState = AncestorDisabledStateUnknown;
     m_dataListAncestorState = Unknown;
     setNeedsWillValidateCheck();
-    HTMLElement::removedFrom(insertionPoint, next);
-    FormAssociatedElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
+    FormAssociatedElement::removedFrom(insertionPoint);
     document().removeFormAssociation(this);
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElement.h b/third_party/WebKit/Source/core/html/HTMLFormControlElement.h
index bd245ef..aa34278 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormControlElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLFormControlElement.h
@@ -128,7 +128,7 @@
     virtual void disabledAttributeChanged();
     void attach(const AttachContext& = AttachContext()) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void willChangeForm() override;
     void didChangeForm() override;
     void didMoveToNewDocument(Document& oldDocument) override;
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp b/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp
index f0fdf919..88c2036 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.cpp
@@ -50,11 +50,11 @@
     return HTMLFormControlElement::insertedInto(insertionPoint);
 }
 
-void HTMLFormControlElementWithState::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLFormControlElementWithState::removedFrom(ContainerNode* insertionPoint)
 {
     if (insertionPoint->inDocument() && !containingShadowRoot() && !insertionPoint->containingShadowRoot())
         document().formController().unregisterStatefulFormControl(*this);
-    HTMLFormControlElement::removedFrom(insertionPoint, next);
+    HTMLFormControlElement::removedFrom(insertionPoint);
 }
 
 bool HTMLFormControlElementWithState::shouldAutocomplete() const
diff --git a/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h b/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h
index 88262d8..546e722 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h
+++ b/third_party/WebKit/Source/core/html/HTMLFormControlElementWithState.h
@@ -49,7 +49,7 @@
 
     void finishParsingChildren() override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     bool isFormControlElementWithState() const final;
 };
 
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
index 168d5b8..df13f4ae 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
@@ -165,7 +165,7 @@
         element->formRemovedFromTree(root);
 }
 
-void HTMLFormElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLFormElement::removedFrom(ContainerNode* insertionPoint)
 {
     // We don't need to take care of form association by 'form' content
     // attribute becuse IdTargetObserver handles it.
@@ -196,7 +196,7 @@
 #if ENABLE(OILPAN)
     document().formController().willDeleteForm(this);
 #endif
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
 }
 
 void HTMLFormElement::handleLocalEvents(Event& event)
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.h b/third_party/WebKit/Source/core/html/HTMLFormElement.h
index ead53a8..9bb909cb 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLFormElement.h
@@ -123,7 +123,7 @@
 
     bool layoutObjectIsNeeded(const ComputedStyle&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void finishParsingChildren() override;
 
     void handleLocalEvents(Event&) override;
diff --git a/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp b/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp
index 4168d7b4..43abe48 100644
--- a/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp
@@ -134,9 +134,9 @@
     return result;
 }
 
-void HTMLIFrameElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLIFrameElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLFrameElementBase::removedFrom(insertionPoint, next);
+    HTMLFrameElementBase::removedFrom(insertionPoint);
     if (insertionPoint->inDocument() && document().isHTMLDocument() && !insertionPoint->isInShadowTree())
         toHTMLDocument(document()).removeExtraNamedItem(m_name);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLIFrameElement.h b/third_party/WebKit/Source/core/html/HTMLIFrameElement.h
index 97d679d..3c52fda 100644
--- a/third_party/WebKit/Source/core/html/HTMLIFrameElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLIFrameElement.h
@@ -46,7 +46,7 @@
     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     bool layoutObjectIsNeeded(const ComputedStyle&) override;
     LayoutObject* createLayoutObject(const ComputedStyle&) override;
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index f61e6e7..858b47a 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -270,7 +270,7 @@
             if (text && text->textContent() != value)
                 text->setTextContent(altText());
         }
-    } else if (name == srcAttr || ((name == srcsetAttr || name == sizesAttr) && (value != oldValue))) {
+    } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) {
         selectSourceURL(ImageLoader::UpdateIgnorePreviousError);
     } else if (name == usemapAttr) {
         setIsLink(!value.isNull());
@@ -400,26 +400,19 @@
 
     // If we have been inserted from a layoutObject-less document,
     // our loader may have not fetched the image, so do it now.
-    if ((insertionPoint->inDocument() && !imageLoader().image()) || imageWasModified || isHTMLPictureElement(insertionPoint))
+    if ((insertionPoint->inDocument() && !imageLoader().image()) || imageWasModified)
         imageLoader().updateFromElement(ImageLoader::UpdateNormal, m_referrerPolicy);
 
     return HTMLElement::insertedInto(insertionPoint);
 }
 
-void HTMLImageElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLImageElement::removedFrom(ContainerNode* insertionPoint)
 {
     if (!m_form || NodeTraversal::highestAncestorOrSelf(*m_form.get()) != NodeTraversal::highestAncestorOrSelf(*this))
         resetFormOwner();
     if (m_listener)
         document().mediaQueryMatcher().removeViewportListener(m_listener);
-    HTMLElement::removedFrom(insertionPoint, next);
-
-    if (isHTMLPictureElement(insertionPoint)) {
-        // This is diverging from the spec because we don't want to trigger spurious downloads of fallback images.
-        // See https://github.com/ResponsiveImagesCG/picture-element/issues/274
-        m_bestFitImageURL = AtomicString();
-        imageLoader().updateFromElement(ImageLoader::UpdateNormal, m_referrerPolicy);
-    }
+    HTMLElement::removedFrom(insertionPoint);
 }
 
 int HTMLImageElement::width()
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.h b/third_party/WebKit/Source/core/html/HTMLImageElement.h
index e3c936e..1191799e6 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.h
@@ -148,7 +148,7 @@
     bool draggable() const override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     bool shouldRegisterAsNamedItem() const override { return true; }
     bool shouldRegisterAsExtraNamedItem() const override { return true; }
     bool isInteractiveContent() const override;
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
index 42851a4e..78231df 100644
--- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
@@ -1515,12 +1515,12 @@
     return InsertionShouldCallDidNotifySubtreeInsertions;
 }
 
-void HTMLInputElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLInputElement::removedFrom(ContainerNode* insertionPoint)
 {
     m_inputTypeView->closePopupView();
     if (insertionPoint->inDocument() && !form())
         removeFromRadioButtonGroup();
-    HTMLTextFormControlElement::removedFrom(insertionPoint, next);
+    HTMLTextFormControlElement::removedFrom(insertionPoint);
     ASSERT(!inDocument());
     resetListAttributeTargetObserver();
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.h b/third_party/WebKit/Source/core/html/HTMLInputElement.h
index 9227523..8dd5bd2 100644
--- a/third_party/WebKit/Source/core/html/HTMLInputElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLInputElement.h
@@ -280,7 +280,7 @@
     void willChangeForm() final;
     void didChangeForm() final;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) final;
+    void removedFrom(ContainerNode*) final;
     void didMoveToNewDocument(Document& oldDocument) final;
     void removeAllEventListeners() final;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp b/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp
index fb13d31..52932b1 100644
--- a/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLabelElement.cpp
@@ -252,15 +252,15 @@
     return result;
 }
 
-void HTMLLabelElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLLabelElement::removedFrom(ContainerNode* insertionPoint)
 {
     if (insertionPoint->isInTreeScope() && treeScope() == document()) {
         TreeScope& treeScope = insertionPoint->treeScope();
         if (treeScope.shouldCacheLabelsByForAttribute())
             updateLabel(treeScope, fastGetAttribute(forAttr), nullAtom);
     }
-    HTMLElement::removedFrom(insertionPoint, next);
-    FormAssociatedElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
+    FormAssociatedElement::removedFrom(insertionPoint);
     document().removeFormAssociation(this);
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLLabelElement.h b/third_party/WebKit/Source/core/html/HTMLLabelElement.h
index ee6516e..fcdf958 100644
--- a/third_party/WebKit/Source/core/html/HTMLLabelElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLLabelElement.h
@@ -58,7 +58,7 @@
     void accessKeyAction(bool sendMouseEvents) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     // Overridden to update the hover/active state of the corresponding control.
     void setActive(bool = true) override;
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
index 2d41712a..4b3082f 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -283,9 +283,9 @@
     return InsertionDone;
 }
 
-void HTMLLinkElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLLinkElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
     if (!insertionPoint->inDocument())
         return;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.h b/third_party/WebKit/Source/core/html/HTMLLinkElement.h
index 4c998441..42d102b5 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.h
@@ -194,7 +194,7 @@
     // From Node and subclassses
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     bool isURLAttribute(const Attribute&) const override;
     bool hasLegalLinkAttribute(const QualifiedName&) const override;
     const QualifiedName& subResourceAttributeName() const override;
diff --git a/third_party/WebKit/Source/core/html/HTMLMapElement.cpp b/third_party/WebKit/Source/core/html/HTMLMapElement.cpp
index 8a817ac..d1e48c2 100644
--- a/third_party/WebKit/Source/core/html/HTMLMapElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMapElement.cpp
@@ -117,11 +117,11 @@
     return HTMLElement::insertedInto(insertionPoint);
 }
 
-void HTMLMapElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLMapElement::removedFrom(ContainerNode* insertionPoint)
 {
     if (insertionPoint->inDocument())
         treeScope().removeImageMap(this);
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
 }
 
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLMapElement.h b/third_party/WebKit/Source/core/html/HTMLMapElement.h
index 976243b1..9afd66b0 100644
--- a/third_party/WebKit/Source/core/html/HTMLMapElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMapElement.h
@@ -50,7 +50,7 @@
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     AtomicString m_name;
 };
diff --git a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
index 5e41579e..95a8d107 100644
--- a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
@@ -63,9 +63,9 @@
     return InsertionDone;
 }
 
-void HTMLMarqueeElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLMarqueeElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
     if (insertionPoint->inDocument()) {
         V8HTMLMarqueeElement::PrivateScript::detachedCallbackMethod(insertionPoint->document().frame(), this);
     }
diff --git a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h
index 3e19ee9..8446b08 100644
--- a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.h
@@ -34,7 +34,7 @@
 
     void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason) final;
     InsertionNotificationRequest insertedInto(ContainerNode*) final;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) final;
+    void removedFrom(ContainerNode*) final;
 
     bool isHorizontal() const;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index 77aa5fe3..5a36203a 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -551,11 +551,11 @@
     configureMediaControls();
 }
 
-void HTMLMediaElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLMediaElement::removedFrom(ContainerNode* insertionPoint)
 {
     WTF_LOG(Media, "HTMLMediaElement::removedFrom(%p, %p)", this, insertionPoint);
 
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
     if (insertionPoint->inActiveDocument()) {
         configureMediaControls();
         if (m_networkState > NETWORK_EMPTY)
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
index 3fb86a6..5a29fd6b 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -292,7 +292,7 @@
     LayoutObject* createLayoutObject(const ComputedStyle&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) final;
     void didNotifySubtreeInsertionsToDocument() override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) final;
+    void removedFrom(ContainerNode*) final;
     void didRecalcStyle(StyleRecalcChange) final;
 
     bool canStartSelection() const override { return false; }
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
index be530ee..bab324a 100644
--- a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
@@ -312,10 +312,10 @@
     return InsertionDone;
 }
 
-void HTMLObjectElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLObjectElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLPlugInElement::removedFrom(insertionPoint, next);
-    FormAssociatedElement::removedFrom(insertionPoint, next);
+    HTMLPlugInElement::removedFrom(insertionPoint);
+    FormAssociatedElement::removedFrom(insertionPoint);
 }
 
 void HTMLObjectElement::childrenChanged(const ChildrenChange& change)
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.h b/third_party/WebKit/Source/core/html/HTMLObjectElement.h
index 7410220..1a7970a 100644
--- a/third_party/WebKit/Source/core/html/HTMLObjectElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.h
@@ -79,7 +79,7 @@
     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     void didMoveToNewDocument(Document& oldDocument) override;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
index 94c04ce..07ba7a7 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLOptionElement.cpp
@@ -389,7 +389,7 @@
     return InsertionDone;
 }
 
-void HTMLOptionElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLOptionElement::removedFrom(ContainerNode* insertionPoint)
 {
     if (isHTMLSelectElement(*insertionPoint)) {
         if (!parentNode() || isHTMLOptGroupElement(*parentNode()))
@@ -399,7 +399,7 @@
         if (isHTMLSelectElement(parent))
             toHTMLSelectElement(parent)->optionRemoved(*this);
     }
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
 }
 
 String HTMLOptionElement::collectOptionInnerText() const
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionElement.h b/third_party/WebKit/Source/core/html/HTMLOptionElement.h
index 65602a9..6202ec4 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptionElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLOptionElement.h
@@ -94,7 +94,7 @@
     void detach(const AttachContext& = AttachContext()) override;
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void accessKeyAction(bool) override;
     void childrenChanged(const ChildrenChange&) override;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLPictureElement.cpp b/third_party/WebKit/Source/core/html/HTMLPictureElement.cpp
index a3d1ab40..f71379d 100644
--- a/third_party/WebKit/Source/core/html/HTMLPictureElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLPictureElement.cpp
@@ -9,7 +9,6 @@
 #include "core/dom/ElementTraversal.h"
 #include "core/frame/UseCounter.h"
 #include "core/html/HTMLImageElement.h"
-#include "core/html/HTMLSourceElement.h"
 #include "core/loader/ImageLoader.h"
 
 namespace blink {
@@ -23,19 +22,10 @@
 
 DEFINE_NODE_FACTORY(HTMLPictureElement)
 
-void HTMLPictureElement::sourceOrMediaChanged(HTMLElement* sourceElement, Node* next)
+void HTMLPictureElement::sourceOrMediaChanged()
 {
-    bool seenSource = false;
-    Node* node;
-    NodeVector potentialSourceNodes;
-    getChildNodes(*this, potentialSourceNodes);
-
-    for (unsigned i = 0; i < potentialSourceNodes.size(); ++i) {
-        node = potentialSourceNodes[i].get();
-        if (sourceElement == node || (next && node == next))
-            seenSource = true;
-        if (isHTMLImageElement(node) && seenSource)
-            toHTMLImageElement(node)->selectSourceURL(ImageLoader::UpdateNormal);
+    for (HTMLImageElement* imageElement = Traversal<HTMLImageElement>::firstChild(*this); imageElement; imageElement = Traversal<HTMLImageElement>::nextSibling(*imageElement)) {
+        imageElement->selectSourceURL(ImageLoader::UpdateNormal);
     }
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLPictureElement.h b/third_party/WebKit/Source/core/html/HTMLPictureElement.h
index 1fc9f970..80b44db4 100644
--- a/third_party/WebKit/Source/core/html/HTMLPictureElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLPictureElement.h
@@ -14,7 +14,7 @@
 public:
     DECLARE_NODE_FACTORY(HTMLPictureElement);
 
-    void sourceOrMediaChanged(HTMLElement*, Node* next = nullptr);
+    void sourceOrMediaChanged();
 
 protected:
     explicit HTMLPictureElement(Document&);
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
index 882aed5..edf7ca7 100644
--- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -230,7 +230,7 @@
     }
 }
 
-void HTMLPlugInElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLPlugInElement::removedFrom(ContainerNode* insertionPoint)
 {
     // If we've persisted the plugin and we're removed from the tree then
     // make sure we cleanup the persistance pointer.
@@ -238,7 +238,7 @@
         HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
         setPersistedPluginWidget(nullptr);
     }
-    HTMLFrameOwnerElement::removedFrom(insertionPoint, next);
+    HTMLFrameOwnerElement::removedFrom(insertionPoint);
 }
 
 void HTMLPlugInElement::requestPluginCreationWithoutLayoutObjectIfPossible()
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.h b/third_party/WebKit/Source/core/html/HTMLPlugInElement.h
index afe27dc4..da253c3 100644
--- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.h
@@ -69,7 +69,7 @@
     void requestPluginCreationWithoutLayoutObjectIfPossible();
     void createPluginWithoutLayoutObject();
 
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode* insertionPoint) override;
 
 protected:
     HTMLPlugInElement(const QualifiedName& tagName, Document&, bool createdByParser, PreferPlugInsForImagesOption);
diff --git a/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp b/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
index 8e5b1eff..36f820d 100644
--- a/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
@@ -108,20 +108,20 @@
     if (isHTMLMediaElement(parent))
         toHTMLMediaElement(parent)->sourceWasAdded(this);
     if (isHTMLPictureElement(parent))
-        toHTMLPictureElement(parent)->sourceOrMediaChanged(this);
+        toHTMLPictureElement(parent)->sourceOrMediaChanged();
     return InsertionDone;
 }
 
-void HTMLSourceElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLSourceElement::removedFrom(ContainerNode* removalRoot)
 {
     Element* parent = parentElement();
-    if (!parent && insertionPoint->isElementNode())
-        parent = toElement(insertionPoint);
+    if (!parent && removalRoot->isElementNode())
+        parent = toElement(removalRoot);
     if (isHTMLMediaElement(parent))
         toHTMLMediaElement(parent)->sourceWasRemoved(this);
     if (isHTMLPictureElement(parent))
-        toHTMLPictureElement(parent)->sourceOrMediaChanged(this, next);
-    HTMLElement::removedFrom(insertionPoint, next);
+        toHTMLPictureElement(parent)->sourceOrMediaChanged();
+    HTMLElement::removedFrom(removalRoot);
 }
 
 void HTMLSourceElement::setSrc(const String& url)
@@ -179,7 +179,7 @@
     if (name == srcsetAttr || name == sizesAttr || name == mediaAttr || name == typeAttr) {
         Element* parent = parentElement();
         if (isHTMLPictureElement(parent))
-            toHTMLPictureElement(parent)->sourceOrMediaChanged(this);
+            toHTMLPictureElement(parent)->sourceOrMediaChanged();
     }
 }
 
@@ -187,7 +187,7 @@
 {
     Element* parent = parentElement();
     if (isHTMLPictureElement(parent))
-        toHTMLPictureElement(parent)->sourceOrMediaChanged(this);
+        toHTMLPictureElement(parent)->sourceOrMediaChanged();
 }
 
 DEFINE_TRACE(HTMLSourceElement)
diff --git a/third_party/WebKit/Source/core/html/HTMLSourceElement.h b/third_party/WebKit/Source/core/html/HTMLSourceElement.h
index fb395d38..35b4229 100644
--- a/third_party/WebKit/Source/core/html/HTMLSourceElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLSourceElement.h
@@ -62,7 +62,7 @@
     void didMoveToNewDocument(Document& oldDocument) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     bool isURLAttribute(const Attribute&) const override;
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp b/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp
index 030fd112..f562876 100644
--- a/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLStyleElement.cpp
@@ -90,9 +90,9 @@
     return InsertionShouldCallDidNotifySubtreeInsertions;
 }
 
-void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLStyleElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
     StyleElement::removedFrom(this, insertionPoint);
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLStyleElement.h b/third_party/WebKit/Source/core/html/HTMLStyleElement.h
index 668e104..476052b 100644
--- a/third_party/WebKit/Source/core/html/HTMLStyleElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLStyleElement.h
@@ -57,7 +57,7 @@
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
     void didNotifySubtreeInsertionsToDocument() override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void childrenChanged(const ChildrenChange&) override;
 
     void finishParsingChildren() override;
diff --git a/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp b/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp
index 94e5126..30e6735b 100644
--- a/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTitleElement.cpp
@@ -52,9 +52,9 @@
     return InsertionDone;
 }
 
-void HTMLTitleElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLTitleElement::removedFrom(ContainerNode* insertionPoint)
 {
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
     if (insertionPoint->inDocument() && !insertionPoint->isInShadowTree())
         document().removeTitle(this);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLTitleElement.h b/third_party/WebKit/Source/core/html/HTMLTitleElement.h
index 6457653..a68f395 100644
--- a/third_party/WebKit/Source/core/html/HTMLTitleElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLTitleElement.h
@@ -38,7 +38,7 @@
     explicit HTMLTitleElement(Document&);
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void childrenChanged(const ChildrenChange&) override;
 
     bool m_ignoreTitleUpdatesWhenChildrenChange;
diff --git a/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp b/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp
index 4413a04..07e7acf1 100644
--- a/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTrackElement.cpp
@@ -81,11 +81,11 @@
     return InsertionDone;
 }
 
-void HTMLTrackElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void HTMLTrackElement::removedFrom(ContainerNode* insertionPoint)
 {
     if (!parentNode() && isHTMLMediaElement(*insertionPoint))
         toHTMLMediaElement(insertionPoint)->didRemoveTrackElement(this);
-    HTMLElement::removedFrom(insertionPoint, next);
+    HTMLElement::removedFrom(insertionPoint);
 }
 
 void HTMLTrackElement::parseAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& value)
diff --git a/third_party/WebKit/Source/core/html/HTMLTrackElement.h b/third_party/WebKit/Source/core/html/HTMLTrackElement.h
index c07ab0e..8d1d1990 100644
--- a/third_party/WebKit/Source/core/html/HTMLTrackElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLTrackElement.h
@@ -65,7 +65,7 @@
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
 
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     bool isURLAttribute(const Attribute&) const override;
 
     // TextTrackLoaderClient
diff --git a/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.cpp b/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.cpp
new file mode 100644
index 0000000..94e7e62b5
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.cpp
@@ -0,0 +1,36 @@
+// Copyright 2015 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 "config.h"
+#include "core/html/canvas/OffScreenCanvas.h"
+
+#include "wtf/MathExtras.h"
+
+namespace blink {
+
+OffScreenCanvas* OffScreenCanvas::create(unsigned width, unsigned height)
+{
+    return new OffScreenCanvas(IntSize(clampTo<int>(width), clampTo<int>(height)));
+}
+
+void OffScreenCanvas::setWidth(unsigned width)
+{
+    m_size.setWidth(clampTo<int>(width));
+}
+
+void OffScreenCanvas::setHeight(unsigned height)
+{
+    m_size.setHeight(clampTo<int>(height));
+}
+
+OffScreenCanvas::OffScreenCanvas(const IntSize& size)
+    : m_size(size)
+{
+}
+
+DEFINE_TRACE(OffScreenCanvas)
+{
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.h b/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.h
new file mode 100644
index 0000000..1f24801
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.h
@@ -0,0 +1,39 @@
+// Copyright 2015 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 OffScreenCanvas_h
+#define OffScreenCanvas_h
+
+#include "bindings/core/v8/ScriptPromise.h"
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "core/CoreExport.h"
+#include "platform/geometry/IntSize.h"
+#include "platform/heap/Handle.h"
+
+namespace blink {
+
+class CORE_EXPORT OffScreenCanvas final : public GarbageCollectedFinalized<OffScreenCanvas>, public ScriptWrappable {
+    DEFINE_WRAPPERTYPEINFO();
+public:
+    static OffScreenCanvas* create(unsigned width, unsigned height);
+
+    IntSize size() const { return m_size; }
+    unsigned width() const { return m_size.width(); }
+    unsigned height() const { return m_size.height(); }
+
+    void setWidth(unsigned);
+    void setHeight(unsigned);
+
+    DECLARE_VIRTUAL_TRACE();
+
+private:
+    OffScreenCanvas(const IntSize&);
+
+    IntSize m_size;
+};
+
+} // namespace blink
+
+#endif // OffScreenCanvas_h
diff --git a/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.idl b/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.idl
new file mode 100644
index 0000000..32afa8a
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/canvas/OffScreenCanvas.idl
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+[
+    Constructor([EnforceRange] unsigned long width, [EnforceRange] unsigned long height),
+    GarbageCollected,
+    RuntimeEnabled=ExperimentalCanvasFeatures,
+] interface OffScreenCanvas {
+    [EnforceRange] attribute unsigned long width;
+    [EnforceRange] attribute unsigned long height;
+};
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp
index ccc83bc..a098b72 100644
--- a/third_party/WebKit/Source/core/input/EventHandler.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -1785,13 +1785,19 @@
     if (!m_nodeUnderMouse)
         return WebInputEventResult::NotHandled;
 
-    WebInputEventResult result = dispatchPointerEvent(m_nodeUnderMouse.get(),
-        pointerEventNameForMouseEventName(mouseEventType),
-        mouseEvent);
+    AtomicString pointerEventType = pointerEventNameForMouseEventName(mouseEventType);
+    unsigned short pointerButtonsPressed = MouseEvent::platformModifiersToButtons(mouseEvent.modifiers());
 
-    if (result != WebInputEventResult::NotHandled && mouseEventType == EventTypeNames::mousedown) {
+    // Make sure chorded buttons fire pointermove instead of pointerup/pointerdown.
+    if ((pointerEventType == EventTypeNames::pointerdown && (pointerButtonsPressed & ~MouseEvent::buttonToButtons(mouseEvent.button())) != 0)
+        || (pointerEventType == EventTypeNames::pointerup && pointerButtonsPressed != 0))
+        pointerEventType = EventTypeNames::pointermove;
+
+    WebInputEventResult result = dispatchPointerEvent(
+        m_nodeUnderMouse.get(), pointerEventType, mouseEvent);
+
+    if (result != WebInputEventResult::NotHandled && pointerEventType == EventTypeNames::pointerdown)
         m_preventMouseEventForPointerTypeMouse = true;
-    }
 
     if (!m_preventMouseEventForPointerTypeMouse) {
         RefPtrWillBeRawPtr<MouseEvent> event = MouseEvent::create(mouseEventType, m_nodeUnderMouse->document().domWindow(), mouseEvent, clickCount, nullptr);
@@ -2949,9 +2955,6 @@
     if (!doc)
         return WebInputEventResult::NotHandled;
 
-    // Clear mouse press state to avoid initiating a drag while context menu is up.
-    m_mousePressed = false;
-
     static const int kContextMenuMargin = 1;
 
 #if OS(WIN)
diff --git a/third_party/WebKit/Source/core/input/EventHandler.h b/third_party/WebKit/Source/core/input/EventHandler.h
index 415bf70..cd06e11 100644
--- a/third_party/WebKit/Source/core/input/EventHandler.h
+++ b/third_party/WebKit/Source/core/input/EventHandler.h
@@ -361,7 +361,10 @@
 
     const RawPtrWillBeMember<LocalFrame> m_frame;
 
+    // Current button-press state for mouse/mouse-like-stylus.
+    // TODO(crbug.com/563676): Buggy for chorded buttons.
     bool m_mousePressed;
+
     bool m_capturesDragging;
     RefPtrWillBeMember<Node> m_mousePressNode;
 
diff --git a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
index 6df3a735..2715210 100644
--- a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
@@ -78,7 +78,7 @@
         LeftButton,
         PlatformEvent::MousePressed,
         1,
-        static_cast<PlatformEvent::Modifiers>(0),
+        PlatformEvent::Modifiers::LeftButtonDown,
         WTF::monotonicallyIncreasingTime());
     document().frame()->eventHandler().handleMousePressEvent(mouseDownEvent);
 
@@ -88,7 +88,7 @@
         LeftButton,
         PlatformEvent::MouseMoved,
         1,
-        static_cast<PlatformEvent::Modifiers>(0),
+        PlatformEvent::Modifiers::LeftButtonDown,
         WTF::monotonicallyIncreasingTime());
     document().frame()->eventHandler().handleMouseMoveEvent(mouseMoveEvent);
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
index 90ee7c6..3e18330 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -60,7 +60,6 @@
 #include "core/layout/line/InlineIterator.h"
 #include "core/layout/line/InlineTextBox.h"
 #include "core/layout/shapes/ShapeOutsideInfo.h"
-#include "core/layout/svg/LayoutSVGResourceClipper.h"
 #include "core/page/Page.h"
 #include "core/paint/BlockPainter.h"
 #include "core/paint/BoxPainter.h"
@@ -1632,6 +1631,8 @@
     return isAnonymousBlockContinuation() ? continuation()->node() : node();
 }
 
+// TODO(pdr): This is too similar to LayoutBox::nodeAtPoint and should share
+//            more code, or merge into LayoutBox::nodeAtPoint entirely.
 bool LayoutBlock::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
 {
     LayoutPoint adjustedLocation(accumulatedOffset + location());
@@ -1656,31 +1657,16 @@
             return true;
     }
 
-    if (style()->clipPath()) {
-        switch (style()->clipPath()->type()) {
-        case ClipPathOperation::SHAPE: {
-            ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style()->clipPath());
-            // FIXME: handle marginBox etc.
-            if (!clipPath->path(FloatRect(borderBoxRect())).contains(FloatPoint(locationInContainer.point() - localOffset), clipPath->windRule()))
-                return false;
-            break;
-        }
-        case ClipPathOperation::REFERENCE:
-            ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClipPathOperation(style()->clipPath());
-            Element* element = document().getElementById(referenceClipPathOperation->fragment());
-            if (isSVGClipPathElement(element) && element->layoutObject()) {
-                LayoutSVGResourceClipper* clipper = toLayoutSVGResourceClipper(toLayoutSVGResourceContainer(element->layoutObject()));
-                if (!clipper->hitTestClipContent(FloatRect(borderBoxRect()), FloatPoint(locationInContainer.point() - localOffset)))
-                    return false;
-            }
-            break;
-        }
-    }
+    // Clip path hit testing should already be handled by PaintLayer.
+    ASSERT(!hitTestClippedOutByClipPath(locationInContainer, adjustedLocation));
+
+    // TODO(pdr): We should also check for css clip in the !isSelfPaintingLayer
+    //            case, similar to overflow clip below.
 
     bool checkChildren = true;
 
-    // Self painting layers will handle overflow clip in most cases, but without one we need to
-    // check if overflip clip will affect child hit testing.
+    // TODO(pdr): We should also include checks for hit testing border radius at
+    //            the layer level (see: crbug.com/568904).
     if (hasOverflowClip() && !hasSelfPaintingLayer()) {
         if (style()->hasBorderRadius()) {
             LayoutRect borderRect = borderBoxRect();
@@ -1710,13 +1696,8 @@
             return true;
     }
 
-    // Check if the point is outside radii.
-    if (style()->hasBorderRadius()) {
-        LayoutRect borderRect = borderBoxRect();
-        borderRect.moveBy(adjustedLocation);
-        if (!locationInContainer.intersects(style()->getRoundedBorderFor(borderRect)))
-            return false;
-    }
+    if (hitTestClippedOutByRoundedBorder(locationInContainer, adjustedLocation))
+        return false;
 
     // Now hit test our background
     if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 4426b10..31f903a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -54,6 +54,7 @@
 #include "core/layout/LayoutView.h"
 #include "core/layout/compositing/PaintLayerCompositor.h"
 #include "core/layout/shapes/ShapeOutsideInfo.h"
+#include "core/layout/svg/LayoutSVGResourceClipper.h"
 #include "core/page/AutoscrollController.h"
 #include "core/page/Page.h"
 #include "core/paint/BackgroundImageGeometry.h"
@@ -1173,9 +1174,14 @@
     // Exit early if no children can be hit.
     LayoutRect overflowRect = visualOverflowRect();
     overflowRect.moveBy(adjustedLocation);
-    if (!locationInContainer.intersects(overflowRect)) {
+    if (!locationInContainer.intersects(overflowRect))
         return false;
-    }
+
+    // Clip path hit testing should already be handled by PaintLayer.
+    ASSERT(!hitTestClippedOutByClipPath(locationInContainer, adjustedLocation));
+
+    // TODO(pdr): We should also check for css clip in the !isSelfPaintingLayer
+    //            case, similar to overflow clip in LayoutBlock::nodeAtPoint.
 
     // Check kids first.
     for (LayoutObject* child = slowLastChild(); child; child = child->previousSibling()) {
@@ -1185,6 +1191,9 @@
         }
     }
 
+    if (hitTestClippedOutByRoundedBorder(locationInContainer, adjustedLocation))
+        return false;
+
     // Check our bounds next. For this purpose always assume that we can only be hit in the
     // foreground phase (which is true for replaced elements like images).
     LayoutRect boundsRect = borderBoxRect();
@@ -1198,6 +1207,40 @@
     return false;
 }
 
+bool LayoutBox::hitTestClippedOutByClipPath(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const
+{
+    if (!style()->clipPath())
+        return false;
+
+    if (style()->clipPath()->type() == ClipPathOperation::SHAPE) {
+        ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style()->clipPath());
+        // FIXME: handle marginBox etc.
+        if (!clipPath->path(FloatRect(borderBoxRect())).contains(FloatPoint(locationInContainer.point() - toLayoutSize(accumulatedOffset)), clipPath->windRule()))
+            return true;
+    } else {
+        ASSERT(style()->clipPath()->type() == ClipPathOperation::REFERENCE);
+        ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClipPathOperation(style()->clipPath());
+        Element* element = document().getElementById(referenceClipPathOperation->fragment());
+        if (isSVGClipPathElement(element) && element->layoutObject()) {
+            LayoutSVGResourceClipper* clipper = toLayoutSVGResourceClipper(toLayoutSVGResourceContainer(element->layoutObject()));
+            if (!clipper->hitTestClipContent(FloatRect(borderBoxRect()), FloatPoint(locationInContainer.point() - toLayoutSize(accumulatedOffset))))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+bool LayoutBox::hitTestClippedOutByRoundedBorder(const HitTestLocation& locationInContainer, const LayoutPoint& borderBoxLocation) const
+{
+    if (!style()->hasBorderRadius())
+        return false;
+
+    LayoutRect borderRect = borderBoxRect();
+    borderRect.moveBy(borderBoxLocation);
+    return !locationInContainer.intersects(style()->getRoundedBorderFor(borderRect));
+}
+
 void LayoutBox::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const
 {
     BoxPainter(*this).paint(paintInfo, paintOffset);
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h
index 2e4ebe4b..93ae1b4 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -491,6 +491,8 @@
     void paint(const PaintInfo&, const LayoutPoint&) const override;
     bool nodeAtPoint(HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
 
+    bool hitTestClippedOutByClipPath(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const;
+
     LayoutUnit minPreferredLogicalWidth() const override;
     LayoutUnit maxPreferredLogicalWidth() const override;
 
@@ -874,6 +876,8 @@
     void addLayerHitTestRects(LayerHitTestRects&, const PaintLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const override;
     void computeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layerOffset) const override;
 
+    bool hitTestClippedOutByRoundedBorder(const HitTestLocation& locationInContainer, const LayoutPoint& borderBoxLocation) const;
+
     PaintInvalidationReason paintInvalidationReason(const LayoutBoxModelObject& paintInvalidationContainer,
         const LayoutRect& oldBounds, const LayoutPoint& oldPositionFromPaintInvalidationContainer,
         const LayoutRect& newBounds, const LayoutPoint& newPositionFromPaintInvalidationContainer) const override;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h
index 8e55591..4de0b8dc 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h
@@ -31,6 +31,7 @@
 
 namespace blink {
 
+class LineLayoutBoxModel;
 class PaintLayer;
 class PaintLayerScrollableArea;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutImage.cpp b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
index 87eedf88..0c85625 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImage.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
@@ -244,9 +244,11 @@
     ObjectFit objectFit = style()->objectFit();
     if (objectFit != ObjectFitFill && objectFit != ObjectFitCover)
         return false;
+    if (!m_imageResource->cachedImage())
+        return false;
     // Check for image with alpha.
     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(this, *m_imageResource->cachedImage()));
-    return m_imageResource->cachedImage() && m_imageResource->cachedImage()->image()->currentFrameKnownToBeOpaque(Image::PreCacheMetadata);
+    return m_imageResource->cachedImage()->image()->currentFrameKnownToBeOpaque(Image::PreCacheMetadata);
 }
 
 bool LayoutImage::computeBackgroundIsKnownToBeObscured() const
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index 928bf82..a45e243 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -726,12 +726,12 @@
 
     Node* node() const
     {
-        return isAnonymous() ? nullptr : m_node;
+        return isAnonymous() ? 0 : m_node;
     }
 
     Node* nonPseudoNode() const
     {
-        return isPseudoElement() ? nullptr : node();
+        return isPseudoElement() ? 0 : node();
     }
 
     void clearNode() { m_node = nullptr; }
@@ -1545,8 +1545,9 @@
 
     RefPtr<ComputedStyle> m_style;
 
-    // Oilpan: This untraced pointer to the owning Node is considered safe.
-    RawPtrWillBeUntracedMember<Node> m_node;
+    // Oilpan: raw pointer back to the owning Node is considered safe.
+    GC_PLUGIN_IGNORE("http://crbug.com/509911")
+    Node* m_node;
 
     LayoutObject* m_parent;
     LayoutObject* m_previous;
diff --git a/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp b/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp
index 1e819cb8..6ab1d222 100644
--- a/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp
@@ -242,21 +242,21 @@
 
     if (needLayoutObject && partStyle->display() != BLOCK) {
         // See if we are a button that should not be visible according to OS settings.
-        ScrollbarButtonsPlacement buttonsPlacement = theme().buttonsPlacement();
+        WebScrollbarButtonsPlacement buttonsPlacement = theme().buttonsPlacement();
         switch (partType) {
         case BackButtonStartPart:
-            needLayoutObject = (buttonsPlacement == ScrollbarButtonsPlacementSingle || buttonsPlacement == ScrollbarButtonsPlacementDoubleStart
-                || buttonsPlacement == ScrollbarButtonsPlacementDoubleBoth);
+            needLayoutObject = (buttonsPlacement == WebScrollbarButtonsPlacementSingle || buttonsPlacement == WebScrollbarButtonsPlacementDoubleStart
+                || buttonsPlacement == WebScrollbarButtonsPlacementDoubleBoth);
             break;
         case ForwardButtonStartPart:
-            needLayoutObject = (buttonsPlacement == ScrollbarButtonsPlacementDoubleStart || buttonsPlacement == ScrollbarButtonsPlacementDoubleBoth);
+            needLayoutObject = (buttonsPlacement == WebScrollbarButtonsPlacementDoubleStart || buttonsPlacement == WebScrollbarButtonsPlacementDoubleBoth);
             break;
         case BackButtonEndPart:
-            needLayoutObject = (buttonsPlacement == ScrollbarButtonsPlacementDoubleEnd || buttonsPlacement == ScrollbarButtonsPlacementDoubleBoth);
+            needLayoutObject = (buttonsPlacement == WebScrollbarButtonsPlacementDoubleEnd || buttonsPlacement == WebScrollbarButtonsPlacementDoubleBoth);
             break;
         case ForwardButtonEndPart:
-            needLayoutObject = (buttonsPlacement == ScrollbarButtonsPlacementSingle || buttonsPlacement == ScrollbarButtonsPlacementDoubleEnd
-                || buttonsPlacement == ScrollbarButtonsPlacementDoubleBoth);
+            needLayoutObject = (buttonsPlacement == WebScrollbarButtonsPlacementSingle || buttonsPlacement == WebScrollbarButtonsPlacementDoubleEnd
+                || buttonsPlacement == WebScrollbarButtonsPlacementDoubleBoth);
             break;
         default:
             break;
diff --git a/third_party/WebKit/Source/core/layout/LayoutScrollbarTheme.h b/third_party/WebKit/Source/core/layout/LayoutScrollbarTheme.h
index c70b2911..56d70bd 100644
--- a/third_party/WebKit/Source/core/layout/LayoutScrollbarTheme.h
+++ b/third_party/WebKit/Source/core/layout/LayoutScrollbarTheme.h
@@ -38,7 +38,7 @@
 
     int scrollbarThickness(ScrollbarControlSize controlSize) override { return ScrollbarTheme::theme().scrollbarThickness(controlSize); }
 
-    ScrollbarButtonsPlacement buttonsPlacement() const override { return ScrollbarTheme::theme().buttonsPlacement(); }
+    WebScrollbarButtonsPlacement buttonsPlacement() const override { return ScrollbarTheme::theme().buttonsPlacement(); }
 
     void paintScrollCorner(GraphicsContext&, const DisplayItemClient&, const IntRect& cornerRect) override;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.h b/third_party/WebKit/Source/core/layout/LayoutView.h
index 7f18e7d..0a8e984 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.h
+++ b/third_party/WebKit/Source/core/layout/LayoutView.h
@@ -229,7 +229,8 @@
     int viewLogicalWidthForBoxSizing() const;
     int viewLogicalHeightForBoxSizing() const;
 
-    RawPtrWillBeUntracedMember<FrameView> m_frameView;
+    GC_PLUGIN_IGNORE("http://crbug.com/509911")
+    FrameView* m_frameView;
 
     // The current selection represented as 2 boundaries.
     // Selection boundaries are represented in LayoutView by a tuple
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h b/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h
index dd6ef69..abba975 100644
--- a/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutInline.h
@@ -97,6 +97,11 @@
         return toInline()->hitTestCulledInline(result, locationInContainer, accumulatedOffset);
     }
 
+    LayoutBoxModelObject* continuation() const
+    {
+        return toInline()->continuation();
+    }
+
 protected:
     LayoutInline* toInline()
     {
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp
index 543b247d..851df37 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositingInputsUpdater.cpp
@@ -134,12 +134,6 @@
                 const PaintLayer* parentLayerOnClippingContainerChain = findParentLayerOnClippingContainerChain(layer);
                 const bool parentHasClipOrOverflowClip = parentLayerOnClippingContainerChain->layoutObject()->hasClipOrOverflowClip();
                 properties.clippingContainer = parentHasClipOrOverflowClip ? parentLayerOnClippingContainerChain->layoutObject() : parentLayerOnClippingContainerChain->clippingContainer();
-
-                if (layer->layoutObject()->isOutOfFlowPositioned() && !layer->subtreeIsInvisible()) {
-                    const PaintLayer* clippingLayer = properties.clippingContainer ? properties.clippingContainer->enclosingLayer() : layer->compositor()->rootLayer();
-                    if (hasClippedStackingAncestor(layer, clippingLayer))
-                        properties.clipParent = clippingLayer;
-                }
             }
 
             if (info.lastScrollingAncestor) {
@@ -150,6 +144,12 @@
                 if (parentLayerOnContainingBlockChain->scrollsOverflow())
                     properties.ancestorScrollingLayer = parentLayerOnContainingBlockChain;
 
+                if (layer->layoutObject()->isOutOfFlowPositioned() && !layer->subtreeIsInvisible()) {
+                    const PaintLayer* clippingLayer = properties.clippingContainer ? properties.clippingContainer->enclosingLayer() : layer->compositor()->rootLayer();
+                    if (hasClippedStackingAncestor(layer, clippingLayer))
+                        properties.clipParent = clippingLayer;
+                }
+
                 if (layer->stackingNode()->isTreatedAsOrStackingContext()
                     && properties.ancestorScrollingLayer
                     && !info.ancestorStackingContext->layoutObject()->isDescendantOf(properties.ancestorScrollingLayer->layoutObject()))
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
index 27a1ee1e..e11ae09 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
@@ -107,7 +107,7 @@
     child->setFirstLineStyleBit(isFirstLineStyle());
     child->setIsHorizontal(isHorizontal());
     if (child->isText()) {
-        if (child->lineLayoutItem().parent().isEqual(&layoutObject()))
+        if (child->lineLayoutItem().parent() == lineLayoutItem())
             m_hasTextChildren = true;
         setHasTextDescendantsOnAncestors(this);
     } else if (child->isInlineFlowBox()) {
@@ -122,7 +122,7 @@
         if (child->lineLayoutItem().isAtomicInlineLevel()) {
             shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
         } else if (child->isText()) {
-            if (child->lineLayoutItem().isBR() || (!child->lineLayoutItem().parent().isEqual(&layoutObject()))) {
+            if (child->lineLayoutItem().isBR() || (child->lineLayoutItem().parent() != lineLayoutItem())) {
                 if (!parentStyle.font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle.font().fontMetrics())
                     || parentStyle.lineHeight() != childStyle.lineHeight()
                     || (parentStyle.verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle.verticalAlign() != BASELINE)
@@ -326,7 +326,7 @@
         }
 
         if (!lineBoxList->lastLineBox()->isConstructed()) {
-            LayoutInline& inlineFlow = toLayoutInline(layoutObject());
+            LineLayoutInline inlineFlow = LineLayoutInline(lineLayoutItem());
             LineLayoutItem logicallyLastRunLayoutItem = LineLayoutItem(logicallyLastRunLayoutObject);
             bool isLastObjectOnLine = !isAncestorAndWithinBlock(lineLayoutItem(), logicallyLastRunLayoutItem) || (isLastChildForLayoutObject(lineLayoutItem(), logicallyLastRunLayoutItem) && !isLogicallyLastRunWrapped);
 
@@ -637,7 +637,7 @@
             LineLayoutBox box = LineLayoutBox(curr->lineLayoutItem());
             newLogicalTopIncludingMargins = newLogicalTop;
             // TODO(kojii): isHorizontal() does not match to m_layoutObject.isHorizontalWritingMode(). crbug.com/552954
-            // ASSERT(curr->isHorizontal() == curr->layoutObject().style()->isHorizontalWritingMode());
+            // ASSERT(curr->isHorizontal() == curr->lineLayoutItem().style()->isHorizontalWritingMode());
             LayoutUnit overSideMargin = curr->isHorizontal() ? box.marginTop() : box.marginRight();
             LayoutUnit underSideMargin = curr->isHorizontal() ? box.marginBottom() : box.marginLeft();
             newLogicalTop += overSideMargin;
@@ -999,7 +999,7 @@
             continue;
 
         if (curr->nodeAtPoint(result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
-            layoutObject().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+            lineLayoutItem().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
             return true;
         }
 
@@ -1047,7 +1047,7 @@
     //  Pixel snap hit testing.
     rect = LayoutRect(pixelSnappedIntRect(rect));
     if (visibleToHitTestRequest(result.hitTestRequest()) && locationInContainer.intersects(rect)) {
-        layoutObject().updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); // Don't add in m_topLeft here, we want coords in the containing block's space.
+        lineLayoutItem().updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); // Don't add in m_topLeft here, we want coords in the containing block's space.
         if (!result.addNodeToListBasedTestResult(lineLayoutItem().node(), locationInContainer, rect))
             return true;
     }
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
index 96661d27..0ddc9e6a 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
@@ -59,11 +59,10 @@
         newPaintInvalidationRect = scrollControlPaintInvalidationRect(scrollbar->frameRect(), box, paintInvalidationState, paintInvalidationContainer);
 
     bool needsPaintInvalidation = needsPaintInvalidationArg;
-    if (graphicsLayer && needsPaintInvalidation) {
-        graphicsLayer->setNeedsDisplay();
-        graphicsLayer->setContentsNeedsDisplay();
+    if (graphicsLayer) {
         // If the scrollbar needs paint invalidation but didn't change location/size or the scrollbar is an
-        // overlay scrollbar (paint invalidation rect is empty), invalidating the graphics layer is enough.
+        // overlay scrollbar (paint invalidation rect is empty), invalidating the graphics layer is enough
+        // (which has been done in ScrollableArea::setScrollbarNeedsPaintInvalidation()).
         // Otherwise invalidatePaintOfScrollControlIfNeeded() below will invalidate the old and new location
         // of the scrollbar on the box's paint invalidation container to ensure newly expanded/shrunk areas
         // of the box to be invalidated.
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index 964ade1b..a764e09 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -1655,7 +1655,7 @@
     ASSERT(layoutObject()->document().lifecycle().state() >= DocumentLifecycle::CompositingClean);
 
     if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
-        return 0;
+        return nullptr;
 
     ClipRectsCacheSlot clipRectsCacheSlot = result.hitTestRequest().ignoreClipping() ? RootRelativeClipRectsIgnoringViewportClip : RootRelativeClipRects;
 
@@ -1669,12 +1669,20 @@
             ClipRect clipRect = clipper().backgroundClipRect(ClipRectsContext(rootLayer, clipRectsCacheSlot, IncludeOverlayScrollbarSize));
             // Go ahead and test the enclosing clip now.
             if (!clipRect.intersects(hitTestLocation))
-                return 0;
+                return nullptr;
         }
 
         return hitTestLayerByApplyingTransform(rootLayer, containerLayer, result, hitTestRect, hitTestLocation, transformState, zOffset);
     }
 
+    if (layoutObject()->hasClipPath()) {
+        ASSERT(layoutObject()->isBox() && isSelfPaintingLayer());
+        LayoutPoint offsetToRootLayer;
+        convertToLayerCoords(rootLayer, offsetToRootLayer);
+        if (toLayoutBox(layoutObject())->hitTestClippedOutByClipPath(hitTestLocation.point(), offsetToRootLayer))
+            return nullptr;
+    }
+
     // Ensure our lists and 3d status are up-to-date.
     m_stackingNode->updateLayerListsIfNeeded();
     update3DTransformedDescendantStatus();
@@ -1695,7 +1703,7 @@
         TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
         // If the z-vector of the matrix is negative, the back is facing towards the viewer.
         if (invertedMatrix.m33() < 0)
-            return 0;
+            return nullptr;
     }
 
     RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
@@ -1806,7 +1814,7 @@
             result.append(tempResult);
     }
 
-    return 0;
+    return nullptr;
 }
 
 bool PaintLayer::hitTestContentsForFragments(const PaintLayerFragments& layerFragments, HitTestResult& result,
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp
index 9db1b4c3..103c2ab6 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -322,7 +322,7 @@
     return InsertionDone;
 }
 
-void SVGElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGElement::removedFrom(ContainerNode* rootParent)
 {
     bool wasInDocument = rootParent->inDocument();
 
@@ -340,7 +340,7 @@
 
     ASSERT_WITH_SECURITY_IMPLICATION(!rootParent->isSVGElement() || !toSVGElement(rootParent)->m_elementsWithRelativeLengths.contains(this));
 
-    Element::removedFrom(rootParent, next);
+    Element::removedFrom(rootParent);
 
     if (wasInDocument) {
         rebuildAllIncomingReferences();
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.h b/third_party/WebKit/Source/core/svg/SVGElement.h
index 1c4e3b9..3598356 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGElement.h
@@ -204,7 +204,7 @@
     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void childrenChanged(const ChildrenChange&) override;
 
     static CSSPropertyID cssPropertyIdForSVGAttributeName(const QualifiedName&);
diff --git a/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp
index 36562bb..ec9b5cc5 100644
--- a/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFEImageElement.cpp
@@ -137,9 +137,9 @@
     return InsertionDone;
 }
 
-void SVGFEImageElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGFEImageElement::removedFrom(ContainerNode* rootParent)
 {
-    SVGFilterPrimitiveStandardAttributes::removedFrom(rootParent, next);
+    SVGFilterPrimitiveStandardAttributes::removedFrom(rootParent);
     if (rootParent->inDocument())
         clearResourceReferences();
 }
diff --git a/third_party/WebKit/Source/core/svg/SVGFEImageElement.h b/third_party/WebKit/Source/core/svg/SVGFEImageElement.h
index 578a25db..fe54161 100644
--- a/third_party/WebKit/Source/core/svg/SVGFEImageElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGFEImageElement.h
@@ -63,7 +63,7 @@
 
     void buildPendingResource() override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     RefPtrWillBeMember<SVGAnimatedPreserveAspectRatio> m_preserveAspectRatio;
 
diff --git a/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp
index c2379aa..cd071bcb 100644
--- a/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGMPathElement.cpp
@@ -90,9 +90,9 @@
     return InsertionDone;
 }
 
-void SVGMPathElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGMPathElement::removedFrom(ContainerNode* rootParent)
 {
-    SVGElement::removedFrom(rootParent, next);
+    SVGElement::removedFrom(rootParent);
     notifyParentOfPathChange(rootParent);
     if (rootParent->inDocument())
         clearResourceReferences();
diff --git a/third_party/WebKit/Source/core/svg/SVGMPathElement.h b/third_party/WebKit/Source/core/svg/SVGMPathElement.h
index 9f36fdc..a9cdc20 100644
--- a/third_party/WebKit/Source/core/svg/SVGMPathElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGMPathElement.h
@@ -51,7 +51,7 @@
     void buildPendingResource() override;
     void clearResourceReferences();
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     void svgAttributeChanged(const QualifiedName&) override;
 
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
index 37350343..dc0b4b4 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
@@ -137,9 +137,9 @@
     return InsertionDone;
 }
 
-void SVGPathElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGPathElement::removedFrom(ContainerNode* rootParent)
 {
-    SVGGeometryElement::removedFrom(rootParent, next);
+    SVGGeometryElement::removedFrom(rootParent);
     invalidateMPathDependencies();
 }
 
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.h b/third_party/WebKit/Source/core/svg/SVGPathElement.h
index 2a55d593..c50a3e5 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGPathElement.h
@@ -51,7 +51,7 @@
     void svgAttributeChanged(const QualifiedName&) override;
 
     Node::InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     void invalidateMPathDependencies();
 
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
index 4d1db6e2..8c4803a 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -548,7 +548,7 @@
     return SVGGraphicsElement::insertedInto(rootParent);
 }
 
-void SVGSVGElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGSVGElement::removedFrom(ContainerNode* rootParent)
 {
     if (rootParent->inDocument()) {
         SVGDocumentExtensions& svgExtensions = document().accessSVGExtensions();
@@ -556,7 +556,7 @@
         svgExtensions.removeSVGRootWithRelativeLengthDescendents(this);
     }
 
-    SVGGraphicsElement::removedFrom(rootParent, next);
+    SVGGraphicsElement::removedFrom(rootParent);
 }
 
 void SVGSVGElement::pauseAnimations()
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.h b/third_party/WebKit/Source/core/svg/SVGSVGElement.h
index 23b2ddb..f65eddc 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.h
@@ -130,7 +130,7 @@
     LayoutObject* createLayoutObject(const ComputedStyle&) override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     void svgAttributeChanged(const QualifiedName&) override;
 
diff --git a/third_party/WebKit/Source/core/svg/SVGStyleElement.cpp b/third_party/WebKit/Source/core/svg/SVGStyleElement.cpp
index 509dd9b9..492f9f5 100644
--- a/third_party/WebKit/Source/core/svg/SVGStyleElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGStyleElement.cpp
@@ -136,9 +136,9 @@
         notifyLoadedSheetAndAllCriticalSubresources(ErrorOccurredLoadingSubresource);
 }
 
-void SVGStyleElement::removedFrom(ContainerNode* insertionPoint, Node* next)
+void SVGStyleElement::removedFrom(ContainerNode* insertionPoint)
 {
-    SVGElement::removedFrom(insertionPoint, next);
+    SVGElement::removedFrom(insertionPoint);
     StyleElement::removedFrom(this, insertionPoint);
 }
 
diff --git a/third_party/WebKit/Source/core/svg/SVGStyleElement.h b/third_party/WebKit/Source/core/svg/SVGStyleElement.h
index 28f6e64..1c36a2f 100644
--- a/third_party/WebKit/Source/core/svg/SVGStyleElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGStyleElement.h
@@ -63,7 +63,7 @@
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
     void didNotifySubtreeInsertionsToDocument() override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void childrenChanged(const ChildrenChange&) override;
 
     void finishParsingChildren() override;
diff --git a/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp
index f04e37e6..343cb34 100644
--- a/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTextPathElement.cpp
@@ -150,9 +150,9 @@
     return InsertionDone;
 }
 
-void SVGTextPathElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGTextPathElement::removedFrom(ContainerNode* rootParent)
 {
-    SVGTextContentElement::removedFrom(rootParent, next);
+    SVGTextContentElement::removedFrom(rootParent);
     if (rootParent->inDocument())
         clearResourceReferences();
 }
diff --git a/third_party/WebKit/Source/core/svg/SVGTextPathElement.h b/third_party/WebKit/Source/core/svg/SVGTextPathElement.h
index 880e5f3..5b88a78 100644
--- a/third_party/WebKit/Source/core/svg/SVGTextPathElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGTextPathElement.h
@@ -74,7 +74,7 @@
 
     void buildPendingResource() override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     void svgAttributeChanged(const QualifiedName&) override;
 
diff --git a/third_party/WebKit/Source/core/svg/SVGTitleElement.cpp b/third_party/WebKit/Source/core/svg/SVGTitleElement.cpp
index e942204..a905ac6 100644
--- a/third_party/WebKit/Source/core/svg/SVGTitleElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTitleElement.cpp
@@ -43,9 +43,9 @@
     return InsertionDone;
 }
 
-void SVGTitleElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGTitleElement::removedFrom(ContainerNode* rootParent)
 {
-    SVGElement::removedFrom(rootParent, next);
+    SVGElement::removedFrom(rootParent);
     if (rootParent->inDocument() && document().isSVGDocument())
         document().removeTitle(this);
 }
diff --git a/third_party/WebKit/Source/core/svg/SVGTitleElement.h b/third_party/WebKit/Source/core/svg/SVGTitleElement.h
index d1ae04a..31e9753 100644
--- a/third_party/WebKit/Source/core/svg/SVGTitleElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGTitleElement.h
@@ -34,7 +34,7 @@
     explicit SVGTitleElement(Document&);
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
     void childrenChanged(const ChildrenChange&) override;
 
     bool layoutObjectIsNeeded(const ComputedStyle&) override { return false; }
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
index d0e9f56..d4e17161 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -120,9 +120,9 @@
     return InsertionDone;
 }
 
-void SVGUseElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGUseElement::removedFrom(ContainerNode* rootParent)
 {
-    SVGGraphicsElement::removedFrom(rootParent, next);
+    SVGGraphicsElement::removedFrom(rootParent);
     if (rootParent->inDocument()) {
         clearShadowTree();
         cancelShadowTreeRecreation();
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.h b/third_party/WebKit/Source/core/svg/SVGUseElement.h
index bee0903..ff14e9f 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.h
@@ -73,7 +73,7 @@
     bool isStructurallyExternal() const override { return !hrefString().isNull() && isExternalURIReference(hrefString(), document()); }
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     void svgAttributeChanged(const QualifiedName&) override;
 
diff --git a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
index ffefe25..81a97be 100644
--- a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
+++ b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
@@ -348,7 +348,7 @@
     return InsertionDone;
 }
 
-void SVGSMILElement::removedFrom(ContainerNode* rootParent, Node* next)
+void SVGSMILElement::removedFrom(ContainerNode* rootParent)
 {
     if (rootParent->inDocument()) {
         clearResourceAndEventBaseReferences();
@@ -359,7 +359,7 @@
         m_timeContainer = nullptr;
     }
 
-    SVGElement::removedFrom(rootParent, next);
+    SVGElement::removedFrom(rootParent);
 }
 
 bool SVGSMILElement::hasValidAttributeName()
diff --git a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h
index b5e4fcf..0386af82 100644
--- a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h
+++ b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h
@@ -53,7 +53,7 @@
     void parseAttribute(const QualifiedName&, const AtomicString&, const AtomicString&) override;
     void svgAttributeChanged(const QualifiedName&) override;
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
-    void removedFrom(ContainerNode* insertionPoint, Node* next) override;
+    void removedFrom(ContainerNode*) override;
 
     virtual bool hasValidAttributeType() = 0;
     virtual bool hasValidAttributeName();
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js b/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
index 1266faa..5b251ff8 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/CSSWorkspaceBinding.js
@@ -142,15 +142,14 @@
         if (!range)
             return null;
 
-        var url = style.parentRule.resourceURL();
-        if (!url)
+        var header = style.cssModel().styleSheetHeaderForId(style.styleSheetId);
+        if (!header)
             return null;
 
         var line = forName ? range.startLine : range.endLine;
         // End of range is exclusive, so subtract 1 from the end offset.
         var column = forName ? range.startColumn : range.endColumn - (cssProperty.text && cssProperty.text.endsWith(";") ? 2 : 1);
-        var header = style.cssModel().styleSheetHeaderForId(style.styleSheetId);
-        var rawLocation = new WebInspector.CSSLocation(style.cssModel(), style.styleSheetId, url, header.lineNumberInSource(line), header.columnNumberInSource(line, column));
+        var rawLocation = new WebInspector.CSSLocation(header, header.lineNumberInSource(line), header.columnNumberInSource(line, column));
         return this.rawLocationToUILocation(rawLocation);
     },
 
@@ -290,7 +289,7 @@
     _rawLocationToUILocation: function(lineNumber, columnNumber)
     {
         var uiLocation = null;
-        var rawLocation = new WebInspector.CSSLocation(this._header.cssModel(), this._header.id, this._header.resourceURL(), lineNumber, columnNumber);
+        var rawLocation = new WebInspector.CSSLocation(this._header, lineNumber, columnNumber);
         for (var i = this._sourceMappings.length - 1; !uiLocation && i >= 0; --i)
             uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLocation);
         return uiLocation;
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index 93e7a2b4..be31b48 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -1288,9 +1288,12 @@
             return;
 
         if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(/** @type {!MouseEvent} */(event)) && this.navigable) {
-            var cssModel = this._parentPane._cssModel;
-            var rawLocation = new WebInspector.CSSLocation(cssModel, /** @type {string} */(media.parentStyleSheetId), media.sourceURL, /** @type {number} */(media.lineNumberInSource()), media.columnNumberInSource());
-            var uiLocation = WebInspector.cssWorkspaceBinding.rawLocationToUILocation(rawLocation);
+            var location = media.rawLocation();
+            if (!location) {
+                event.consume(true);
+                return;
+            }
+            var uiLocation = WebInspector.cssWorkspaceBinding.rawLocationToUILocation(location);
             if (uiLocation)
                 WebInspector.Revealer.reveal(uiLocation);
             event.consume(true);
@@ -1386,7 +1389,12 @@
             var index = event.target._selectorIndex;
             var cssModel = this._parentPane._cssModel;
             var rule = this._style.parentRule;
-            var rawLocation = new WebInspector.CSSLocation(cssModel, /** @type {string} */(rule.styleSheetId), rule.sourceURL, rule.lineNumberInSource(index), rule.columnNumberInSource(index));
+            var header = cssModel.styleSheetHeaderForId(/** @type {string} */(rule.styleSheetId));
+            if (!header) {
+                event.consume(true);
+                return;
+            }
+            var rawLocation = new WebInspector.CSSLocation(header, rule.lineNumberInSource(index), rule.columnNumberInSource(index));
             var uiLocation = WebInspector.cssWorkspaceBinding.rawLocationToUILocation(rawLocation);
             if (uiLocation)
                 WebInspector.Revealer.reveal(uiLocation);
@@ -1577,10 +1585,9 @@
 WebInspector.StylePropertiesSection._linkifyRuleLocation = function(cssModel, linkifier, styleSheetId, ruleLocation)
 {
     var styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);
-    var sourceURL = styleSheetHeader.resourceURL();
     var lineNumber = styleSheetHeader.lineNumberInSource(ruleLocation.startLine);
     var columnNumber = styleSheetHeader.columnNumberInSource(ruleLocation.startLine, ruleLocation.startColumn);
-    var matchingSelectorLocation = new WebInspector.CSSLocation(cssModel, styleSheetId, sourceURL, lineNumber, columnNumber);
+    var matchingSelectorLocation = new WebInspector.CSSLocation(styleSheetHeader, lineNumber, columnNumber);
     return linkifier.linkifyCSSLocation(matchingSelectorLocation);
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
index ec4c6aa..540e7d2 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
@@ -628,18 +628,16 @@
 /**
  * @constructor
  * @extends {WebInspector.SDKObject}
- * @param {!WebInspector.CSSStyleModel} cssModel
- * @param {!CSSAgent.StyleSheetId} styleSheetId
- * @param {string} url
+ * @param {!WebInspector.CSSStyleSheetHeader} header
  * @param {number} lineNumber
  * @param {number=} columnNumber
  */
-WebInspector.CSSLocation = function(cssModel, styleSheetId, url, lineNumber, columnNumber)
+WebInspector.CSSLocation = function(header, lineNumber, columnNumber)
 {
-    WebInspector.SDKObject.call(this, cssModel.target());
-    this._cssModel = cssModel;
-    this.styleSheetId = styleSheetId;
-    this.url = url;
+    WebInspector.SDKObject.call(this, header.target());
+    this._header = header;
+    this.styleSheetId = header.id;
+    this.url = header.resourceURL();
     this.lineNumber = lineNumber;
     this.columnNumber = columnNumber || 0;
 }
@@ -650,7 +648,7 @@
      */
     cssModel: function()
     {
-        return this._cssModel;
+        return this._header.cssModel();
     },
 
     __proto__: WebInspector.SDKObject.prototype
@@ -1741,10 +1739,11 @@
      */
     rawLocation: function()
     {
-        if (!this.header() || this.lineNumberInSource() === undefined)
+        var header = this.header();
+        if (!header || this.lineNumberInSource() === undefined)
             return null;
         var lineNumber = Number(this.lineNumberInSource());
-        return new WebInspector.CSSLocation(this._cssModel, this.header().id, this.sourceURL, lineNumber, this.columnNumberInSource());
+        return new WebInspector.CSSLocation(header, lineNumber, this.columnNumberInSource());
     }
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index c1f26965..cd86593 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -170,7 +170,7 @@
     else if (m_accelerationMode == DisableAcceleration)
         accelerate = false;
     else
-        accelerate = hint == PreferAcceleration;
+        accelerate = hint == PreferAcceleration || hint == PreferAccelerationAfterVisibilityChange;
 
     if (accelerate && (!m_contextProvider || m_contextProvider->context3d()->isContextLost()))
         accelerate = false;
@@ -251,8 +251,9 @@
     if (m_surface)
         return m_surface.get();
 
-    if (m_layer && !isHibernating())
+    if (m_layer && !isHibernating() && hint == PreferAcceleration) {
         return nullptr; // re-creation will happen through restore()
+    }
 
     bool wantAcceleration = shouldAccelerate(hint);
     bool surfaceIsAccelerated;
@@ -289,6 +290,9 @@
 
         if (m_imageBuffer)
             m_imageBuffer->updateGPUMemoryUsage();
+
+        if (m_imageBuffer && !m_isDeferralEnabled)
+            m_imageBuffer->resetCanvas(m_surface->getCanvas());
     }
     return m_surface.get();
 }
@@ -394,9 +398,12 @@
         copyPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
         RefPtr<SkSurface> oldSurface = m_surface.release();
         m_softwareRenderingWhileHidden = false;
-        SkSurface* newSurface = getOrCreateSurface();
+        SkSurface* newSurface = getOrCreateSurface(PreferAccelerationAfterVisibilityChange);
         if (newSurface) {
             oldSurface->draw(newSurface->getCanvas(), 0, 0, &copyPaint);
+            if (m_imageBuffer && !m_isDeferralEnabled) {
+                m_imageBuffer->resetCanvas(m_surface->getCanvas());
+            }
         }
     }
     if (!isHidden() && isHibernating()) {
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
index 914eb25..64cb48f 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -27,6 +27,7 @@
 
 #include "SkSurface.h"
 #include "platform/graphics/ImageBuffer.h"
+#include "platform/graphics/UnacceleratedImageBufferSurface.h"
 #include "platform/graphics/test/MockWebGraphicsContext3D.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebExternalBitmap.h"
@@ -42,9 +43,12 @@
 #include "third_party/skia/include/gpu/gl/SkNullGLContext.h"
 #include "wtf/RefPtr.h"
 
+using testing::AnyNumber;
+using testing::AtLeast;
 using testing::InSequence;
 using testing::Return;
 using testing::Test;
+using testing::_;
 
 namespace blink {
 
@@ -441,6 +445,16 @@
     WebWaitableEvent* m_doneEvent;
 };
 
+class MockImageBuffer : public ImageBuffer {
+public:
+    MockImageBuffer()
+        : ImageBuffer(adoptPtr(new UnacceleratedImageBufferSurface(IntSize(1, 1)))) { }
+
+    MOCK_CONST_METHOD1(resetCanvas, void(SkCanvas*));
+
+    virtual ~MockImageBuffer() { }
+};
+
 TEST_F(Canvas2DLayerBridgeTest, HibernationLifeCycle)
 {
     MockCanvasContext mainMock;
@@ -487,6 +501,59 @@
     ::testing::Mock::VerifyAndClearExpectations(&mainMock);
 }
 
+TEST_F(Canvas2DLayerBridgeTest, HibernationLifeCycleWithDeferredRenderingDisabled)
+{
+    MockCanvasContext mainMock;
+    OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread"));
+
+    // The Canvas2DLayerBridge has to be created on the thread that will use it
+    // to avoid WeakPtr thread check issues.
+    Canvas2DLayerBridgePtr bridge;
+    OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&bridge, &mainMock, this, bridgeCreatedEvent.get()));
+    bridgeCreatedEvent->wait();
+    bridge->disableDeferral();
+    MockImageBuffer mockImageBuffer;
+    EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AnyNumber());
+    bridge->setImageBuffer(&mockImageBuffer);
+
+    // Register an alternate Logger for tracking hibernation events
+    OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger);
+    MockLogger* mockLoggerPtr = mockLogger.get();
+    bridge->setLoggerForTesting(mockLogger.release());
+
+    // Test entering hibernation
+    OwnPtr<WebWaitableEvent> hibernationStartedEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::HibernationScheduled));
+    EXPECT_CALL(*mockLoggerPtr, didStartHibernating())
+        .WillOnce(testing::Invoke(hibernationStartedEvent.get(), &WebWaitableEvent::signal));
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(bridge.get(), true));
+    hibernationStartedEvent->wait();
+    ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr);
+    ::testing::Mock::VerifyAndClearExpectations(&mockImageBuffer);
+    EXPECT_FALSE(bridge->isAccelerated());
+    EXPECT_TRUE(bridge->isHibernating());
+
+    // Test exiting hibernation
+    OwnPtr<WebWaitableEvent> hibernationEndedEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::HibernationEndedNormally));
+    EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AtLeast(1)); // Because deferred rendering is disabled
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(bridge.get(), false, hibernationEndedEvent.get()));
+    hibernationEndedEvent->wait();
+    ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr);
+    ::testing::Mock::VerifyAndClearExpectations(&mockImageBuffer);
+    EXPECT_TRUE(bridge->isAccelerated());
+    EXPECT_FALSE(bridge->isHibernating());
+
+    // Tear down the bridge on the thread so that 'bridge' can go out of scope
+    // without crashing due to thread checks
+    OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&bridge, bridgeDestroyedEvent.get()));
+    bridgeDestroyedEvent->wait();
+
+    ::testing::Mock::VerifyAndClearExpectations(&mainMock);
+}
+
 class RenderingTask : public WebTaskRunner::Task {
 public:
     RenderingTask(Canvas2DLayerBridge* bridge, WebWaitableEvent* doneEvent)
@@ -563,6 +630,69 @@
     ::testing::Mock::VerifyAndClearExpectations(&mainMock);
 }
 
+TEST_F(Canvas2DLayerBridgeTest, BackgroundRenderingWhileHibernatingWithDeferredRenderingDisabled)
+{
+    MockCanvasContext mainMock;
+    OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("TestThread"));
+
+    // The Canvas2DLayerBridge has to be created on the thread that will use it
+    // to avoid WeakPtr thread check issues.
+    Canvas2DLayerBridgePtr bridge;
+    OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&bridge, &mainMock, this, bridgeCreatedEvent.get()));
+    bridgeCreatedEvent->wait();
+    MockImageBuffer mockImageBuffer;
+    EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AnyNumber());
+    bridge->setImageBuffer(&mockImageBuffer);
+    bridge->disableDeferral();
+
+
+    // Register an alternate Logger for tracking hibernation events
+    OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger);
+    MockLogger* mockLoggerPtr = mockLogger.get();
+    bridge->setLoggerForTesting(mockLogger.release());
+
+    // Test entering hibernation
+    OwnPtr<WebWaitableEvent> hibernationStartedEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::HibernationScheduled));
+    EXPECT_CALL(*mockLoggerPtr, didStartHibernating())
+        .WillOnce(testing::Invoke(hibernationStartedEvent.get(), &WebWaitableEvent::signal));
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(bridge.get(), true));
+    hibernationStartedEvent->wait();
+    ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr);
+    ::testing::Mock::VerifyAndClearExpectations(&mockImageBuffer);
+    EXPECT_FALSE(bridge->isAccelerated());
+    EXPECT_TRUE(bridge->isHibernating());
+
+    // Rendering in the background -> temp switch to SW
+    EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::HibernationEndedWithSwitchToBackgroundRendering));
+    EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AtLeast(1));
+    OwnPtr<WebWaitableEvent> switchEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new RenderingTask(bridge.get(), switchEvent.get()));
+    switchEvent->wait();
+    ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr);
+    ::testing::Mock::VerifyAndClearExpectations(&mockImageBuffer);
+    EXPECT_FALSE(bridge->isAccelerated());
+    EXPECT_FALSE(bridge->isHibernating());
+
+    // Unhide
+    EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AtLeast(1));
+    OwnPtr<WebWaitableEvent> unhideEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(bridge.get(), false, unhideEvent.get()));
+    unhideEvent->wait();
+    ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr);
+    ::testing::Mock::VerifyAndClearExpectations(&mockImageBuffer);
+    EXPECT_TRUE(bridge->isAccelerated()); // Becoming visible causes switch back to GPU
+    EXPECT_FALSE(bridge->isHibernating());
+
+    // Tear down the bridge on the thread so that 'bridge' can go out of scope
+    // without crashing due to thread checks
+    EXPECT_CALL(mockImageBuffer, resetCanvas(_)).Times(AnyNumber());
+    OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()->createWaitableEvent());
+    testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&bridge, bridgeDestroyedEvent.get()));
+    bridgeDestroyedEvent->wait();
+}
+
 TEST_F(Canvas2DLayerBridgeTest, TeardownWhileHibernating)
 {
     MockCanvasContext mainMock;
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h b/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
index 0c303722..fa3461f8 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
@@ -77,6 +77,9 @@
 
 enum AccelerationHint {
     PreferAcceleration,
+    // The PreferAccelerationAfterVisibilityChange hint suggests we should switch back to acceleration
+    // in the context of the canvas becoming visible again.
+    PreferAccelerationAfterVisibilityChange,
     PreferNoAcceleration,
 };
 
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
index aa171081..5e5d5ea 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
@@ -72,7 +72,7 @@
     static PassOwnPtr<ImageBuffer> create(const IntSize&, OpacityMode = NonOpaque, ImageInitializationMode = InitializeImagePixels);
     static PassOwnPtr<ImageBuffer> create(PassOwnPtr<ImageBufferSurface>);
 
-    ~ImageBuffer();
+    virtual ~ImageBuffer();
 
     void setClient(ImageBufferClient* client) { m_client = client; }
 
@@ -90,8 +90,9 @@
     void setFilterQuality(SkFilterQuality filterQuality) { m_surface->setFilterQuality(filterQuality); }
     void setIsHidden(bool hidden) { m_surface->setIsHidden(hidden); }
 
-    // Called by subclasses of ImageBufferSurface to install a new canvas object
-    void resetCanvas(SkCanvas*) const;
+    // Called by subclasses of ImageBufferSurface to install a new canvas object.
+    // Virtual for mocking
+    virtual void resetCanvas(SkCanvas*) const;
 
     SkCanvas* canvas() const;
     void disableDeferral() const;
@@ -135,9 +136,10 @@
     static intptr_t getGlobalGPUMemoryUsage() { return s_globalGPUMemoryUsage; }
     intptr_t getGPUMemoryUsage() { return m_gpuMemoryUsage; }
 
-private:
+protected:
     ImageBuffer(PassOwnPtr<ImageBufferSurface>);
 
+private:
     enum SnapshotState {
         InitialSnapshotState,
         DidAcquireSnapshot,
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp
index a5f7b66..e7927557 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp
@@ -42,8 +42,8 @@
 {
     TRACE_EVENT0("blink,benchmark", "PaintArtifact::appendToWebDisplayItemList");
     for (const DisplayItem& displayItem : m_displayItemList) {
-        IntRect visualRect = displayItem.client().visualRect();
-        displayItem.appendToWebDisplayItemList(visualRect, list);
+        // TODO(wkorman): Pass the actual visual rect for the display item.
+        displayItem.appendToWebDisplayItemList(IntRect(), list);
     }
 }
 
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp
index 8aba4198..f7f616f 100644
--- a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp
+++ b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp
@@ -51,26 +51,6 @@
 const char* const base64 = "base64";
 const char* const binary = "binary";
 
-String MHTMLArchive::generateMHTMLBoundary()
-{
-    // Trying to generate random boundaries similar to IE/UnMHT
-    // (ex: ----=_NextPart_000_001B_01CC157B.96F808A0).
-    const size_t randomValuesLength = 10;
-    char randomValues[randomValuesLength];
-    cryptographicallyRandomValues(&randomValues, randomValuesLength);
-    StringBuilder stringBuilder;
-    stringBuilder.appendLiteral("----=_NextPart_000_");
-    for (size_t i = 0; i < randomValuesLength; ++i) {
-        if (i == 2)
-            stringBuilder.append('_');
-        else if (i == 6)
-            stringBuilder.append('.');
-        stringBuilder.append(lowerNibbleToASCIIHexDigit(randomValues[i]));
-        stringBuilder.append(upperNibbleToASCIIHexDigit(randomValues[i]));
-    }
-    return stringBuilder.toString();
-}
-
 static String replaceNonPrintableCharacters(const String& text)
 {
     StringBuilder stringBuilder;
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h
index ee7f3a94..1a4f490 100644
--- a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h
+++ b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h
@@ -58,15 +58,11 @@
         UseBinaryEncoding
     };
 
-    // Generates a random/unique boundary that can be used as a separator of
-    // MHTML parts.
-    static String generateMHTMLBoundary();
-
     // Generates an MHTML header and appends it to |outputBuffer|.
     //
     // Same |boundary| needs to used for all generateMHTMLHeader and
     // generateMHTMLPart and generateMHTMLFooter calls that belong to the same
-    // MHTML document (see also generateMHTMLBoundary method).
+    // MHTML document (see also rfc1341, section 7.2.1, "boundary" description).
     static void generateMHTMLHeader(
         const String& boundary, const String& title, const String& mimeType,
         SharedBuffer& outputBuffer);
@@ -76,7 +72,7 @@
     //
     // Same |boundary| needs to used for all generateMHTMLHeader and
     // generateMHTMLPart and generateMHTMLFooter calls that belong to the same
-    // MHTML document (see also generateMHTMLBoundary method).
+    // MHTML document (see also rfc1341, section 7.2.1, "boundary" description).
     //
     // If |contentID| is non-empty, then it will be used as a Content-ID header.
     // See rfc2557 - section 8.3 - "Use of the Content-ID header and CID URLs".
@@ -89,7 +85,7 @@
     //
     // Same |boundary| needs to used for all generateMHTMLHeader and
     // generateMHTMLPart and generateMHTMLFooter calls that belong to the same
-    // MHTML document (see also generateMHTMLBoundary method).
+    // MHTML document (see also rfc1341, section 7.2.1, "boundary" description).
     static void generateMHTMLFooter(
         const String& boundary,
         SharedBuffer& outputBuffer);
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
index 8d7163c..77996f3 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
@@ -408,10 +408,19 @@
 
 void ScrollableArea::setScrollbarNeedsPaintInvalidation(ScrollbarOrientation orientation)
 {
-    if (orientation == HorizontalScrollbar)
+    if (orientation == HorizontalScrollbar) {
+        if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) {
+            graphicsLayer->setNeedsDisplay();
+            graphicsLayer->setContentsNeedsDisplay();
+        }
         m_horizontalScrollbarNeedsPaintInvalidation = true;
-    else
+    } else {
+        if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) {
+            graphicsLayer->setNeedsDisplay();
+            graphicsLayer->setContentsNeedsDisplay();
+        }
         m_verticalScrollbarNeedsPaintInvalidation = true;
+    }
 
     scrollControlWasSetNeedsPaintInvalidation();
 }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
index bda6b24..8b1613a3 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
@@ -5,6 +5,7 @@
 #include "config.h"
 #include "platform/scroll/ScrollableArea.h"
 
+#include "platform/graphics/GraphicsLayer.h"
 #include "platform/scroll/ScrollbarTheme.h"
 #include "platform/scroll/ScrollbarThemeMock.h"
 #include "platform/testing/TestingPlatformSupport.h"
@@ -18,6 +19,8 @@
 
 namespace {
 
+using testing::Return;
+
 class MockScrollableArea : public NoBaseWillBeGarbageCollectedFinalized<MockScrollableArea>, public ScrollableArea {
     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(MockScrollableArea);
 public:
@@ -35,6 +38,7 @@
     MOCK_CONST_METHOD1(visibleContentRect, IntRect(IncludeScrollbarsInRect));
     MOCK_CONST_METHOD0(contentsSize, IntSize());
     MOCK_CONST_METHOD0(scrollableAreaBoundingBox, IntRect());
+    MOCK_CONST_METHOD0(layerForHorizontalScrollbar, GraphicsLayer*());
 
     bool userInputScrollable(ScrollbarOrientation) const override { return true; }
     bool scrollbarsCanBeActive () const override { return true; }
@@ -88,7 +92,8 @@
 // We need just enough scaffolding for the Timer constructor to not segfault.
 class FakePlatform : public TestingPlatformSupport {
 public:
-    FakePlatform() { }
+    explicit FakePlatform(Config& config) : TestingPlatformSupport(config) { }
+
     ~FakePlatform() override { }
 
     WebThread* currentThread() override
@@ -109,16 +114,20 @@
     void SetUp() override
     {
         m_oldPlatform = Platform::current();
-        Platform::initialize(&m_fakePlatform);
+        TestingPlatformSupport::Config config;
+        config.compositorSupport = m_oldPlatform->compositorSupport();
+        m_fakePlatform = adoptPtr(new FakePlatform(config));
+        Platform::initialize(m_fakePlatform.get());
     }
 
     void TearDown() override
     {
         Platform::initialize(m_oldPlatform);
+        m_fakePlatform = nullptr;
     }
 
 private:
-    FakePlatform m_fakePlatform;
+    OwnPtr<FakePlatform> m_fakePlatform;
     Platform* m_oldPlatform; // Not owned.
 };
 
@@ -161,4 +170,34 @@
     EXPECT_FALSE(scrollbar->thumbNeedsRepaint());
 }
 
+class MockGraphicsLayerClient : public GraphicsLayerClient {
+public:
+    IntRect computeInterestRect(const GraphicsLayer*, const IntRect&) const { return IntRect(); }
+    void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&) const override { }
+    String debugName(const GraphicsLayer*) const override { return String(); }
+    bool isTrackingPaintInvalidations() const override { return true; }
+};
+
+class MockGraphicsLayer : public GraphicsLayer {
+public:
+    explicit MockGraphicsLayer(GraphicsLayerClient* client) : GraphicsLayer(client) { }
+};
+
+TEST_F(ScrollableAreaTest, ScrollbarGraphicsLayerInvalidation)
+{
+    ScrollbarTheme::setMockScrollbarsEnabled(true);
+    OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(IntPoint(0, 100));
+    MockGraphicsLayerClient graphicsLayerClient;
+    MockGraphicsLayer graphicsLayer(&graphicsLayerClient);
+    graphicsLayer.setDrawsContent(true);
+    graphicsLayer.setSize(FloatSize(111, 222));
+
+    EXPECT_CALL(*scrollableArea, layerForHorizontalScrollbar()).WillRepeatedly(Return(&graphicsLayer));
+
+    RefPtrWillBeRawPtr<Scrollbar> scrollbar = Scrollbar::create(scrollableArea.get(), HorizontalScrollbar, RegularScrollbar);
+    graphicsLayer.resetTrackedPaintInvalidations();
+    scrollbar->setNeedsPaintInvalidation();
+    EXPECT_TRUE(graphicsLayer.hasTrackedPaintInvalidations());
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarTheme.h b/third_party/WebKit/Source/platform/scroll/ScrollbarTheme.h
index 8a0ad33..8103c98 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarTheme.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarTheme.h
@@ -30,7 +30,7 @@
 #include "platform/geometry/IntRect.h"
 #include "platform/graphics/paint/DisplayItem.h"
 #include "platform/scroll/ScrollTypes.h"
-#include "public/platform/mac/MacScrollTypes.h"
+#include "public/platform/WebScrollbarButtonsPlacement.h"
 
 namespace blink {
 
@@ -62,7 +62,7 @@
     virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar) { return 0; }
     virtual int scrollbarMargin() const { return 0; }
 
-    virtual ScrollbarButtonsPlacement buttonsPlacement() const { return ScrollbarButtonsPlacementSingle; }
+    virtual WebScrollbarButtonsPlacement buttonsPlacement() const { return WebScrollbarButtonsPlacementSingle; }
 
     virtual bool supportsControlTints() const { return false; }
     virtual bool usesOverlayScrollbars() const { return false; }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.h b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.h
index 036083b..185ba2a 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.h
@@ -41,7 +41,7 @@
 
     void registerScrollbar(ScrollbarThemeClient&) override;
     void unregisterScrollbar(ScrollbarThemeClient&) override;
-    void preferencesChanged(float initialButtonDelay, float autoscrollButtonDelay, NSScrollerStyle preferredScrollerStyle, bool redraw, bool scrollAnimationEnabled, ScrollbarButtonsPlacement);
+    void preferencesChanged(float initialButtonDelay, float autoscrollButtonDelay, NSScrollerStyle preferredScrollerStyle, bool redraw, bool scrollAnimationEnabled, WebScrollbarButtonsPlacement);
 
     bool supportsControlTints() const override { return true; }
 
@@ -62,7 +62,7 @@
     bool shouldDragDocumentInsteadOfThumb(const ScrollbarThemeClient&, const PlatformMouseEvent&) override;
     int scrollbarPartToHIPressedState(ScrollbarPart);
 
-    virtual void updateButtonPlacement(ScrollbarButtonsPlacement) {}
+    virtual void updateButtonPlacement(WebScrollbarButtonsPlacement) {}
 
     void paintGivenTickmarks(SkCanvas*, const ScrollbarThemeClient&, const IntRect&, const Vector<IntRect>&);
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.mm b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.mm
index b72b1b2..5832661 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.mm
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacCommon.mm
@@ -160,7 +160,7 @@
 {
 }
 
-void ScrollbarThemeMacCommon::preferencesChanged(float initialButtonDelay, float autoscrollButtonDelay, NSScrollerStyle preferredScrollerStyle, bool redraw, bool scrollAnimationEnabled, ScrollbarButtonsPlacement buttonPlacement)
+void ScrollbarThemeMacCommon::preferencesChanged(float initialButtonDelay, float autoscrollButtonDelay, NSScrollerStyle preferredScrollerStyle, bool redraw, bool scrollAnimationEnabled, WebScrollbarButtonsPlacement buttonPlacement)
 {
     updateButtonPlacement(buttonPlacement);
     gInitialButtonDelay = initialButtonDelay;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.h b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.h
index 15d287c29..a0848ba 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.h
@@ -41,7 +41,7 @@
 public:
     int scrollbarThickness(ScrollbarControlSize = RegularScrollbar) override;
     bool usesOverlayScrollbars() const override { return false; }
-    ScrollbarButtonsPlacement buttonsPlacement() const override;
+    WebScrollbarButtonsPlacement buttonsPlacement() const override;
 
     bool paint(const ScrollbarThemeClient&, GraphicsContext&, const CullRect&) override;
     bool invalidateOnWindowActiveChange() const override { return true; }
@@ -51,7 +51,7 @@
     IntRect backButtonRect(const ScrollbarThemeClient&, ScrollbarPart, bool painting = false) override;
     IntRect forwardButtonRect(const ScrollbarThemeClient&, ScrollbarPart, bool painting = false) override;
 
-    void updateButtonPlacement(ScrollbarButtonsPlacement) override;
+    void updateButtonPlacement(WebScrollbarButtonsPlacement) override;
 
     bool hasButtons(const ScrollbarThemeClient&) override;
     bool hasThumb(const ScrollbarThemeClient&) override;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.mm b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.mm
index 2c55297..10af831 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.mm
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacNonOverlayAPI.mm
@@ -57,9 +57,9 @@
 static int cOuterButtonLength[] = { 16, 14 }; // The outer button in a double button pair is a bit bigger.
 static int cOuterButtonOverlap = 2;
 
-static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsPlacementDoubleEnd;
+static WebScrollbarButtonsPlacement gButtonPlacement = WebScrollbarButtonsPlacementDoubleEnd;
 
-void ScrollbarThemeMacNonOverlayAPI::updateButtonPlacement(ScrollbarButtonsPlacement buttonPlacement)
+void ScrollbarThemeMacNonOverlayAPI::updateButtonPlacement(WebScrollbarButtonsPlacement buttonPlacement)
 {
     gButtonPlacement = buttonPlacement;
 }
@@ -161,14 +161,14 @@
     return cScrollbarThickness[controlSize];
 }
 
-ScrollbarButtonsPlacement ScrollbarThemeMacNonOverlayAPI::buttonsPlacement() const
+WebScrollbarButtonsPlacement ScrollbarThemeMacNonOverlayAPI::buttonsPlacement() const
 {
     return gButtonPlacement;
 }
 
 bool ScrollbarThemeMacNonOverlayAPI::hasButtons(const ScrollbarThemeClient& scrollbar)
 {
-    return scrollbar.enabled() && buttonsPlacement() != ScrollbarButtonsPlacementNone
+    return scrollbar.enabled() && buttonsPlacement() != WebScrollbarButtonsPlacementNone
              && (scrollbar.orientation() == HorizontalScrollbar
              ? scrollbar.width()
              : scrollbar.height()) >= 2 * (cRealButtonLength[scrollbar.controlSize()] - cButtonHitInset[scrollbar.controlSize()]);
@@ -184,7 +184,7 @@
 
 static IntRect buttonRepaintRect(const IntRect& buttonRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, bool start)
 {
-    ASSERT(gButtonPlacement != ScrollbarButtonsPlacementNone);
+    ASSERT(gButtonPlacement != WebScrollbarButtonsPlacementNone);
 
     IntRect paintRect(buttonRect);
     if (orientation == HorizontalScrollbar) {
@@ -204,14 +204,14 @@
 {
     IntRect result;
 
-    if (part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsPlacementNone || buttonsPlacement() == ScrollbarButtonsPlacementDoubleEnd))
+    if (part == BackButtonStartPart && (buttonsPlacement() == WebScrollbarButtonsPlacementNone || buttonsPlacement() == WebScrollbarButtonsPlacementDoubleEnd))
         return result;
 
-    if (part == BackButtonEndPart && (buttonsPlacement() == ScrollbarButtonsPlacementNone || buttonsPlacement() == ScrollbarButtonsPlacementDoubleStart || buttonsPlacement() == ScrollbarButtonsPlacementSingle))
+    if (part == BackButtonEndPart && (buttonsPlacement() == WebScrollbarButtonsPlacementNone || buttonsPlacement() == WebScrollbarButtonsPlacementDoubleStart || buttonsPlacement() == WebScrollbarButtonsPlacementSingle))
         return result;
 
     int thickness = scrollbarThickness(scrollbar.controlSize());
-    bool outerButton = part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsPlacementDoubleStart || buttonsPlacement() == ScrollbarButtonsPlacementDoubleBoth);
+    bool outerButton = part == BackButtonStartPart && (buttonsPlacement() == WebScrollbarButtonsPlacementDoubleStart || buttonsPlacement() == WebScrollbarButtonsPlacementDoubleBoth);
     if (outerButton) {
         if (scrollbar.orientation() == HorizontalScrollbar)
             result = IntRect(scrollbar.x(), scrollbar.y(), cOuterButtonLength[scrollbar.controlSize()] + (painting ? cOuterButtonOverlap : 0), thickness);
@@ -238,17 +238,17 @@
 {
     IntRect result;
 
-    if (part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsPlacementNone || buttonsPlacement() == ScrollbarButtonsPlacementDoubleStart))
+    if (part == ForwardButtonEndPart && (buttonsPlacement() == WebScrollbarButtonsPlacementNone || buttonsPlacement() == WebScrollbarButtonsPlacementDoubleStart))
         return result;
 
-    if (part == ForwardButtonStartPart && (buttonsPlacement() == ScrollbarButtonsPlacementNone || buttonsPlacement() == ScrollbarButtonsPlacementDoubleEnd || buttonsPlacement() == ScrollbarButtonsPlacementSingle))
+    if (part == ForwardButtonStartPart && (buttonsPlacement() == WebScrollbarButtonsPlacementNone || buttonsPlacement() == WebScrollbarButtonsPlacementDoubleEnd || buttonsPlacement() == WebScrollbarButtonsPlacementSingle))
         return result;
 
     int thickness = scrollbarThickness(scrollbar.controlSize());
     int outerButtonLength = cOuterButtonLength[scrollbar.controlSize()];
     int buttonLength = cButtonLength[scrollbar.controlSize()];
 
-    bool outerButton = part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsPlacementDoubleEnd || buttonsPlacement() == ScrollbarButtonsPlacementDoubleBoth);
+    bool outerButton = part == ForwardButtonEndPart && (buttonsPlacement() == WebScrollbarButtonsPlacementDoubleEnd || buttonsPlacement() == WebScrollbarButtonsPlacementDoubleBoth);
     if (outerButton) {
         if (scrollbar.orientation() == HorizontalScrollbar) {
             result = IntRect(scrollbar.x() + scrollbar.width() - outerButtonLength, scrollbar.y(), outerButtonLength, thickness);
@@ -287,17 +287,17 @@
     int buttonLength = cButtonLength[scrollbar.controlSize()];
     int doubleButtonLength = outerButtonLength + buttonLength;
     switch (buttonsPlacement()) {
-        case ScrollbarButtonsPlacementSingle:
+        case WebScrollbarButtonsPlacementSingle:
             startWidth = buttonLength;
             endWidth = buttonLength;
             break;
-        case ScrollbarButtonsPlacementDoubleStart:
+        case WebScrollbarButtonsPlacementDoubleStart:
             startWidth = doubleButtonLength;
             break;
-        case ScrollbarButtonsPlacementDoubleEnd:
+        case WebScrollbarButtonsPlacementDoubleEnd:
             endWidth = doubleButtonLength;
             break;
-        case ScrollbarButtonsPlacementDoubleBoth:
+        case WebScrollbarButtonsPlacementDoubleBoth:
             startWidth = doubleButtonLength;
             endWidth = doubleButtonLength;
             break;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.h b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.h
index d4c62a6..be28778c 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.h
@@ -44,7 +44,7 @@
     int scrollbarThickness(ScrollbarControlSize = RegularScrollbar) override;
     bool usesOverlayScrollbars() const override;
     void updateScrollbarOverlayStyle(const ScrollbarThemeClient&) override;
-    ScrollbarButtonsPlacement buttonsPlacement() const override;
+    WebScrollbarButtonsPlacement buttonsPlacement() const override;
 
     void registerScrollbar(ScrollbarThemeClient&) override;
     void unregisterScrollbar(ScrollbarThemeClient&) override;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.mm b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.mm
index 12e42f8..4a41087e 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.mm
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMacOverlayAPI.mm
@@ -227,9 +227,9 @@
     }
 }
 
-ScrollbarButtonsPlacement ScrollbarThemeMacOverlayAPI::buttonsPlacement() const
+WebScrollbarButtonsPlacement ScrollbarThemeMacOverlayAPI::buttonsPlacement() const
 {
-    return ScrollbarButtonsPlacementNone;
+    return WebScrollbarButtonsPlacementNone;
 }
 
 bool ScrollbarThemeMacOverlayAPI::hasThumb(const ScrollbarThemeClient& scrollbar)
@@ -244,13 +244,13 @@
 
 IntRect ScrollbarThemeMacOverlayAPI::backButtonRect(const ScrollbarThemeClient& scrollbar, ScrollbarPart part, bool painting)
 {
-    ASSERT(buttonsPlacement() == ScrollbarButtonsPlacementNone);
+    ASSERT(buttonsPlacement() == WebScrollbarButtonsPlacementNone);
     return IntRect();
 }
 
 IntRect ScrollbarThemeMacOverlayAPI::forwardButtonRect(const ScrollbarThemeClient& scrollbar, ScrollbarPart part, bool painting)
 {
-    ASSERT(buttonsPlacement() == ScrollbarButtonsPlacementNone);
+    ASSERT(buttonsPlacement() == WebScrollbarButtonsPlacementNone);
     return IntRect();
 }
 
diff --git a/third_party/WebKit/Source/web/WebPageSerializer.cpp b/third_party/WebKit/Source/web/WebPageSerializer.cpp
index 4ac798c..48441a0 100644
--- a/third_party/WebKit/Source/web/WebPageSerializer.cpp
+++ b/third_party/WebKit/Source/web/WebPageSerializer.cpp
@@ -34,16 +34,18 @@
 #include "core/HTMLNames.h"
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
+#include "core/frame/Frame.h"
 #include "core/frame/LocalFrame.h"
+#include "core/frame/RemoteFrame.h"
 #include "core/html/HTMLAllCollection.h"
 #include "core/html/HTMLFrameElementBase.h"
 #include "core/html/HTMLFrameOwnerElement.h"
 #include "core/html/HTMLInputElement.h"
 #include "core/html/HTMLTableElement.h"
 #include "core/loader/DocumentLoader.h"
-#include "core/page/Page.h"
 #include "core/page/PageSerializer.h"
 #include "platform/SerializedResource.h"
+#include "platform/SharedBuffer.h"
 #include "platform/mhtml/MHTMLArchive.h"
 #include "platform/mhtml/MHTMLParser.h"
 #include "platform/weborigin/KURL.h"
@@ -51,14 +53,15 @@
 #include "public/platform/WebString.h"
 #include "public/platform/WebURL.h"
 #include "public/platform/WebVector.h"
+#include "public/web/WebDocument.h"
 #include "public/web/WebFrame.h"
 #include "public/web/WebPageSerializerClient.h"
-#include "public/web/WebView.h"
 #include "web/WebLocalFrameImpl.h"
 #include "web/WebPageSerializerImpl.h"
-#include "web/WebViewImpl.h"
+#include "web/WebRemoteFrameImpl.h"
 #include "wtf/Assertions.h"
 #include "wtf/HashMap.h"
+#include "wtf/HashSet.h"
 #include "wtf/Noncopyable.h"
 #include "wtf/Vector.h"
 #include "wtf/text/StringConcatenate.h"
@@ -133,77 +136,74 @@
     return false;
 }
 
-ContentIDMap generateFrameContentIDs(Page* page)
+ContentIDMap createFrameToContentIDMap(
+    const WebVector<std::pair<WebFrame*, WebString>>& webFrameToContentID)
 {
-    ContentIDMap frameToContentID;
-    int frameID = 0;
-    for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
-        // TODO(lukasza): Move cid generation to the browser + use base/guid.h
-        // (see the draft at crrev.com/1386873003).
-        StringBuilder contentIDBuilder;
-        contentIDBuilder.appendLiteral("<frame");
-        contentIDBuilder.appendNumber(frameID++);
-        contentIDBuilder.appendLiteral("@mhtml.blink>");
+    ContentIDMap result;
+    for (const auto& it : webFrameToContentID) {
+        WebFrame* webFrame = it.first;
+        const WebString& webContentID = it.second;
 
-        frameToContentID.add(frame, contentIDBuilder.toString());
+        Frame* frame = webFrame->toImplBase()->frame();
+        String contentID(webContentID);
+
+        result.add(frame, contentID);
     }
-    return frameToContentID;
-}
-
-PassRefPtr<SharedBuffer> serializePageToMHTML(Page* page, MHTMLArchive::EncodingPolicy encodingPolicy)
-{
-    Vector<SerializedResource> resources;
-    ContentIDMap frameToContentID = generateFrameContentIDs(page);
-    MHTMLPageSerializerDelegate delegate(frameToContentID);
-    PageSerializer serializer(resources, &delegate);
-
-    RefPtr<SharedBuffer> output = SharedBuffer::create();
-    String boundary = MHTMLArchive::generateMHTMLBoundary();
-
-    Document* document = page->deprecatedLocalMainFrame()->document();
-    MHTMLArchive::generateMHTMLHeader(
-        boundary, document->title(), document->suggestedMIMEType(), *output);
-
-    for (Frame* frame = page->deprecatedLocalMainFrame(); frame; frame = frame->tree().traverseNext()) {
-        // TODO(lukasza): This causes incomplete MHTML for OOPIFs.
-        // (crbug.com/538766)
-        if (!frame->isLocalFrame())
-            continue;
-
-        resources.clear();
-        serializer.serializeFrame(*toLocalFrame(frame));
-
-        bool isFirstResource = true;
-        for (const SerializedResource& resource : resources) {
-            // Frame is the 1st resource (see PageSerializer::serializeFrame doc
-            // comment). Frames need a Content-ID header.
-            String contentID = isFirstResource ? frameToContentID.get(frame) : String();
-
-            MHTMLArchive::generateMHTMLPart(
-                boundary, contentID, encodingPolicy, resource, *output);
-
-            isFirstResource = false;
-        }
-    }
-
-    MHTMLArchive::generateMHTMLFooter(boundary, *output);
-    return output.release();
+    return result;
 }
 
 } // namespace
 
-WebCString WebPageSerializer::serializeToMHTML(WebView* view)
+WebData WebPageSerializer::generateMHTMLHeader(
+    const WebString& boundary, WebLocalFrame* frame)
 {
-    RefPtr<SharedBuffer> mhtml = serializePageToMHTML(toWebViewImpl(view)->page(), MHTMLArchive::UseDefaultEncoding);
-    // FIXME: we are copying all the data here. Idealy we would have a WebSharedData().
-    return WebCString(mhtml->data(), mhtml->size());
+    Document* document = toWebLocalFrameImpl(frame)->frame()->document();
+
+    RefPtr<SharedBuffer> buffer = SharedBuffer::create();
+    MHTMLArchive::generateMHTMLHeader(
+        boundary, document->title(), document->suggestedMIMEType(),
+        *buffer);
+    return buffer.release();
 }
 
-WebCString WebPageSerializer::serializeToMHTMLUsingBinaryEncoding(WebView* view)
+WebData WebPageSerializer::generateMHTMLParts(
+    const WebString& boundary, WebLocalFrame* webFrame, bool useBinaryEncoding,
+    const WebVector<std::pair<WebFrame*, WebString>>& webFrameToContentID)
 {
-    RefPtr<SharedBuffer> mhtml = serializePageToMHTML(toWebViewImpl(view)->page(), MHTMLArchive::UseBinaryEncoding);
-    // FIXME: we are copying all the data here. Idealy we would have a WebSharedData().
-    return WebCString(mhtml->data(), mhtml->size());
+    // Translate arguments from public to internal blink APIs.
+    LocalFrame* frame = toWebLocalFrameImpl(webFrame)->frame();
+    MHTMLArchive::EncodingPolicy encodingPolicy = useBinaryEncoding
+        ? MHTMLArchive::EncodingPolicy::UseBinaryEncoding
+        : MHTMLArchive::EncodingPolicy::UseDefaultEncoding;
+    ContentIDMap frameToContentID = createFrameToContentIDMap(webFrameToContentID);
+
+    // Serialize.
+    Vector<SerializedResource> resources;
+    MHTMLPageSerializerDelegate delegate(frameToContentID);
+    PageSerializer serializer(resources, &delegate);
+    serializer.serializeFrame(*frame);
+
+    // Encode serializer's output as MHTML.
+    RefPtr<SharedBuffer> output = SharedBuffer::create();
+    bool isFirstResource = true;
+    for (const SerializedResource& resource : resources) {
+        // Frame is the 1st resource (see PageSerializer::serializeFrame doc
+        // comment). Frames need a Content-ID header.
+        String contentID = isFirstResource ? frameToContentID.get(frame) : String();
+
+        MHTMLArchive::generateMHTMLPart(
+            boundary, contentID, encodingPolicy, resource, *output);
+
+        isFirstResource = false;
+    }
+    return output.release();
+}
+
+WebData WebPageSerializer::generateMHTMLFooter(const WebString& boundary)
+{
+    RefPtr<SharedBuffer> buffer = SharedBuffer::create();
+    MHTMLArchive::generateMHTMLFooter(boundary, *buffer);
+    return buffer.release();
 }
 
 bool WebPageSerializer::serialize(
diff --git a/third_party/WebKit/Source/web/mac/WebScrollbarTheme.mm b/third_party/WebKit/Source/web/mac/WebScrollbarTheme.mm
index 78e6028d..eb37dce 100644
--- a/third_party/WebKit/Source/web/mac/WebScrollbarTheme.mm
+++ b/third_party/WebKit/Source/web/mac/WebScrollbarTheme.mm
@@ -45,7 +45,7 @@
 
 void WebScrollbarTheme::updateScrollbarsWithNSDefaults(
     float initialButtonDelay, float autoscrollButtonDelay,
-    ScrollerStyle preferredScrollerStyle, bool redraw, bool scrollAnimationEnabled, ScrollbarButtonsPlacement buttonPlacement)
+    ScrollerStyle preferredScrollerStyle, bool redraw, bool scrollAnimationEnabled, WebScrollbarButtonsPlacement buttonPlacement)
 {
     ScrollbarTheme& theme = ScrollbarTheme::theme();
     if (theme.isMockTheme())
diff --git a/third_party/WebKit/Source/web/tests/MHTMLTest.cpp b/third_party/WebKit/Source/web/tests/MHTMLTest.cpp
index 4aef940..569c3cd 100644
--- a/third_party/WebKit/Source/web/tests/MHTMLTest.cpp
+++ b/third_party/WebKit/Source/web/tests/MHTMLTest.cpp
@@ -145,7 +145,9 @@
         MHTMLArchive::EncodingPolicy encodingPolicy,
         const String& title, const String& mimeType)
     {
-        String boundary = MHTMLArchive::generateMHTMLBoundary();
+        // This boundary is as good as any other.  Plus it gets used in almost
+        // all the examples in the MHTML spec - RFC 2557.
+        String boundary = String::fromUTF8("boundary-example");
 
         RefPtr<SharedBuffer> mhtmlData = SharedBuffer::create();
         MHTMLArchive::generateMHTMLHeader(boundary, title, mimeType, *mhtmlData);
diff --git a/third_party/WebKit/Source/wtf/Alias.cpp b/third_party/WebKit/Source/wtf/Alias.cpp
deleted file mode 100644
index 6a3d1a8..0000000
--- a/third_party/WebKit/Source/wtf/Alias.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2011 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 "config.h"
-#include "wtf/Alias.h"
-
-// TODO(tasak): This code is copied from //base/debug/alias.cc.
-// If Blink is allowed to use //base/debug, remove this code and use //base/debug.
-namespace WTF {
-
-#if COMPILER(MSVC)
-#pragma optimize("", off)
-#endif
-
-void alias(const void* var)
-{
-}
-
-#if COMPILER(MSVC)
-#pragma optimize("", on)
-#endif
-
-} // namespace WTF
diff --git a/third_party/WebKit/Source/wtf/Alias.h b/third_party/WebKit/Source/wtf/Alias.h
deleted file mode 100644
index 9d0ff752..0000000
--- a/third_party/WebKit/Source/wtf/Alias.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011 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 Alias_h
-#define Alias_h
-
-#include "wtf/WTFExport.h"
-
-namespace WTF {
-
-// Make the optimizer think that var is aliased. This is to prevent it from
-// optimizing out variables that would not otherwise be live at the point
-// of a potential crash.
-void WTF_EXPORT alias(const void* var);
-
-} // namespace WTF
-
-#endif // Alias_h
diff --git a/third_party/WebKit/Source/wtf/DEPS b/third_party/WebKit/Source/wtf/DEPS
index c5c821e..426fe75 100644
--- a/third_party/WebKit/Source/wtf/DEPS
+++ b/third_party/WebKit/Source/wtf/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+    "+base/debug",
     "+base/strings",
 ]
diff --git a/third_party/WebKit/Source/wtf/LeakAnnotations.h b/third_party/WebKit/Source/wtf/LeakAnnotations.h
index 446992db..8dba581 100644
--- a/third_party/WebKit/Source/wtf/LeakAnnotations.h
+++ b/third_party/WebKit/Source/wtf/LeakAnnotations.h
@@ -34,11 +34,7 @@
 
 // This file defines macros for working with LeakSanitizer, allowing memory
 // and allocations to be registered as exempted from LSan consideration.
-//
-// LSan exempted memory will be treated as a source of live pointers,
-// i.e. heap objects reachable by following pointers from an exempted
-// object will not be reported as leaks.
-//
+
 #include "wtf/Noncopyable.h"
 #if USE(LEAK_SANITIZER)
 #include "wtf/AddressSanitizer.h"
@@ -74,6 +70,12 @@
 
 // LEAK_SANITIZER_IGNORE_OBJECT(X): the heap object referenced by pointer X
 // will be ignored by LSan.
+//
+// "Ignorance" means that LSan's reachability traversal is stopped short
+// upon encountering an ignored memory chunk. Consequently, LSan will not
+// scan an ignored memory chunk for live, reachable pointers. However, should
+// those embedded pointers be reachable by some other path, they will be
+// reported as leaking.
 #define LEAK_SANITIZER_IGNORE_OBJECT(X) __lsan_ignore_object(X)
 
 // If the object pointed to by the static local is on the Oilpan heap, a strong
diff --git a/third_party/WebKit/Source/wtf/Partitions.cpp b/third_party/WebKit/Source/wtf/Partitions.cpp
index 2e97e011..00d2852f 100644
--- a/third_party/WebKit/Source/wtf/Partitions.cpp
+++ b/third_party/WebKit/Source/wtf/Partitions.cpp
@@ -31,7 +31,7 @@
 #include "config.h"
 #include "wtf/Partitions.h"
 
-#include "wtf/Alias.h"
+#include "base/debug/alias.h"
 #include "wtf/MainThread.h"
 #include "wtf/PartitionAllocator.h"
 
@@ -128,63 +128,63 @@
 static NEVER_INLINE void partitionsOutOfMemoryUsing2G()
 {
     size_t signature = 2UL * 1024 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsing1G()
 {
     size_t signature = 1UL * 1024 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsing512M()
 {
     size_t signature = 512 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsing256M()
 {
     size_t signature = 256 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsing128M()
 {
     size_t signature = 128 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsing64M()
 {
     size_t signature = 64 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsing32M()
 {
     size_t signature = 32 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsing16M()
 {
     size_t signature = 16 * 1024 * 1024;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
 static NEVER_INLINE void partitionsOutOfMemoryUsingLessThan16M()
 {
     size_t signature = 16 * 1024 * 1024 - 1;
-    alias(&signature);
+    base::debug::Alias(&signature);
     IMMEDIATE_CRASH();
 }
 
diff --git a/third_party/WebKit/Source/wtf/wtf.gyp b/third_party/WebKit/Source/wtf/wtf.gyp
index b6b46912..75e5504a 100644
--- a/third_party/WebKit/Source/wtf/wtf.gyp
+++ b/third_party/WebKit/Source/wtf/wtf.gyp
@@ -71,6 +71,7 @@
       'dependencies': [
           'wtf_config',
           '../config.gyp:config',
+          '<(DEPTH)/base/base.gyp:base',
           '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
           '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
       ],
@@ -99,6 +100,7 @@
       },
       'export_dependent_settings': [
         'wtf_config',
+        '<(DEPTH)/base/base.gyp:base',
         '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
         '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
       ],
diff --git a/third_party/WebKit/Source/wtf/wtf.gypi b/third_party/WebKit/Source/wtf/wtf.gypi
index 1a5f7e03..000cbb2 100644
--- a/third_party/WebKit/Source/wtf/wtf.gypi
+++ b/third_party/WebKit/Source/wtf/wtf.gypi
@@ -7,8 +7,6 @@
             'AddressSanitizer.h',
             'AddressSpaceRandomization.cpp',
             'AddressSpaceRandomization.h',
-            'Alias.cpp',
-            'Alias.h',
             'Alignment.h',
             'Allocator.h',
             'ArrayBuffer.cpp',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py
index 49d122b..9e7e16f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py
@@ -426,6 +426,7 @@
 
         # Create a single line with all of the parameters.
         self.single_line = ' '.join(trimmed_lines)
+        self.single_line = _RE_PATTERN_CLEANSE_MULTIPLE_STRINGS.sub('""', self.single_line)
 
         # Keep the row lengths, so we can calculate the original row number
         # given a column in the single line (adding 1 due to the space added
@@ -713,6 +714,9 @@
 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"')
 # Matches characters.  Escape codes should already be removed by ESCAPES.
 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'")
+# Matches multiple strings (after the above cleanses) which can be concatenated.
+_RE_PATTERN_CLEANSE_MULTIPLE_STRINGS = re.compile(r'"("\s*")+"')
+
 # Matches multi-line C++ comments.
 # This RE is a little bit more complicated than one might expect, because we
 # have to take care of space removals tools so we can handle comments inside
@@ -847,6 +851,7 @@
             elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
             elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided)
             elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided)
+            elided = _RE_PATTERN_CLEANSE_MULTIPLE_STRINGS.sub('""', elided)
         return elided
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py
index eb2f12f..61354b3 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py
@@ -169,6 +169,11 @@
         single_line_view = cpp_style.SingleLineView(['abcdef'], start_position, end_position)
         self.assertEqual(single_line_view.single_line, 'd')
 
+        start_position = cpp_style.Position(row=0, column=0)
+        end_position = cpp_style.Position(row=3, column=2)
+        single_line_view = cpp_style.SingleLineView(['""', '""', '""'], start_position, end_position)
+        self.assertEqual(single_line_view.single_line, '""')
+
     def test_create_skeleton_parameters(self):
         self.assertEqual(cpp_style.create_skeleton_parameters(''), '')
         self.assertEqual(cpp_style.create_skeleton_parameters(' '), ' ')
@@ -2657,6 +2662,7 @@
                           collapse('StringReplace(body, "\\\\", "\\\\\\\\");'))
         self.assertEqual('\'\' ""',
                           collapse('\'"\' "foo"'))
+        self.assertEqual('""', collapse('"a" "b" "c"'))
 
 
 class OrderOfIncludesTest(CppStyleTestBase):
diff --git a/third_party/WebKit/public/blink_headers.gypi b/third_party/WebKit/public/blink_headers.gypi
index 13a4f48..b6b2cec 100644
--- a/third_party/WebKit/public/blink_headers.gypi
+++ b/third_party/WebKit/public/blink_headers.gypi
@@ -190,6 +190,7 @@
       "platform/WebScrollOffsetAnimationCurve.h",
       "platform/WebScrollbar.h",
       "platform/WebScrollbarBehavior.h",
+      "platform/WebScrollbarButtonsPlacement.h",
       "platform/WebScrollbarLayer.h",
       "platform/WebScrollbarThemeGeometry.h",
       "platform/WebScrollbarThemePainter.h",
diff --git a/third_party/WebKit/public/platform/WebScrollbarButtonsPlacement.h b/third_party/WebKit/public/platform/WebScrollbarButtonsPlacement.h
new file mode 100644
index 0000000..31c884e
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebScrollbarButtonsPlacement.h
@@ -0,0 +1,21 @@
+// Copyright 2015 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 WebScrollbarButtonsPlacement_h
+#define WebScrollbarButtonsPlacement_h
+
+namespace blink {
+
+enum WebScrollbarButtonsPlacement {
+    WebScrollbarButtonsPlacementNone,
+    WebScrollbarButtonsPlacementSingle,
+    WebScrollbarButtonsPlacementDoubleStart,
+    WebScrollbarButtonsPlacementDoubleEnd,
+    WebScrollbarButtonsPlacementDoubleBoth,
+    WebScrollbarButtonsPlacementLast = WebScrollbarButtonsPlacementDoubleBoth
+};
+
+} // namespace blink
+
+#endif // WebScrollbarButtonsPlacement_h
diff --git a/third_party/WebKit/public/platform/mac/MacScrollTypes.h b/third_party/WebKit/public/platform/mac/MacScrollTypes.h
deleted file mode 100644
index 35a7686d..0000000
--- a/third_party/WebKit/public/platform/mac/MacScrollTypes.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 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 MacScrollTypes_h
-#define MacScrollTypes_h
-
-namespace blink {
-
-enum ScrollbarButtonsPlacement {
-    ScrollbarButtonsPlacementNone,
-    ScrollbarButtonsPlacementSingle,
-    ScrollbarButtonsPlacementDoubleStart,
-    ScrollbarButtonsPlacementDoubleEnd,
-    ScrollbarButtonsPlacementDoubleBoth,
-    ScrollbarButtonsPlacementLast = ScrollbarButtonsPlacementDoubleBoth
-};
-
-}
-
-#endif // MacScrollTypes_h
diff --git a/third_party/WebKit/public/web/WebPageSerializer.h b/third_party/WebKit/public/web/WebPageSerializer.h
index 2ae2e25..7a59b6a 100644
--- a/third_party/WebKit/public/web/WebPageSerializer.h
+++ b/third_party/WebKit/public/web/WebPageSerializer.h
@@ -33,26 +33,58 @@
 
 #include "../platform/WebCString.h"
 #include "../platform/WebCommon.h"
+#include "../platform/WebData.h"
+#include "../platform/WebString.h"
 #include "../platform/WebURL.h"
-#include "WebFrame.h"
+#include "../platform/WebVector.h"
+
+#include <utility>
 
 namespace blink {
 
 class WebPageSerializerClient;
-class WebString;
-class WebView;
+class WebFrame;
+class WebLocalFrame;
 template <typename T> class WebVector;
 
-// Get html data by serializing all frames of current page with lists
-// which contain all resource links that have local copy.
+// Serialization of frame contents into html or mhtml.
+// TODO(lukasza): Rename this class to WebFrameSerializer?
 class WebPageSerializer {
 public:
-    // Serializes the WebView contents to a MHTML representation.
-    BLINK_EXPORT static WebCString serializeToMHTML(WebView*);
+    // Generates and returns an MHTML header.
+    //
+    // Contents of the header (i.e. title and mime type) will be based
+    // on the frame passed as an argument (which typically should be
+    // the main, top-level frame).
+    //
+    // Same |boundary| needs to used for all generateMHTMLHeader and
+    // generateMHTMLParts and generateMHTMLFooter calls that belong to the same
+    // MHTML document (see also rfc1341, section 7.2.1, "boundary" description).
+    BLINK_EXPORT static WebData generateMHTMLHeader(
+        const WebString& boundary, WebLocalFrame*);
 
-    // Similar to serializeToMHTML but uses binary encoding for the MHTML parts.
-    // This results in a smaller MHTML file but it might not be supported by other browsers.
-    BLINK_EXPORT static WebCString serializeToMHTMLUsingBinaryEncoding(WebView*);
+    // Generates and returns MHTML parts for the given frame and all the
+    // savable resources underneath.
+    //
+    // Same |boundary| needs to used for all generateMHTMLHeader and
+    // generateMHTMLParts and generateMHTMLFooter calls that belong to the same
+    // MHTML document (see also rfc1341, section 7.2.1, "boundary" description).
+    //
+    // |frameToContentID| is used for 1) emitting cid: scheme uri links for
+    // subframes and 2) emitting MIME Content-ID headers.
+    // See rfc2557 - section 8.3 - "Use of the Content-ID header and CID URLs".
+    // Format note - |frameToContentID| should contain strings of the form
+    // "<foo@bar.com>" (i.e. the strings should include the angle brackets).
+    BLINK_EXPORT static WebData generateMHTMLParts(
+        const WebString& boundary, WebLocalFrame*, bool useBinaryEncoding,
+        const WebVector<std::pair<WebFrame*, WebString>>& frameToContentID);
+
+    // Generates and returns an MHTML footer.
+    //
+    // Same |boundary| needs to used for all generateMHTMLHeader and
+    // generateMHTMLParts and generateMHTMLFooter calls that belong to the same
+    // MHTML document (see also rfc1341, section 7.2.1, "boundary" description).
+    BLINK_EXPORT static WebData generateMHTMLFooter(const WebString& boundary);
 
     // IMPORTANT:
     // The API below is an older implementation of a pageserialization that
diff --git a/third_party/WebKit/public/web/mac/WebScrollbarTheme.h b/third_party/WebKit/public/web/mac/WebScrollbarTheme.h
index 88fd5430..a610ac93 100644
--- a/third_party/WebKit/public/web/mac/WebScrollbarTheme.h
+++ b/third_party/WebKit/public/web/mac/WebScrollbarTheme.h
@@ -32,7 +32,7 @@
 #define WebScrollbarTheme_h
 
 #include "public/platform/WebCommon.h"
-#include "public/platform/mac/MacScrollTypes.h"
+#include "public/platform/WebScrollbarButtonsPlacement.h"
 
 namespace blink {
 
@@ -54,7 +54,7 @@
     BLINK_EXPORT static void updateScrollbarsWithNSDefaults(
         float initialButtonDelay, float autoscrollButtonDelay,
         ScrollerStyle preferredScrollerStyle, bool redraw,
-        bool scrollAnimationEnabled, ScrollbarButtonsPlacement);
+        bool scrollAnimationEnabled, WebScrollbarButtonsPlacement);
 };
 
 } // namespace blink
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index 47cc9be..9c21317 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: unknown
-Revision: 6bebb10829332dee5c7315abafb0a8bf32840c15
+Revision: 583d1dc3efa96ea50f62afa69a598eeed1534edc
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
@@ -35,5 +35,4 @@
 $ git am --3way --message-id -p4 /tmp/patchdir
 
 Local Modifications:
- - Cherry-pick upstream 7efdc94f5982a1f9654c53fd4bf5663e5efa66ce.
- - Cherry-pick upstream b9e732d3180f9eadc74d7229090e613d0700b8a6.
+None.
diff --git a/third_party/crashpad/crashpad/client/client.gyp b/third_party/crashpad/crashpad/client/client.gyp
index 765a2b47..3524be4 100644
--- a/third_party/crashpad/crashpad/client/client.gyp
+++ b/third_party/crashpad/crashpad/client/client.gyp
@@ -21,6 +21,7 @@
       'target_name': 'crashpad_client',
       'type': 'static_library',
       'dependencies': [
+        '../compat/compat.gyp:crashpad_compat',
         '../third_party/mini_chromium/mini_chromium.gyp:base',
         '../util/util.gyp:crashpad_util',
       ],
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_test.cc b/third_party/crashpad/crashpad/client/crash_report_database_test.cc
index 54dcdd7..ca839f4 100644
--- a/third_party/crashpad/crashpad/client/crash_report_database_test.cc
+++ b/third_party/crashpad/crashpad/client/crash_report_database_test.cc
@@ -555,6 +555,36 @@
             db()->LookUpCrashReport(keep_completed.uuid, &keep_completed));
 }
 
+TEST_F(CrashReportDatabaseTest, DeleteReportEmptyingDatabase) {
+  CrashReportDatabase::Report report;
+  CreateCrashReport(&report);
+
+  EXPECT_TRUE(FileExists(report.file_path));
+
+  UploadReport(report.uuid, true, "1");
+
+  EXPECT_EQ(CrashReportDatabase::kNoError,
+            db()->LookUpCrashReport(report.uuid, &report));
+
+  EXPECT_TRUE(FileExists(report.file_path));
+
+  // This causes an empty database to be written, make sure this is handled.
+  EXPECT_EQ(CrashReportDatabase::kNoError, db()->DeleteReport(report.uuid));
+  EXPECT_FALSE(FileExists(report.file_path));
+}
+
+TEST_F(CrashReportDatabaseTest, ReadEmptyDatabase) {
+  CrashReportDatabase::Report report;
+  CreateCrashReport(&report);
+  EXPECT_EQ(CrashReportDatabase::kNoError, db()->DeleteReport(report.uuid));
+
+  // Deleting and the creating another report causes an empty database to be
+  // loaded. Make sure this is handled.
+
+  CrashReportDatabase::Report report2;
+  CreateCrashReport(&report2);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_win.cc b/third_party/crashpad/crashpad/client/crash_report_database_win.cc
index 7f4ede4f..d7968bd 100644
--- a/third_party/crashpad/crashpad/client/crash_report_database_win.cc
+++ b/third_party/crashpad/crashpad/client/crash_report_database_win.cc
@@ -18,6 +18,8 @@
 #include <time.h>
 #include <windows.h>
 
+#include <utility>
+
 #include "base/logging.h"
 #include "base/numerics/safe_math.h"
 #include "base/strings/string16.h"
@@ -25,7 +27,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "client/settings.h"
 #include "util/misc/initialization_state_dcheck.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 
@@ -417,26 +418,29 @@
     return;
   }
 
-  std::vector<MetadataFileReportRecord> records(header.num_records);
-  if (!LoggingReadFile(handle_.get(), &records[0], records_size.ValueOrDie())) {
-    LOG(ERROR) << "failed to read records";
-    return;
-  }
-
-  std::string string_table = ReadRestOfFileAsString(handle_.get());
-  if (string_table.empty() || string_table.back() != '\0') {
-    LOG(ERROR) << "bad string table";
-    return;
-  }
-
   std::vector<ReportDisk> reports;
-  for (const auto& record : records) {
-    if (record.file_path_index >= string_table.size() ||
-        record.id_index >= string_table.size()) {
-      LOG(ERROR) << "invalid string table index";
+  if (header.num_records > 0) {
+    std::vector<MetadataFileReportRecord> records(header.num_records);
+    if (!LoggingReadFile(
+            handle_.get(), &records[0], records_size.ValueOrDie())) {
+      LOG(ERROR) << "failed to read records";
       return;
     }
-    reports.push_back(ReportDisk(record, report_dir_, string_table));
+
+    std::string string_table = ReadRestOfFileAsString(handle_.get());
+    if (string_table.empty() || string_table.back() != '\0') {
+      LOG(ERROR) << "bad string table";
+      return;
+    }
+
+    for (const auto& record : records) {
+      if (record.file_path_index >= string_table.size() ||
+          record.id_index >= string_table.size()) {
+        LOG(ERROR) << "invalid string table index";
+        return;
+      }
+      reports.push_back(ReportDisk(record, report_dir_, string_table));
+    }
   }
   reports_.swap(reports);
 }
@@ -466,6 +470,9 @@
     return;
   }
 
+  if (num_records == 0)
+    return;
+
   // Build the records and string table we're going to write.
   std::string string_table;
   std::vector<MetadataFileReportRecord> records;
@@ -816,7 +823,7 @@
   scoped_ptr<CrashReportDatabaseWin> database_win(
       new CrashReportDatabaseWin(path));
   return database_win->Initialize(may_create)
-             ? crashpad::move(database_win)
+             ? std::move(database_win)
              : scoped_ptr<CrashReportDatabaseWin>();
 }
 
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
index 4a3673fb..cce11d1 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
+++ b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
@@ -20,6 +20,8 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <utility>
+
 #include "base/logging.h"
 #include "base/mac/mach_logging.h"
 #include "base/posix/eintr_wrapper.h"
@@ -32,7 +34,6 @@
 #include "util/mach/notify_server.h"
 #include "util/misc/clock.h"
 #include "util/misc/implicit_cast.h"
-#include "util/stdlib/move.h"
 #include "util/posix/close_multiple.h"
 
 namespace crashpad {
@@ -159,7 +160,7 @@
                      url,
                      annotations,
                      arguments,
-                     crashpad::move(receive_right),
+                     std::move(receive_right),
                      handler_restarter.get(),
                      false)) {
       return base::mac::ScopedMachSendRight();
@@ -539,7 +540,7 @@
     return false;
   }
 
-  SetHandlerMachPort(crashpad::move(exception_port));
+  SetHandlerMachPort(std::move(exception_port));
   return true;
 }
 
@@ -549,14 +550,14 @@
     return false;
   }
 
-  SetHandlerMachPort(crashpad::move(exception_port));
+  SetHandlerMachPort(std::move(exception_port));
   return true;
 }
 
 void CrashpadClient::SetHandlerMachPort(
     base::mac::ScopedMachSendRight exception_port) {
   DCHECK(exception_port.is_valid());
-  exception_port_ = crashpad::move(exception_port);
+  exception_port_ = std::move(exception_port);
 }
 
 bool CrashpadClient::UseHandler() {
diff --git a/third_party/crashpad/crashpad/client/settings.cc b/third_party/crashpad/crashpad/client/settings.cc
index e7ff2a90e..b991a38 100644
--- a/third_party/crashpad/crashpad/client/settings.cc
+++ b/third_party/crashpad/crashpad/client/settings.cc
@@ -18,7 +18,6 @@
 
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/in_range_cast.h"
 
 namespace crashpad {
diff --git a/third_party/crashpad/crashpad/compat/compat.gyp b/third_party/crashpad/crashpad/compat/compat.gyp
index 176fe4f9..f1cd4933 100644
--- a/third_party/crashpad/crashpad/compat/compat.gyp
+++ b/third_party/crashpad/crashpad/compat/compat.gyp
@@ -22,12 +22,14 @@
       'type': 'static_library',
       'sources': [
         'mac/AvailabilityMacros.h',
-        'mac/kern/exc_resource.h'
+        'mac/kern/exc_resource.h',
         'mac/mach/mach.h',
         'mac/mach-o/getsect.cc',
         'mac/mach-o/getsect.h',
         'mac/mach-o/loader.h',
         'mac/sys/resource.h',
+        'non_cxx11_lib/type_traits',
+        'non_cxx11_lib/utility',
         'non_mac/mach/mach.h',
         'non_win/dbghelp.h',
         'non_win/minwinbase.h',
@@ -50,10 +52,12 @@
           ],
           'include_dirs': [
             'mac',
+            'non_cxx11_lib',
           ],
           'direct_dependent_settings': {
             'include_dirs': [
               'mac',
+              'non_cxx11_lib',
             ],
           },
         }],
diff --git a/third_party/crashpad/crashpad/compat/non_cxx11_lib/type_traits b/third_party/crashpad/crashpad/compat/non_cxx11_lib/type_traits
new file mode 100644
index 0000000..9f11fd4a
--- /dev/null
+++ b/third_party/crashpad/crashpad/compat/non_cxx11_lib/type_traits
@@ -0,0 +1,37 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_COMPAT_NON_CXX11_LIB_TYPE_TRAITS_
+#define CRASHPAD_COMPAT_NON_CXX11_LIB_TYPE_TRAITS_
+
+#include "util/stdlib/cxx.h"
+
+#if CXX_LIBRARY_VERSION >= 2011
+
+#include_next <type_traits>
+
+#else
+
+namespace std {
+
+template <class T>
+struct remove_reference { using type = T; };
+template <class T>
+struct remove_reference<T&> { using type = T; };
+
+}  // namespace std
+
+#endif  // CXX_LIBRARY_VERSION
+
+#endif  // CRASHPAD_COMPAT_NON_CXX11_LIB_TYPE_TRAITS_
diff --git a/third_party/crashpad/crashpad/compat/non_cxx11_lib/utility b/third_party/crashpad/crashpad/compat/non_cxx11_lib/utility
new file mode 100644
index 0000000..8aa3de1
--- /dev/null
+++ b/third_party/crashpad/crashpad/compat/non_cxx11_lib/utility
@@ -0,0 +1,46 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_COMPAT_NON_CXX11_LIB_UTILITY_
+#define CRASHPAD_COMPAT_NON_CXX11_LIB_UTILITY_
+
+#include_next <utility>
+
+#include "util/stdlib/cxx.h"
+
+#if CXX_LIBRARY_VERSION < 2011
+
+#include <type_traits>
+
+namespace std {
+
+template <class T>
+T&& forward(typename remove_reference<T>::type& t) noexcept {
+  return static_cast<T&&>(t);
+}
+template <class T>
+T&& forward(typename remove_reference<T>::type&& t) noexcept {
+  return static_cast<T&&>(t);
+}
+
+template <class T>
+typename remove_reference<T>::type&& move(T&& t) noexcept {
+  return static_cast<typename remove_reference<T>::type&&>(t);
+}
+
+}  // namespace std
+
+#endif  // CXX_LIBRARY_VERSION
+
+#endif  // CRASHPAD_COMPAT_NON_CXX11_LIB_UTILITY_
diff --git a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
index c5fdfaad..7d29aa1 100644
--- a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
+++ b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
@@ -28,7 +28,6 @@
 #include "snapshot/minidump/process_snapshot_minidump.h"
 #include "snapshot/module_snapshot.h"
 #include "util/file/file_reader.h"
-#include "util/stdlib/move.h"
 #include "util/misc/uuid.h"
 #include "util/net/http_body.h"
 #include "util/net/http_multipart_builder.h"
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc
index 923d2b7..7ad13f6 100644
--- a/third_party/crashpad/crashpad/handler/handler_main.cc
+++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -19,6 +19,7 @@
 
 #include <map>
 #include <string>
+#include <utility>
 
 #include "base/auto_reset.h"
 #include "base/files/file_path.h"
@@ -33,7 +34,6 @@
 #include "tools/tool_support.h"
 #include "handler/crash_report_upload_thread.h"
 #include "util/file/file_io.h"
-#include "util/stdlib/move.h"
 #include "util/stdlib/map_insert.h"
 #include "util/stdlib/string_number_conversion.h"
 #include "util/string/split_string.h"
@@ -315,7 +315,7 @@
   }
 
   ExceptionHandlerServer exception_handler_server(
-      crashpad::move(receive_right), !options.mach_service.empty());
+      std::move(receive_right), !options.mach_service.empty());
   base::AutoReset<ExceptionHandlerServer*> reset_g_exception_handler_server(
       &g_exception_handler_server, &exception_handler_server);
 
@@ -337,9 +337,12 @@
     reset_sigterm.reset(&old_sa);
   }
 #elif defined(OS_WIN)
+  // Shut down as late as possible relative to programs we're watching.
+  if (!SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY))
+    PLOG(ERROR) << "SetProcessShutdownParameters";
+
   ExceptionHandlerServer exception_handler_server(!options.pipe_name.empty());
 
-  std::string pipe_name;
   if (!options.pipe_name.empty()) {
     exception_handler_server.SetPipeName(base::UTF8ToUTF16(options.pipe_name));
   } else if (options.handshake_handle != INVALID_HANDLE_VALUE) {
diff --git a/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc b/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc
index 050cc6f3..38a016e 100644
--- a/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc
+++ b/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc
@@ -14,6 +14,8 @@
 
 #include "handler/mac/exception_handler_server.h"
 
+#include <utility>
+
 #include "base/logging.h"
 #include "base/mac/mach_logging.h"
 #include "util/mach/composite_mach_message_server.h"
@@ -21,7 +23,6 @@
 #include "util/mach/mach_message.h"
 #include "util/mach/mach_message_server.h"
 #include "util/mach/notify_server.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 
@@ -184,7 +185,7 @@
 ExceptionHandlerServer::ExceptionHandlerServer(
     base::mac::ScopedMachReceiveRight receive_port,
     bool launchd)
-    : receive_port_(crashpad::move(receive_port)),
+    : receive_port_(std::move(receive_port)),
       notify_port_(NewMachPort(MACH_PORT_RIGHT_RECEIVE)),
       launchd_(launchd) {
   CHECK(receive_port_.is_valid());
diff --git a/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer.cc
index ea50152..2f2cd552 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer.cc
@@ -14,12 +14,13 @@
 
 #include "minidump/minidump_crashpad_info_writer.h"
 
+#include <utility>
+
 #include "base/logging.h"
 #include "minidump/minidump_module_crashpad_info_writer.h"
 #include "minidump/minidump_simple_string_dictionary_writer.h"
 #include "snapshot/process_snapshot.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 
@@ -52,14 +53,14 @@
   simple_annotations->InitializeFromMap(
       process_snapshot->AnnotationsSimpleMap());
   if (simple_annotations->IsUseful()) {
-    SetSimpleAnnotations(crashpad::move(simple_annotations));
+    SetSimpleAnnotations(std::move(simple_annotations));
   }
 
   auto modules = make_scoped_ptr(new MinidumpModuleCrashpadInfoListWriter());
   modules->InitializeFromSnapshot(process_snapshot->Modules());
 
   if (modules->IsUseful()) {
-    SetModuleList(crashpad::move(modules));
+    SetModuleList(std::move(modules));
   }
 }
 
@@ -79,14 +80,14 @@
     scoped_ptr<MinidumpSimpleStringDictionaryWriter> simple_annotations) {
   DCHECK_EQ(state(), kStateMutable);
 
-  simple_annotations_ = crashpad::move(simple_annotations);
+  simple_annotations_ = std::move(simple_annotations);
 }
 
 void MinidumpCrashpadInfoWriter::SetModuleList(
     scoped_ptr<MinidumpModuleCrashpadInfoListWriter> module_list) {
   DCHECK_EQ(state(), kStateMutable);
 
-  module_list_ = crashpad::move(module_list);
+  module_list_ = std::move(module_list);
 }
 
 bool MinidumpCrashpadInfoWriter::Freeze() {
diff --git a/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer_test.cc
index bbfbdfc..d5ff65ce 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_crashpad_info_writer_test.cc
@@ -19,6 +19,7 @@
 
 #include <map>
 #include <string>
+#include <utility>
 
 #include "gtest/gtest.h"
 #include "minidump/minidump_extensions.h"
@@ -31,7 +32,6 @@
 #include "snapshot/test/test_module_snapshot.h"
 #include "snapshot/test/test_process_snapshot.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -68,7 +68,7 @@
   auto crashpad_info_writer = make_scoped_ptr(new MinidumpCrashpadInfoWriter());
   EXPECT_FALSE(crashpad_info_writer->IsUseful());
 
-  minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer));
+  minidump_file_writer.AddStream(std::move(crashpad_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -103,7 +103,7 @@
 
   EXPECT_TRUE(crashpad_info_writer->IsUseful());
 
-  minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer));
+  minidump_file_writer.AddStream(std::move(crashpad_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -138,13 +138,13 @@
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   simple_string_dictionary_entry_writer->SetKeyValue(kKey, kValue);
   simple_string_dictionary_writer->AddEntry(
-      crashpad::move(simple_string_dictionary_entry_writer));
+      std::move(simple_string_dictionary_entry_writer));
   crashpad_info_writer->SetSimpleAnnotations(
-      crashpad::move(simple_string_dictionary_writer));
+      std::move(simple_string_dictionary_writer));
 
   EXPECT_TRUE(crashpad_info_writer->IsUseful());
 
-  minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer));
+  minidump_file_writer.AddStream(std::move(crashpad_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -178,12 +178,13 @@
   auto module_list_writer =
       make_scoped_ptr(new MinidumpModuleCrashpadInfoListWriter());
   auto module_writer = make_scoped_ptr(new MinidumpModuleCrashpadInfoWriter());
-  module_list_writer->AddModule(crashpad::move(module_writer), kMinidumpModuleListIndex);
-  crashpad_info_writer->SetModuleList(crashpad::move(module_list_writer));
+  module_list_writer->AddModule(std::move(module_writer),
+                                kMinidumpModuleListIndex);
+  crashpad_info_writer->SetModuleList(std::move(module_list_writer));
 
   EXPECT_TRUE(crashpad_info_writer->IsUseful());
 
-  minidump_file_writer.AddStream(crashpad::move(crashpad_info_writer));
+  minidump_file_writer.AddStream(std::move(crashpad_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -233,7 +234,7 @@
   auto process_snapshot = make_scoped_ptr(new TestProcessSnapshot());
 
   auto module_snapshot = make_scoped_ptr(new TestModuleSnapshot());
-  process_snapshot->AddModule(crashpad::move(module_snapshot));
+  process_snapshot->AddModule(std::move(module_snapshot));
 
   auto info_writer = make_scoped_ptr(new MinidumpCrashpadInfoWriter());
   info_writer->InitializeFromSnapshot(process_snapshot.get());
@@ -252,14 +253,14 @@
   module_snapshot.reset(new TestModuleSnapshot());
   std::vector<std::string> annotations_list(1, std::string(kEntry));
   module_snapshot->SetAnnotationsVector(annotations_list);
-  process_snapshot->AddModule(crashpad::move(module_snapshot));
+  process_snapshot->AddModule(std::move(module_snapshot));
 
   info_writer.reset(new MinidumpCrashpadInfoWriter());
   info_writer->InitializeFromSnapshot(process_snapshot.get());
   EXPECT_TRUE(info_writer->IsUseful());
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(info_writer));
+  minidump_file_writer.AddStream(std::move(info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
diff --git a/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc
index f11b86f..cd471b9c 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_exception_writer.cc
@@ -16,12 +16,13 @@
 
 #include <sys/types.h>
 
+#include <utility>
+
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "minidump/minidump_context_writer.h"
 #include "snapshot/exception_snapshot.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 
@@ -49,14 +50,14 @@
 
   scoped_ptr<MinidumpContextWriter> context =
       MinidumpContextWriter::CreateFromSnapshot(exception_snapshot->Context());
-  SetContext(crashpad::move(context));
+  SetContext(std::move(context));
 }
 
 void MinidumpExceptionWriter::SetContext(
     scoped_ptr<MinidumpContextWriter> context) {
   DCHECK_EQ(state(), kStateMutable);
 
-  context_ = crashpad::move(context);
+  context_ = std::move(context);
 }
 
 void MinidumpExceptionWriter::SetExceptionInformation(
diff --git a/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc
index 4c6e267..bc3bfec9 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_exception_writer_test.cc
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "gtest/gtest.h"
@@ -35,7 +36,6 @@
 #include "snapshot/test/test_exception_snapshot.h"
 #include "test/gtest_death_check.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -105,9 +105,9 @@
 
   auto context_x86_writer = make_scoped_ptr(new MinidumpContextX86Writer());
   InitializeMinidumpContextX86(context_x86_writer->context(), kSeed);
-  exception_writer->SetContext(crashpad::move(context_x86_writer));
+  exception_writer->SetContext(std::move(context_x86_writer));
 
-  minidump_file_writer.AddStream(crashpad::move(exception_writer));
+  minidump_file_writer.AddStream(std::move(exception_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -145,7 +145,7 @@
 
   auto context_x86_writer = make_scoped_ptr(new MinidumpContextX86Writer());
   InitializeMinidumpContextX86(context_x86_writer->context(), kSeed);
-  exception_writer->SetContext(crashpad::move(context_x86_writer));
+  exception_writer->SetContext(std::move(context_x86_writer));
 
   exception_writer->SetThreadID(kThreadID);
   exception_writer->SetExceptionCode(kExceptionCode);
@@ -166,7 +166,7 @@
   exception_information.push_back(kExceptionInformation2);
   exception_writer->SetExceptionInformation(exception_information);
 
-  minidump_file_writer.AddStream(crashpad::move(exception_writer));
+  minidump_file_writer.AddStream(std::move(exception_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -239,7 +239,7 @@
   exception_writer->InitializeFromSnapshot(&exception_snapshot, thread_id_map);
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(exception_writer));
+  minidump_file_writer.AddStream(std::move(exception_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -261,7 +261,7 @@
   MinidumpFileWriter minidump_file_writer;
   auto exception_writer = make_scoped_ptr(new MinidumpExceptionWriter());
 
-  minidump_file_writer.AddStream(crashpad::move(exception_writer));
+  minidump_file_writer.AddStream(std::move(exception_writer));
 
   StringFile string_file;
   ASSERT_DEATH_CHECK(minidump_file_writer.WriteEverything(&string_file),
diff --git a/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
index be2b1cd..b9a9eea 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
@@ -14,6 +14,8 @@
 
 #include "minidump/minidump_file_writer.h"
 
+#include <utility>
+
 #include "base/logging.h"
 #include "minidump/minidump_crashpad_info_writer.h"
 #include "minidump/minidump_exception_writer.h"
@@ -28,7 +30,6 @@
 #include "minidump/minidump_writer_util.h"
 #include "snapshot/process_snapshot.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/safe_assignment.h"
 
 namespace crashpad {
@@ -68,11 +69,11 @@
   const SystemSnapshot* system_snapshot = process_snapshot->System();
   auto system_info = make_scoped_ptr(new MinidumpSystemInfoWriter());
   system_info->InitializeFromSnapshot(system_snapshot);
-  AddStream(crashpad::move(system_info));
+  AddStream(std::move(system_info));
 
   auto misc_info = make_scoped_ptr(new MinidumpMiscInfoWriter());
   misc_info->InitializeFromSnapshot(process_snapshot);
-  AddStream(crashpad::move(misc_info));
+  AddStream(std::move(misc_info));
 
   auto memory_list = make_scoped_ptr(new MinidumpMemoryListWriter());
   auto thread_list = make_scoped_ptr(new MinidumpThreadListWriter());
@@ -80,18 +81,18 @@
   MinidumpThreadIDMap thread_id_map;
   thread_list->InitializeFromSnapshot(process_snapshot->Threads(),
                                       &thread_id_map);
-  AddStream(crashpad::move(thread_list));
+  AddStream(std::move(thread_list));
 
   const ExceptionSnapshot* exception_snapshot = process_snapshot->Exception();
   if (exception_snapshot) {
     auto exception = make_scoped_ptr(new MinidumpExceptionWriter());
     exception->InitializeFromSnapshot(exception_snapshot, thread_id_map);
-    AddStream(crashpad::move(exception));
+    AddStream(std::move(exception));
   }
 
   auto module_list = make_scoped_ptr(new MinidumpModuleListWriter());
   module_list->InitializeFromSnapshot(process_snapshot->Modules());
-  AddStream(crashpad::move(module_list));
+  AddStream(std::move(module_list));
 
   auto crashpad_info = make_scoped_ptr(new MinidumpCrashpadInfoWriter());
   crashpad_info->InitializeFromSnapshot(process_snapshot);
@@ -99,7 +100,7 @@
   // Since the MinidumpCrashpadInfo stream is an extension, it’s safe to not add
   // it to the minidump file if it wouldn’t carry any useful information.
   if (crashpad_info->IsUseful()) {
-    AddStream(crashpad::move(crashpad_info));
+    AddStream(std::move(crashpad_info));
   }
 
   std::vector<const MemoryMapRegionSnapshot*> memory_map_snapshot =
@@ -107,19 +108,19 @@
   if (!memory_map_snapshot.empty()) {
     auto memory_info_list = make_scoped_ptr(new MinidumpMemoryInfoListWriter());
     memory_info_list->InitializeFromSnapshot(memory_map_snapshot);
-    AddStream(crashpad::move(memory_info_list));
+    AddStream(std::move(memory_info_list));
   }
 
   std::vector<HandleSnapshot> handles_snapshot = process_snapshot->Handles();
   if (!handles_snapshot.empty()) {
     auto handle_data_writer = make_scoped_ptr(new MinidumpHandleDataWriter());
     handle_data_writer->InitializeFromSnapshot(handles_snapshot);
-    AddStream(crashpad::move(handle_data_writer));
+    AddStream(std::move(handle_data_writer));
   }
 
   memory_list->AddFromSnapshot(process_snapshot->ExtraMemory());
 
-  AddStream(crashpad::move(memory_list));
+  AddStream(std::move(memory_list));
 }
 
 void MinidumpFileWriter::SetTimestamp(time_t timestamp) {
diff --git a/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc
index 2295a99..314c758 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc
@@ -18,6 +18,7 @@
 #include <dbghelp.h>
 
 #include <string>
+#include <utility>
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
@@ -35,7 +36,6 @@
 #include "snapshot/test/test_thread_snapshot.h"
 #include "test/gtest_death_check.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -97,7 +97,7 @@
   const uint8_t kStreamValue = 0x5a;
   auto stream =
       make_scoped_ptr(new TestStream(kStreamType, kStreamSize, kStreamValue));
-  minidump_file.AddStream(crashpad::move(stream));
+  minidump_file.AddStream(std::move(stream));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file.WriteEverything(&string_file));
@@ -136,7 +136,7 @@
   const uint8_t kStream0Value = 0x5a;
   auto stream0 = make_scoped_ptr(
       new TestStream(kStream0Type, kStream0Size, kStream0Value));
-  minidump_file.AddStream(crashpad::move(stream0));
+  minidump_file.AddStream(std::move(stream0));
 
   // Make the second stream’s type be a smaller quantity than the first stream’s
   // to test that the streams show up in the order that they were added, not in
@@ -146,14 +146,14 @@
   const uint8_t kStream1Value = 0xa5;
   auto stream1 = make_scoped_ptr(
       new TestStream(kStream1Type, kStream1Size, kStream1Value));
-  minidump_file.AddStream(crashpad::move(stream1));
+  minidump_file.AddStream(std::move(stream1));
 
   const size_t kStream2Size = 1;
   const MinidumpStreamType kStream2Type = static_cast<MinidumpStreamType>(0x7e);
   const uint8_t kStream2Value = 0x36;
   auto stream2 = make_scoped_ptr(
       new TestStream(kStream2Type, kStream2Size, kStream2Value));
-  minidump_file.AddStream(crashpad::move(stream2));
+  minidump_file.AddStream(std::move(stream2));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file.WriteEverything(&string_file));
@@ -220,7 +220,7 @@
   const size_t kStreamSize = 0;
   const MinidumpStreamType kStreamType = static_cast<MinidumpStreamType>(0x4d);
   auto stream = make_scoped_ptr(new TestStream(kStreamType, kStreamSize, 0));
-  minidump_file.AddStream(crashpad::move(stream));
+  minidump_file.AddStream(std::move(stream));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file.WriteEverything(&string_file));
@@ -252,7 +252,7 @@
   auto system_snapshot = make_scoped_ptr(new TestSystemSnapshot());
   system_snapshot->SetCPUArchitecture(kCPUArchitectureX86_64);
   system_snapshot->SetOperatingSystem(SystemSnapshot::kOperatingSystemMacOSX);
-  process_snapshot.SetSystem(crashpad::move(system_snapshot));
+  process_snapshot.SetSystem(std::move(system_snapshot));
 
   auto peb_snapshot = make_scoped_ptr(new TestMemorySnapshot());
   const uint64_t kPebAddress = 0x07f90000;
@@ -260,7 +260,7 @@
   const size_t kPebSize = 0x280;
   peb_snapshot->SetSize(kPebSize);
   peb_snapshot->SetValue('p');
-  process_snapshot.AddExtraMemory(crashpad::move(peb_snapshot));
+  process_snapshot.AddExtraMemory(std::move(peb_snapshot));
 
   MinidumpFileWriter minidump_file_writer;
   minidump_file_writer.InitializeFromSnapshot(&process_snapshot);
@@ -316,22 +316,22 @@
   auto system_snapshot = make_scoped_ptr(new TestSystemSnapshot());
   system_snapshot->SetCPUArchitecture(kCPUArchitectureX86_64);
   system_snapshot->SetOperatingSystem(SystemSnapshot::kOperatingSystemMacOSX);
-  process_snapshot.SetSystem(crashpad::move(system_snapshot));
+  process_snapshot.SetSystem(std::move(system_snapshot));
 
   auto thread_snapshot = make_scoped_ptr(new TestThreadSnapshot());
   InitializeCPUContextX86_64(thread_snapshot->MutableContext(), 5);
-  process_snapshot.AddThread(crashpad::move(thread_snapshot));
+  process_snapshot.AddThread(std::move(thread_snapshot));
 
   auto exception_snapshot = make_scoped_ptr(new TestExceptionSnapshot());
   InitializeCPUContextX86_64(exception_snapshot->MutableContext(), 11);
-  process_snapshot.SetException(crashpad::move(exception_snapshot));
+  process_snapshot.SetException(std::move(exception_snapshot));
 
   // The module does not have anything that needs to be represented in a
   // MinidumpModuleCrashpadInfo structure, so no such structure is expected to
   // be present, which will in turn suppress the addition of a
   // MinidumpCrashpadInfo stream.
   auto module_snapshot = make_scoped_ptr(new TestModuleSnapshot());
-  process_snapshot.AddModule(crashpad::move(module_snapshot));
+  process_snapshot.AddModule(std::move(module_snapshot));
 
   MinidumpFileWriter minidump_file_writer;
   minidump_file_writer.InitializeFromSnapshot(&process_snapshot);
@@ -380,22 +380,22 @@
   auto system_snapshot = make_scoped_ptr(new TestSystemSnapshot());
   system_snapshot->SetCPUArchitecture(kCPUArchitectureX86_64);
   system_snapshot->SetOperatingSystem(SystemSnapshot::kOperatingSystemMacOSX);
-  process_snapshot.SetSystem(crashpad::move(system_snapshot));
+  process_snapshot.SetSystem(std::move(system_snapshot));
 
   auto thread_snapshot = make_scoped_ptr(new TestThreadSnapshot());
   InitializeCPUContextX86_64(thread_snapshot->MutableContext(), 5);
-  process_snapshot.AddThread(crashpad::move(thread_snapshot));
+  process_snapshot.AddThread(std::move(thread_snapshot));
 
   auto exception_snapshot = make_scoped_ptr(new TestExceptionSnapshot());
   InitializeCPUContextX86_64(exception_snapshot->MutableContext(), 11);
-  process_snapshot.SetException(crashpad::move(exception_snapshot));
+  process_snapshot.SetException(std::move(exception_snapshot));
 
   // The module needs an annotation for the MinidumpCrashpadInfo stream to be
   // considered useful and be included.
   auto module_snapshot = make_scoped_ptr(new TestModuleSnapshot());
   std::vector<std::string> annotations_list(1, std::string("annotation"));
   module_snapshot->SetAnnotationsVector(annotations_list);
-  process_snapshot.AddModule(crashpad::move(module_snapshot));
+  process_snapshot.AddModule(std::move(module_snapshot));
 
   MinidumpFileWriter minidump_file_writer;
   minidump_file_writer.InitializeFromSnapshot(&process_snapshot);
@@ -446,7 +446,7 @@
   const uint8_t kStream0Value = 0x5a;
   auto stream0 = make_scoped_ptr(
       new TestStream(kStream0Type, kStream0Size, kStream0Value));
-  minidump_file.AddStream(crashpad::move(stream0));
+  minidump_file.AddStream(std::move(stream0));
 
   // It is an error to add a second stream of the same type.
   const size_t kStream1Size = 3;
@@ -454,7 +454,7 @@
   const uint8_t kStream1Value = 0xa5;
   auto stream1 = make_scoped_ptr(
       new TestStream(kStream1Type, kStream1Size, kStream1Value));
-  ASSERT_DEATH_CHECK(minidump_file.AddStream(crashpad::move(stream1)),
+  ASSERT_DEATH_CHECK(minidump_file.AddStream(std::move(stream1)),
                      "already present");
 }
 
diff --git a/third_party/crashpad/crashpad/minidump/minidump_handle_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_handle_writer_test.cc
index 049a095..2a5445d 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_handle_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_handle_writer_test.cc
@@ -15,6 +15,7 @@
 #include "minidump/minidump_handle_writer.h"
 
 #include <string>
+#include <utility>
 
 #include "base/strings/utf_string_conversions.h"
 #include "gtest/gtest.h"
@@ -23,7 +24,6 @@
 #include "minidump/test/minidump_string_writer_test_util.h"
 #include "minidump/test/minidump_writable_test_util.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -58,7 +58,7 @@
 TEST(MinidumpHandleDataWriter, Empty) {
   MinidumpFileWriter minidump_file_writer;
   auto handle_data_writer = make_scoped_ptr(new MinidumpHandleDataWriter());
-  minidump_file_writer.AddStream(crashpad::move(handle_data_writer));
+  minidump_file_writer.AddStream(std::move(handle_data_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -91,7 +91,7 @@
 
   handle_data_writer->InitializeFromSnapshot(snapshot);
 
-  minidump_file_writer.AddStream(crashpad::move(handle_data_writer));
+  minidump_file_writer.AddStream(std::move(handle_data_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -149,7 +149,7 @@
 
   handle_data_writer->InitializeFromSnapshot(snapshot);
 
-  minidump_file_writer.AddStream(crashpad::move(handle_data_writer));
+  minidump_file_writer.AddStream(std::move(handle_data_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
diff --git a/third_party/crashpad/crashpad/minidump/minidump_memory_info_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_memory_info_writer_test.cc
index a1073f8..f59cbb8 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_memory_info_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_memory_info_writer_test.cc
@@ -15,6 +15,7 @@
 #include "minidump/minidump_memory_info_writer.h"
 
 #include <string>
+#include <utility>
 
 #include "gtest/gtest.h"
 #include "minidump/minidump_file_writer.h"
@@ -22,7 +23,6 @@
 #include "minidump/test/minidump_writable_test_util.h"
 #include "snapshot/test/test_memory_map_region_snapshot.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -59,7 +59,7 @@
   MinidumpFileWriter minidump_file_writer;
   auto memory_info_list_writer =
       make_scoped_ptr(new MinidumpMemoryInfoListWriter());
-  minidump_file_writer.AddStream(crashpad::move(memory_info_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_info_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -96,7 +96,7 @@
   memory_map.push_back(memory_map_region.get());
   memory_info_list_writer->InitializeFromSnapshot(memory_map);
 
-  minidump_file_writer.AddStream(crashpad::move(memory_info_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_info_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
diff --git a/third_party/crashpad/crashpad/minidump/minidump_memory_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_memory_writer.cc
index 1c9b2858..3528655 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_memory_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_memory_writer.cc
@@ -14,11 +14,12 @@
 
 #include "minidump/minidump_memory_writer.h"
 
+#include <utility>
+
 #include "base/auto_reset.h"
 #include "base/logging.h"
 #include "snapshot/memory_snapshot.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/safe_assignment.h"
 
 namespace crashpad {
@@ -178,7 +179,7 @@
   for (const MemorySnapshot* memory_snapshot : memory_snapshots) {
     scoped_ptr<MinidumpMemoryWriter> memory =
         MinidumpMemoryWriter::CreateFromSnapshot(memory_snapshot);
-    AddMemory(crashpad::move(memory));
+    AddMemory(std::move(memory));
   }
 }
 
diff --git a/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc
index 38d3cb2..cefe7475 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_memory_writer_test.cc
@@ -18,6 +18,8 @@
 #include <dbghelp.h>
 #include <stdint.h>
 
+#include <utility>
+
 #include "base/basictypes.h"
 #include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
@@ -30,7 +32,6 @@
 #include "minidump/test/minidump_writable_test_util.h"
 #include "snapshot/test/test_memory_snapshot.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 #include "util/stdlib/pointer_container.h"
 
 namespace crashpad {
@@ -81,7 +82,7 @@
   MinidumpFileWriter minidump_file_writer;
   auto memory_list_writer = make_scoped_ptr(new MinidumpMemoryListWriter());
 
-  minidump_file_writer.AddStream(crashpad::move(memory_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -107,9 +108,9 @@
 
   auto memory_writer = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kBaseAddress, kSize, kValue));
-  memory_list_writer->AddMemory(crashpad::move(memory_writer));
+  memory_list_writer->AddMemory(std::move(memory_writer));
 
-  minidump_file_writer.AddStream(crashpad::move(memory_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -145,12 +146,12 @@
 
   auto memory_writer_0 = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kBaseAddress0, kSize0, kValue0));
-  memory_list_writer->AddMemory(crashpad::move(memory_writer_0));
+  memory_list_writer->AddMemory(std::move(memory_writer_0));
   auto memory_writer_1 = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kBaseAddress1, kSize1, kValue1));
-  memory_list_writer->AddMemory(crashpad::move(memory_writer_1));
+  memory_list_writer->AddMemory(std::move(memory_writer_1));
 
-  minidump_file_writer.AddStream(crashpad::move(memory_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -249,7 +250,7 @@
   auto memory_list_writer = make_scoped_ptr(new MinidumpMemoryListWriter());
   memory_list_writer->AddExtraMemory(test_memory_stream->memory());
 
-  minidump_file_writer.AddStream(crashpad::move(test_memory_stream));
+  minidump_file_writer.AddStream(std::move(test_memory_stream));
 
   const uint64_t kBaseAddress1 = 0x2000;
   const size_t kSize1 = 0x0400;
@@ -257,9 +258,9 @@
 
   auto memory_writer = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kBaseAddress1, kSize1, kValue1));
-  memory_list_writer->AddMemory(crashpad::move(memory_writer));
+  memory_list_writer->AddMemory(std::move(memory_writer));
 
-  minidump_file_writer.AddStream(crashpad::move(memory_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -337,7 +338,7 @@
   memory_list_writer->AddFromSnapshot(memory_snapshots);
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(memory_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
diff --git a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc
index 64825ad..de8cde3 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer_test.cc
@@ -19,6 +19,7 @@
 #include <string.h>
 
 #include <string>
+#include <utility>
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
@@ -32,7 +33,6 @@
 #include "snapshot/test/test_process_snapshot.h"
 #include "snapshot/test/test_system_snapshot.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 #include "util/stdlib/strlcpy.h"
 
 namespace crashpad {
@@ -169,7 +169,7 @@
   MinidumpFileWriter minidump_file_writer;
   auto misc_info_writer = make_scoped_ptr(new MinidumpMiscInfoWriter());
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -190,7 +190,7 @@
 
   misc_info_writer->SetProcessID(kProcessId);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -216,7 +216,7 @@
   misc_info_writer->SetProcessTimes(
       kProcessCreateTime, kProcessUserTime, kProcessKernelTime);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -249,7 +249,7 @@
                                           kProcessorMaxIdleState,
                                           kProcessorCurrentIdleState);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -276,7 +276,7 @@
 
   misc_info_writer->SetProcessIntegrityLevel(kProcessIntegrityLevel);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -299,7 +299,7 @@
 
   misc_info_writer->SetProcessExecuteFlags(kProcessExecuteFlags);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -322,7 +322,7 @@
 
   misc_info_writer->SetProtectedProcess(kProtectedProcess);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -359,7 +359,7 @@
                                 kDaylightDate,
                                 kDaylightBias);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -420,7 +420,7 @@
                                 kSystemTimeZero,
                                 kDaylightBias);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -461,7 +461,7 @@
 
   misc_info_writer->SetBuildString(kBuildString, kDebugBuildString);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -498,7 +498,7 @@
 
   misc_info_writer->SetBuildString(build_string, debug_build_string);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -568,7 +568,7 @@
                                 kDaylightBias);
   misc_info_writer->SetBuildString(kBuildString, kDebugBuildString);
 
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -702,13 +702,13 @@
   system_snapshot->SetOSVersionFull(kOSVersionFull);
   system_snapshot->SetMachineDescription(kMachineDescription);
 
-  process_snapshot.SetSystem(crashpad::move(system_snapshot));
+  process_snapshot.SetSystem(std::move(system_snapshot));
 
   auto misc_info_writer = make_scoped_ptr(new MinidumpMiscInfoWriter());
   misc_info_writer->InitializeFromSnapshot(&process_snapshot);
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(misc_info_writer));
+  minidump_file_writer.AddStream(std::move(misc_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
diff --git a/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer.cc
index 5b71ec2..c4a09c33c 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer.cc
@@ -16,11 +16,12 @@
 
 #include <sys/types.h>
 
+#include <utility>
+
 #include "base/logging.h"
 #include "minidump/minidump_simple_string_dictionary_writer.h"
 #include "snapshot/module_snapshot.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/safe_assignment.h"
 
 namespace crashpad {
@@ -45,7 +46,7 @@
   auto list_annotations = make_scoped_ptr(new MinidumpUTF8StringListWriter());
   list_annotations->InitializeFromVector(module_snapshot->AnnotationsVector());
   if (list_annotations->IsUseful()) {
-    SetListAnnotations(crashpad::move(list_annotations));
+    SetListAnnotations(std::move(list_annotations));
   }
 
   auto simple_annotations =
@@ -53,7 +54,7 @@
   simple_annotations->InitializeFromMap(
       module_snapshot->AnnotationsSimpleMap());
   if (simple_annotations->IsUseful()) {
-    SetSimpleAnnotations(crashpad::move(simple_annotations));
+    SetSimpleAnnotations(std::move(simple_annotations));
   }
 }
 
@@ -61,14 +62,14 @@
     scoped_ptr<MinidumpUTF8StringListWriter> list_annotations) {
   DCHECK_EQ(state(), kStateMutable);
 
-  list_annotations_ = crashpad::move(list_annotations);
+  list_annotations_ = std::move(list_annotations);
 }
 
 void MinidumpModuleCrashpadInfoWriter::SetSimpleAnnotations(
     scoped_ptr<MinidumpSimpleStringDictionaryWriter> simple_annotations) {
   DCHECK_EQ(state(), kStateMutable);
 
-  simple_annotations_ = crashpad::move(simple_annotations);
+  simple_annotations_ = std::move(simple_annotations);
 }
 
 bool MinidumpModuleCrashpadInfoWriter::IsUseful() const {
@@ -145,7 +146,7 @@
     auto module = make_scoped_ptr(new MinidumpModuleCrashpadInfoWriter());
     module->InitializeFromSnapshot(module_snapshot);
     if (module->IsUseful()) {
-      AddModule(crashpad::move(module), index);
+      AddModule(std::move(module), index);
     }
   }
 }
diff --git a/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc
index 79ed2667..07f44c1 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_module_crashpad_info_writer_test.cc
@@ -17,6 +17,8 @@
 #include <windows.h>
 #include <dbghelp.h>
 
+#include <utility>
+
 #include "gtest/gtest.h"
 #include "minidump/minidump_extensions.h"
 #include "minidump/minidump_simple_string_dictionary_writer.h"
@@ -25,7 +27,6 @@
 #include "minidump/test/minidump_writable_test_util.h"
 #include "snapshot/test/test_module_snapshot.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -78,7 +79,7 @@
       make_scoped_ptr(new MinidumpModuleCrashpadInfoListWriter());
   auto module_writer = make_scoped_ptr(new MinidumpModuleCrashpadInfoWriter());
   EXPECT_FALSE(module_writer->IsUseful());
-  module_list_writer->AddModule(crashpad::move(module_writer), 0);
+  module_list_writer->AddModule(std::move(module_writer), 0);
 
   EXPECT_TRUE(module_list_writer->IsUseful());
 
@@ -120,18 +121,18 @@
   auto module_writer = make_scoped_ptr(new MinidumpModuleCrashpadInfoWriter());
   auto string_list_writer = make_scoped_ptr(new MinidumpUTF8StringListWriter());
   string_list_writer->InitializeFromVector(vector);
-  module_writer->SetListAnnotations(crashpad::move(string_list_writer));
+  module_writer->SetListAnnotations(std::move(string_list_writer));
   auto simple_string_dictionary_writer =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryWriter());
   auto simple_string_dictionary_entry_writer =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   simple_string_dictionary_entry_writer->SetKeyValue(kKey, kValue);
   simple_string_dictionary_writer->AddEntry(
-      crashpad::move(simple_string_dictionary_entry_writer));
+      std::move(simple_string_dictionary_entry_writer));
   module_writer->SetSimpleAnnotations(
-      crashpad::move(simple_string_dictionary_writer));
+      std::move(simple_string_dictionary_writer));
   EXPECT_TRUE(module_writer->IsUseful());
-  module_list_writer->AddModule(crashpad::move(module_writer),
+  module_list_writer->AddModule(std::move(module_writer),
                                 kMinidumpModuleListIndex);
 
   EXPECT_TRUE(module_list_writer->IsUseful());
@@ -214,17 +215,17 @@
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   simple_string_dictionary_entry_writer_0->SetKeyValue(kKey0, kValue0);
   simple_string_dictionary_writer_0->AddEntry(
-      crashpad::move(simple_string_dictionary_entry_writer_0));
+      std::move(simple_string_dictionary_entry_writer_0));
   module_writer_0->SetSimpleAnnotations(
-      crashpad::move(simple_string_dictionary_writer_0));
+      std::move(simple_string_dictionary_writer_0));
   EXPECT_TRUE(module_writer_0->IsUseful());
-  module_list_writer->AddModule(crashpad::move(module_writer_0),
+  module_list_writer->AddModule(std::move(module_writer_0),
                                 kMinidumpModuleListIndex0);
 
   auto module_writer_1 =
       make_scoped_ptr(new MinidumpModuleCrashpadInfoWriter());
   EXPECT_FALSE(module_writer_1->IsUseful());
-  module_list_writer->AddModule(crashpad::move(module_writer_1),
+  module_list_writer->AddModule(std::move(module_writer_1),
                                 kMinidumpModuleListIndex1);
 
   auto module_writer_2 =
@@ -235,16 +236,16 @@
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   simple_string_dictionary_entry_writer_2a->SetKeyValue(kKey2A, kValue2A);
   simple_string_dictionary_writer_2->AddEntry(
-      crashpad::move(simple_string_dictionary_entry_writer_2a));
+      std::move(simple_string_dictionary_entry_writer_2a));
   auto simple_string_dictionary_entry_writer_2b =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   simple_string_dictionary_entry_writer_2b->SetKeyValue(kKey2B, kValue2B);
   simple_string_dictionary_writer_2->AddEntry(
-      crashpad::move(simple_string_dictionary_entry_writer_2b));
+      std::move(simple_string_dictionary_entry_writer_2b));
   module_writer_2->SetSimpleAnnotations(
-      crashpad::move(simple_string_dictionary_writer_2));
+      std::move(simple_string_dictionary_writer_2));
   EXPECT_TRUE(module_writer_2->IsUseful());
-  module_list_writer->AddModule(crashpad::move(module_writer_2),
+  module_list_writer->AddModule(std::move(module_writer_2),
                                 kMinidumpModuleListIndex2);
 
   EXPECT_TRUE(module_list_writer->IsUseful());
diff --git a/third_party/crashpad/crashpad/minidump/minidump_module_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_module_writer.cc
index 8cbf855..c3a0e83 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_module_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_module_writer.cc
@@ -17,6 +17,7 @@
 #include <sys/types.h>
 
 #include <limits>
+#include <utility>
 
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
@@ -25,7 +26,6 @@
 #include "snapshot/module_snapshot.h"
 #include "util/file/file_writer.h"
 #include "util/misc/implicit_cast.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/in_range_cast.h"
 #include "util/numeric/safe_assignment.h"
 
@@ -245,7 +245,7 @@
   auto codeview_record =
       make_scoped_ptr(new MinidumpModuleCodeViewRecordPDB70Writer());
   codeview_record->InitializeFromSnapshot(module_snapshot);
-  SetCodeViewRecord(crashpad::move(codeview_record));
+  SetCodeViewRecord(std::move(codeview_record));
 }
 
 const MINIDUMP_MODULE* MinidumpModuleWriter::MinidumpModule() const {
@@ -267,14 +267,14 @@
     scoped_ptr<MinidumpModuleCodeViewRecordWriter> codeview_record) {
   DCHECK_EQ(state(), kStateMutable);
 
-  codeview_record_ = crashpad::move(codeview_record);
+  codeview_record_ = std::move(codeview_record);
 }
 
 void MinidumpModuleWriter::SetMiscDebugRecord(
     scoped_ptr<MinidumpModuleMiscDebugRecordWriter> misc_debug_record) {
   DCHECK_EQ(state(), kStateMutable);
 
-  misc_debug_record_ = crashpad::move(misc_debug_record);
+  misc_debug_record_ = std::move(misc_debug_record);
 }
 
 void MinidumpModuleWriter::SetTimestamp(time_t timestamp) {
@@ -386,7 +386,7 @@
   for (const ModuleSnapshot* module_snapshot : module_snapshots) {
     auto module = make_scoped_ptr(new MinidumpModuleWriter());
     module->InitializeFromSnapshot(module_snapshot);
-    AddModule(crashpad::move(module));
+    AddModule(std::move(module));
   }
 }
 
diff --git a/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc
index 9919b0c..8d6272de 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_module_writer_test.cc
@@ -20,6 +20,8 @@
 #include <string.h>
 #include <sys/types.h>
 
+#include <utility>
+
 #include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -33,7 +35,6 @@
 #include "test/gtest_death_check.h"
 #include "util/file/string_file.h"
 #include "util/misc/implicit_cast.h"
-#include "util/stdlib/move.h"
 #include "util/misc/uuid.h"
 #include "util/stdlib/pointer_container.h"
 
@@ -69,7 +70,7 @@
   MinidumpFileWriter minidump_file_writer;
   auto module_list_writer = make_scoped_ptr(new MinidumpModuleListWriter());
 
-  minidump_file_writer.AddStream(crashpad::move(module_list_writer));
+  minidump_file_writer.AddStream(std::move(module_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -277,8 +278,8 @@
   auto module_writer = make_scoped_ptr(new MinidumpModuleWriter());
   module_writer->SetName(kModuleName);
 
-  module_list_writer->AddModule(crashpad::move(module_writer));
-  minidump_file_writer.AddStream(crashpad::move(module_list_writer));
+  module_list_writer->AddModule(std::move(module_writer));
+  minidump_file_writer.AddStream(std::move(module_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -360,16 +361,16 @@
       make_scoped_ptr(new MinidumpModuleCodeViewRecordPDB70Writer());
   codeview_pdb70_writer->SetPDBName(kPDBName);
   codeview_pdb70_writer->SetUUIDAndAge(pdb_uuid, kPDBAge);
-  module_writer->SetCodeViewRecord(crashpad::move(codeview_pdb70_writer));
+  module_writer->SetCodeViewRecord(std::move(codeview_pdb70_writer));
 
   auto misc_debug_writer =
       make_scoped_ptr(new MinidumpModuleMiscDebugRecordWriter());
   misc_debug_writer->SetDataType(kDebugType);
   misc_debug_writer->SetData(kDebugName, kDebugUTF16);
-  module_writer->SetMiscDebugRecord(crashpad::move(misc_debug_writer));
+  module_writer->SetMiscDebugRecord(std::move(misc_debug_writer));
 
-  module_list_writer->AddModule(crashpad::move(module_writer));
-  minidump_file_writer.AddStream(crashpad::move(module_list_writer));
+  module_list_writer->AddModule(std::move(module_writer));
+  minidump_file_writer.AddStream(std::move(module_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -435,16 +436,16 @@
       make_scoped_ptr(new MinidumpModuleCodeViewRecordPDB20Writer());
   codeview_pdb20_writer->SetPDBName(kPDBName);
   codeview_pdb20_writer->SetTimestampAndAge(kPDBTimestamp, kPDBAge);
-  module_writer->SetCodeViewRecord(crashpad::move(codeview_pdb20_writer));
+  module_writer->SetCodeViewRecord(std::move(codeview_pdb20_writer));
 
   auto misc_debug_writer =
       make_scoped_ptr(new MinidumpModuleMiscDebugRecordWriter());
   misc_debug_writer->SetDataType(kDebugType);
   misc_debug_writer->SetData(kDebugName, kDebugUTF16);
-  module_writer->SetMiscDebugRecord(crashpad::move(misc_debug_writer));
+  module_writer->SetMiscDebugRecord(std::move(misc_debug_writer));
 
-  module_list_writer->AddModule(crashpad::move(module_writer));
-  minidump_file_writer.AddStream(crashpad::move(module_list_writer));
+  module_list_writer->AddModule(std::move(module_writer));
+  minidump_file_writer.AddStream(std::move(module_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -512,16 +513,16 @@
       make_scoped_ptr(new MinidumpModuleCodeViewRecordPDB70Writer());
   codeview_pdb70_writer_0->SetPDBName(kPDBName0);
   codeview_pdb70_writer_0->SetUUIDAndAge(pdb_uuid_0, kPDBAge0);
-  module_writer_0->SetCodeViewRecord(crashpad::move(codeview_pdb70_writer_0));
+  module_writer_0->SetCodeViewRecord(std::move(codeview_pdb70_writer_0));
 
-  module_list_writer->AddModule(crashpad::move(module_writer_0));
+  module_list_writer->AddModule(std::move(module_writer_0));
 
   auto module_writer_1 = make_scoped_ptr(new MinidumpModuleWriter());
   module_writer_1->SetName(kModuleName1);
   module_writer_1->SetImageBaseAddress(kModuleBase1);
   module_writer_1->SetImageSize(kModuleSize1);
 
-  module_list_writer->AddModule(crashpad::move(module_writer_1));
+  module_list_writer->AddModule(std::move(module_writer_1));
 
   auto module_writer_2 = make_scoped_ptr(new MinidumpModuleWriter());
   module_writer_2->SetName(kModuleName2);
@@ -532,11 +533,11 @@
       make_scoped_ptr(new MinidumpModuleCodeViewRecordPDB20Writer());
   codeview_pdb70_writer_2->SetPDBName(kPDBName2);
   codeview_pdb70_writer_2->SetTimestampAndAge(kPDBTimestamp2, kPDBAge2);
-  module_writer_2->SetCodeViewRecord(crashpad::move(codeview_pdb70_writer_2));
+  module_writer_2->SetCodeViewRecord(std::move(codeview_pdb70_writer_2));
 
-  module_list_writer->AddModule(crashpad::move(module_writer_2));
+  module_list_writer->AddModule(std::move(module_writer_2));
 
-  minidump_file_writer.AddStream(crashpad::move(module_list_writer));
+  minidump_file_writer.AddStream(std::move(module_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -729,7 +730,7 @@
   module_list_writer->InitializeFromSnapshot(module_snapshots);
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(module_list_writer));
+  minidump_file_writer.AddStream(std::move(module_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -760,8 +761,8 @@
   MinidumpFileWriter minidump_file_writer;
   auto module_list_writer = make_scoped_ptr(new MinidumpModuleListWriter());
   auto module_writer = make_scoped_ptr(new MinidumpModuleWriter());
-  module_list_writer->AddModule(crashpad::move(module_writer));
-  minidump_file_writer.AddStream(crashpad::move(module_list_writer));
+  module_list_writer->AddModule(std::move(module_writer));
+  minidump_file_writer.AddStream(std::move(module_list_writer));
 
   StringFile string_file;
   ASSERT_DEATH_CHECK(minidump_file_writer.WriteEverything(&string_file),
diff --git a/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc
index 19a908ca..fa18dc5 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_rva_list_writer_test.cc
@@ -14,13 +14,14 @@
 
 #include "minidump/minidump_rva_list_writer.h"
 
+#include <utility>
+
 #include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
 #include "gtest/gtest.h"
 #include "minidump/test/minidump_rva_list_test_util.h"
 #include "minidump/test/minidump_writable_test_util.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -33,7 +34,7 @@
 
   void AddChild(uint32_t value) {
     auto child = make_scoped_ptr(new TestUInt32MinidumpWritable(value));
-    MinidumpRVAListWriter::AddChild(crashpad::move(child));
+    MinidumpRVAListWriter::AddChild(std::move(child));
   }
 
  private:
diff --git a/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer.cc
index 50c1f720..b3283e59 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer.cc
@@ -14,10 +14,11 @@
 
 #include "minidump/minidump_simple_string_dictionary_writer.h"
 
+#include <utility>
+
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/safe_assignment.h"
 
 namespace crashpad {
@@ -110,7 +111,7 @@
     auto entry =
         make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
     entry->SetKeyValue(iterator.first, iterator.second);
-    AddEntry(crashpad::move(entry));
+    AddEntry(std::move(entry));
   }
 }
 
diff --git a/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer_test.cc
index a8c8d02d..1e401d4 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_simple_string_dictionary_writer_test.cc
@@ -16,13 +16,13 @@
 
 #include <map>
 #include <string>
+#include <utility>
 
 #include "gtest/gtest.h"
 #include "minidump/minidump_extensions.h"
 #include "minidump/test/minidump_string_writer_test_util.h"
 #include "minidump/test/minidump_writable_test_util.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -63,7 +63,7 @@
   MinidumpSimpleStringDictionaryWriter dictionary_writer;
   auto entry_writer =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
-  dictionary_writer.AddEntry(crashpad::move(entry_writer));
+  dictionary_writer.AddEntry(std::move(entry_writer));
 
   EXPECT_TRUE(dictionary_writer.IsUseful());
 
@@ -97,7 +97,7 @@
   auto entry_writer =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   entry_writer->SetKeyValue(kKey, kValue);
-  dictionary_writer.AddEntry(crashpad::move(entry_writer));
+  dictionary_writer.AddEntry(std::move(entry_writer));
 
   EXPECT_TRUE(dictionary_writer.IsUseful());
 
@@ -135,15 +135,15 @@
   auto entry_writer_0 =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   entry_writer_0->SetKeyValue(kKey0, kValue0);
-  dictionary_writer.AddEntry(crashpad::move(entry_writer_0));
+  dictionary_writer.AddEntry(std::move(entry_writer_0));
   auto entry_writer_1 =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   entry_writer_1->SetKeyValue(kKey1, kValue1);
-  dictionary_writer.AddEntry(crashpad::move(entry_writer_1));
+  dictionary_writer.AddEntry(std::move(entry_writer_1));
   auto entry_writer_2 =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   entry_writer_2->SetKeyValue(kKey2, kValue2);
-  dictionary_writer.AddEntry(crashpad::move(entry_writer_2));
+  dictionary_writer.AddEntry(std::move(entry_writer_2));
 
   EXPECT_TRUE(dictionary_writer.IsUseful());
 
@@ -203,11 +203,11 @@
   auto entry_writer_0 =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   entry_writer_0->SetKeyValue(kKey, kValue0);
-  dictionary_writer.AddEntry(crashpad::move(entry_writer_0));
+  dictionary_writer.AddEntry(std::move(entry_writer_0));
   auto entry_writer_1 =
       make_scoped_ptr(new MinidumpSimpleStringDictionaryEntryWriter());
   entry_writer_1->SetKeyValue(kKey, kValue1);
-  dictionary_writer.AddEntry(crashpad::move(entry_writer_1));
+  dictionary_writer.AddEntry(std::move(entry_writer_1));
 
   EXPECT_TRUE(dictionary_writer.IsUseful());
 
diff --git a/third_party/crashpad/crashpad/minidump/minidump_string_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_string_writer.cc
index af210c2..bf40d256 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_string_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_string_writer.cc
@@ -16,10 +16,11 @@
 
 #include <sys/types.h>
 
+#include <utility>
+
 #include "base/logging.h"
 #include "minidump/minidump_writer_util.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/safe_assignment.h"
 
 namespace crashpad {
@@ -122,7 +123,7 @@
     const std::string& string_utf8) {
   auto string_writer = make_scoped_ptr(new MinidumpStringWriterType());
   string_writer->SetUTF8(string_utf8);
-  AddChild(crashpad::move(string_writer));
+  AddChild(std::move(string_writer));
 }
 
 template <typename MinidumpStringWriterType>
diff --git a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer_test.cc
index bc1a1b6..88bb0e0 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer_test.cc
@@ -21,6 +21,7 @@
 
 #include <algorithm>
 #include <string>
+#include <utility>
 
 #include "base/compiler_specific.h"
 #include "gtest/gtest.h"
@@ -31,7 +32,6 @@
 #include "snapshot/test/test_system_snapshot.h"
 #include "test/gtest_death_check.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -84,7 +84,7 @@
 
   system_info_writer->SetCSDVersion(std::string());
 
-  minidump_file_writer.AddStream(crashpad::move(system_info_writer));
+  minidump_file_writer.AddStream(std::move(system_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -155,7 +155,7 @@
   system_info_writer->SetCPUX86VersionAndFeatures(kCPUVersion, kCPUFeatures);
   system_info_writer->SetCPUX86AMDExtendedFeatures(kAMDFeatures);
 
-  minidump_file_writer.AddStream(crashpad::move(system_info_writer));
+  minidump_file_writer.AddStream(std::move(system_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -215,7 +215,7 @@
   system_info_writer->SetCSDVersion(kCSDVersion);
   system_info_writer->SetCPUOtherFeatures(kCPUFeatures[0], kCPUFeatures[1]);
 
-  minidump_file_writer.AddStream(crashpad::move(system_info_writer));
+  minidump_file_writer.AddStream(std::move(system_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -257,7 +257,7 @@
       kCPUVendor[0], kCPUVendor[1], kCPUVendor[2]);
   system_info_writer->SetCSDVersion(std::string());
 
-  minidump_file_writer.AddStream(crashpad::move(system_info_writer));
+  minidump_file_writer.AddStream(std::move(system_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -337,7 +337,7 @@
   system_info_writer->InitializeFromSnapshot(&system_snapshot);
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(system_info_writer));
+  minidump_file_writer.AddStream(std::move(system_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -432,7 +432,7 @@
   system_info_writer->InitializeFromSnapshot(&system_snapshot);
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(system_info_writer));
+  minidump_file_writer.AddStream(std::move(system_info_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -470,7 +470,7 @@
 TEST(MinidumpSystemInfoWriterDeathTest, NoCSDVersion) {
   MinidumpFileWriter minidump_file_writer;
   auto system_info_writer = make_scoped_ptr(new MinidumpSystemInfoWriter());
-  minidump_file_writer.AddStream(crashpad::move(system_info_writer));
+  minidump_file_writer.AddStream(std::move(system_info_writer));
 
   StringFile string_file;
   ASSERT_DEATH_CHECK(minidump_file_writer.WriteEverything(&string_file),
diff --git a/third_party/crashpad/crashpad/minidump/minidump_thread_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_thread_writer.cc
index ab426c3d..d41d2dd 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_thread_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_thread_writer.cc
@@ -16,13 +16,14 @@
 
 #include <sys/types.h>
 
+#include <utility>
+
 #include "base/logging.h"
 #include "minidump/minidump_context_writer.h"
 #include "minidump/minidump_memory_writer.h"
 #include "snapshot/memory_snapshot.h"
 #include "snapshot/thread_snapshot.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 #include "util/numeric/safe_assignment.h"
 
 namespace crashpad {
@@ -53,12 +54,12 @@
   if (stack_snapshot && stack_snapshot->Size() > 0) {
     scoped_ptr<MinidumpMemoryWriter> stack =
         MinidumpMemoryWriter::CreateFromSnapshot(stack_snapshot);
-    SetStack(crashpad::move(stack));
+    SetStack(std::move(stack));
   }
 
   scoped_ptr<MinidumpContextWriter> context =
       MinidumpContextWriter::CreateFromSnapshot(thread_snapshot->Context());
-  SetContext(crashpad::move(context));
+  SetContext(std::move(context));
 }
 
 const MINIDUMP_THREAD* MinidumpThreadWriter::MinidumpThread() const {
@@ -70,14 +71,14 @@
 void MinidumpThreadWriter::SetStack(scoped_ptr<MinidumpMemoryWriter> stack) {
   DCHECK_EQ(state(), kStateMutable);
 
-  stack_ = crashpad::move(stack);
+  stack_ = std::move(stack);
 }
 
 void MinidumpThreadWriter::SetContext(
     scoped_ptr<MinidumpContextWriter> context) {
   DCHECK_EQ(state(), kStateMutable);
 
-  context_ = crashpad::move(context);
+  context_ = std::move(context);
 }
 
 bool MinidumpThreadWriter::Freeze() {
@@ -149,7 +150,7 @@
   for (const ThreadSnapshot* thread_snapshot : thread_snapshots) {
     auto thread = make_scoped_ptr(new MinidumpThreadWriter());
     thread->InitializeFromSnapshot(thread_snapshot, thread_id_map);
-    AddThread(crashpad::move(thread));
+    AddThread(std::move(thread));
   }
 
   // Do this in a separate loop to keep the thread stacks earlier in the dump,
diff --git a/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc
index 4e3fd5c..ab0561a 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 
 #include <string>
+#include <utility>
 
 #include "base/compiler_specific.h"
 #include "base/format_macros.h"
@@ -37,7 +38,6 @@
 #include "snapshot/test/test_thread_snapshot.h"
 #include "test/gtest_death_check.h"
 #include "util/file/string_file.h"
-#include "util/stdlib/move.h"
 
 namespace crashpad {
 namespace test {
@@ -84,7 +84,7 @@
   MinidumpFileWriter minidump_file_writer;
   auto thread_list_writer = make_scoped_ptr(new MinidumpThreadListWriter());
 
-  minidump_file_writer.AddStream(crashpad::move(thread_list_writer));
+  minidump_file_writer.AddStream(std::move(thread_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -161,10 +161,10 @@
 
   auto context_x86_writer = make_scoped_ptr(new MinidumpContextX86Writer());
   InitializeMinidumpContextX86(context_x86_writer->context(), kSeed);
-  thread_writer->SetContext(crashpad::move(context_x86_writer));
+  thread_writer->SetContext(std::move(context_x86_writer));
 
-  thread_list_writer->AddThread(crashpad::move(thread_writer));
-  minidump_file_writer.AddStream(crashpad::move(thread_list_writer));
+  thread_list_writer->AddThread(std::move(thread_writer));
+  minidump_file_writer.AddStream(std::move(thread_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -223,15 +223,15 @@
 
   auto memory_writer = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kMemoryBase, kMemorySize, kMemoryValue));
-  thread_writer->SetStack(crashpad::move(memory_writer));
+  thread_writer->SetStack(std::move(memory_writer));
 
   MSVC_SUPPRESS_WARNING(4316);  // Object allocated on heap may not be aligned.
   auto context_amd64_writer = make_scoped_ptr(new MinidumpContextAMD64Writer());
   InitializeMinidumpContextAMD64(context_amd64_writer->context(), kSeed);
-  thread_writer->SetContext(crashpad::move(context_amd64_writer));
+  thread_writer->SetContext(std::move(context_amd64_writer));
 
-  thread_list_writer->AddThread(crashpad::move(thread_writer));
-  minidump_file_writer.AddStream(crashpad::move(thread_list_writer));
+  thread_list_writer->AddThread(std::move(thread_writer));
+  minidump_file_writer.AddStream(std::move(thread_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -301,13 +301,13 @@
 
   auto memory_writer_0 = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kMemoryBase0, kMemorySize0, kMemoryValue0));
-  thread_writer_0->SetStack(crashpad::move(memory_writer_0));
+  thread_writer_0->SetStack(std::move(memory_writer_0));
 
   auto context_x86_writer_0 = make_scoped_ptr(new MinidumpContextX86Writer());
   InitializeMinidumpContextX86(context_x86_writer_0->context(), kSeed0);
-  thread_writer_0->SetContext(crashpad::move(context_x86_writer_0));
+  thread_writer_0->SetContext(std::move(context_x86_writer_0));
 
-  thread_list_writer->AddThread(crashpad::move(thread_writer_0));
+  thread_list_writer->AddThread(std::move(thread_writer_0));
 
   const uint32_t kThreadID1 = 2222222;
   const uint32_t kSuspendCount1 = 222222;
@@ -328,13 +328,13 @@
 
   auto memory_writer_1 = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kMemoryBase1, kMemorySize1, kMemoryValue1));
-  thread_writer_1->SetStack(crashpad::move(memory_writer_1));
+  thread_writer_1->SetStack(std::move(memory_writer_1));
 
   auto context_x86_writer_1 = make_scoped_ptr(new MinidumpContextX86Writer());
   InitializeMinidumpContextX86(context_x86_writer_1->context(), kSeed1);
-  thread_writer_1->SetContext(crashpad::move(context_x86_writer_1));
+  thread_writer_1->SetContext(std::move(context_x86_writer_1));
 
-  thread_list_writer->AddThread(crashpad::move(thread_writer_1));
+  thread_list_writer->AddThread(std::move(thread_writer_1));
 
   const uint32_t kThreadID2 = 3333333;
   const uint32_t kSuspendCount2 = 333333;
@@ -355,16 +355,16 @@
 
   auto memory_writer_2 = make_scoped_ptr(
       new TestMinidumpMemoryWriter(kMemoryBase2, kMemorySize2, kMemoryValue2));
-  thread_writer_2->SetStack(crashpad::move(memory_writer_2));
+  thread_writer_2->SetStack(std::move(memory_writer_2));
 
   auto context_x86_writer_2 = make_scoped_ptr(new MinidumpContextX86Writer());
   InitializeMinidumpContextX86(context_x86_writer_2->context(), kSeed2);
-  thread_writer_2->SetContext(crashpad::move(context_x86_writer_2));
+  thread_writer_2->SetContext(std::move(context_x86_writer_2));
 
-  thread_list_writer->AddThread(crashpad::move(thread_writer_2));
+  thread_list_writer->AddThread(std::move(thread_writer_2));
 
-  minidump_file_writer.AddStream(crashpad::move(thread_list_writer));
-  minidump_file_writer.AddStream(crashpad::move(memory_list_writer));
+  minidump_file_writer.AddStream(std::move(thread_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -601,7 +601,7 @@
           expect_threads[index].Stack.StartOfMemoryRange);
       memory_snapshot->SetSize(expect_threads[index].Stack.Memory.DataSize);
       memory_snapshot->SetValue(memory_values[index]);
-      thread_snapshot->SetStack(crashpad::move(memory_snapshot));
+      thread_snapshot->SetStack(std::move(memory_snapshot));
     }
 
     Traits::InitializeCPUContext(thread_snapshot->MutableContext(),
@@ -611,7 +611,7 @@
     teb_snapshot->SetAddress(expect_threads[index].Teb);
     teb_snapshot->SetSize(kTebSize);
     teb_snapshot->SetValue(static_cast<char>('t' + index));
-    thread_snapshot->AddExtraMemory(crashpad::move(teb_snapshot));
+    thread_snapshot->AddExtraMemory(std::move(teb_snapshot));
 
     thread_snapshots.push_back(thread_snapshot);
   }
@@ -623,8 +623,8 @@
   thread_list_writer->InitializeFromSnapshot(thread_snapshots, &thread_id_map);
 
   MinidumpFileWriter minidump_file_writer;
-  minidump_file_writer.AddStream(crashpad::move(thread_list_writer));
-  minidump_file_writer.AddStream(crashpad::move(memory_list_writer));
+  minidump_file_writer.AddStream(std::move(thread_list_writer));
+  minidump_file_writer.AddStream(std::move(memory_list_writer));
 
   StringFile string_file;
   ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
@@ -701,8 +701,8 @@
 
   auto thread_writer = make_scoped_ptr(new MinidumpThreadWriter());
 
-  thread_list_writer->AddThread(crashpad::move(thread_writer));
-  minidump_file_writer.AddStream(crashpad::move(thread_list_writer));
+  thread_list_writer->AddThread(std::move(thread_writer));
+  minidump_file_writer.AddStream(std::move(thread_list_writer));
 
   StringFile string_file;
   ASSERT_DEATH_CHECK(minidump_file_writer.WriteEverything(&string_file),
diff --git a/third_party/crashpad/crashpad/package.h b/third_party/crashpad/crashpad/package.h
index a18d7b8..af4d1fc 100644
--- a/third_party/crashpad/crashpad/package.h
+++ b/third_party/crashpad/crashpad/package.h
@@ -23,7 +23,7 @@
 #define PACKAGE_NAME "Crashpad"
 #define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION
 #define PACKAGE_TARNAME "crashpad"
-#define PACKAGE_VERSION "0.7.0"
+#define PACKAGE_VERSION "0.8.0"
 #define PACKAGE_URL "https://crashpad.chromium.org/"
 
 #endif  // CRASHPAD_PACKAGE_H_
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot.gyp b/third_party/crashpad/crashpad/snapshot/snapshot.gyp
index 0a78e90..3f7c63ee 100644
--- a/third_party/crashpad/crashpad/snapshot/snapshot.gyp
+++ b/third_party/crashpad/crashpad/snapshot/snapshot.gyp
@@ -103,10 +103,14 @@
         'win/pe_image_annotations_reader.h',
         'win/pe_image_reader.cc',
         'win/pe_image_reader.h',
+        'win/pe_image_resource_reader.cc',
+        'win/pe_image_resource_reader.h',
         'win/process_reader_win.cc',
         'win/process_reader_win.h',
         'win/process_snapshot_win.cc',
         'win/process_snapshot_win.h',
+        'win/process_subrange_reader.cc',
+        'win/process_subrange_reader.h',
         'win/system_snapshot_win.cc',
         'win/system_snapshot_win.h',
         'win/thread_snapshot_win.cc',
diff --git a/third_party/crashpad/crashpad/snapshot/test/test_process_snapshot.h b/third_party/crashpad/crashpad/snapshot/test/test_process_snapshot.h
index 666fa0a..6e81354 100644
--- a/third_party/crashpad/crashpad/snapshot/test/test_process_snapshot.h
+++ b/third_party/crashpad/crashpad/snapshot/test/test_process_snapshot.h
@@ -21,6 +21,7 @@
 
 #include <map>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -32,7 +33,6 @@
 #include "snapshot/process_snapshot.h"
 #include "snapshot/system_snapshot.h"
 #include "snapshot/thread_snapshot.h"
-#include "util/stdlib/move.h"
 #include "util/misc/uuid.h"
 #include "util/stdlib/pointer_container.h"
 
@@ -73,7 +73,7 @@
   //! \param[in] system The system snapshot that System() will return. The
   //!     TestProcessSnapshot object takes ownership of \a system.
   void SetSystem(scoped_ptr<SystemSnapshot> system) {
-    system_ = crashpad::move(system);
+    system_ = std::move(system);
   }
 
   //! \brief Adds a thread snapshot to be returned by Threads().
@@ -97,7 +97,7 @@
   //! \param[in] exception The exception snapshot that Exception() will return.
   //!     The TestProcessSnapshot object takes ownership of \a exception.
   void SetException(scoped_ptr<ExceptionSnapshot> exception) {
-    exception_ = crashpad::move(exception);
+    exception_ = std::move(exception);
   }
 
   //! \brief Adds a memory map region snapshot to be returned by MemoryMap().
diff --git a/third_party/crashpad/crashpad/snapshot/test/test_thread_snapshot.h b/third_party/crashpad/crashpad/snapshot/test/test_thread_snapshot.h
index 49a10c6..29e3f5f 100644
--- a/third_party/crashpad/crashpad/snapshot/test/test_thread_snapshot.h
+++ b/third_party/crashpad/crashpad/snapshot/test/test_thread_snapshot.h
@@ -17,6 +17,7 @@
 
 #include <stdint.h>
 
+#include <utility>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -24,7 +25,6 @@
 #include "snapshot/cpu_context.h"
 #include "snapshot/memory_snapshot.h"
 #include "snapshot/thread_snapshot.h"
-#include "util/stdlib/move.h"
 #include "util/stdlib/pointer_container.h"
 
 namespace crashpad {
@@ -56,9 +56,7 @@
   //!
   //! \param[in] stack The memory region that Stack() will return. The
   //!     TestThreadSnapshot object takes ownership of \a stack.
-  void SetStack(scoped_ptr<MemorySnapshot> stack) {
-    stack_ = crashpad::move(stack);
-  }
+  void SetStack(scoped_ptr<MemorySnapshot> stack) { stack_ = std::move(stack); }
 
   void SetThreadID(uint64_t thread_id) { thread_id_ = thread_id; }
   void SetSuspendCount(int suspend_count) { suspend_count_ = suspend_count; }
diff --git a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc
index 49478880..0553f35 100644
--- a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc
@@ -19,7 +19,6 @@
 #include "snapshot/win/pe_image_reader.h"
 #include "util/misc/tri_state.h"
 #include "util/misc/uuid.h"
-#include "util/win/module_version.h"
 
 namespace crashpad {
 namespace internal {
@@ -210,7 +209,7 @@
 
   if (initialized_vs_fixed_file_info_.is_uninitialized()) {
     initialized_vs_fixed_file_info_.set_invalid();
-    if (GetModuleVersionAndType(base::FilePath(name_), &vs_fixed_file_info_)) {
+    if (pe_image_reader_->VSFixedFileInfo(&vs_fixed_file_info_)) {
       initialized_vs_fixed_file_info_.set_valid();
     }
   }
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc
index f408fb18..9abf0b1 100644
--- a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.cc
@@ -18,9 +18,8 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/strings/stringprintf.h"
 #include "client/crashpad_info.h"
-#include "snapshot/win/process_reader_win.h"
+#include "snapshot/win/pe_image_resource_reader.h"
 #include "util/misc/pdb_structures.h"
 #include "util/win/process_structs.h"
 
@@ -28,13 +27,6 @@
 
 namespace {
 
-std::string RangeToString(const CheckedWinAddressRange& range) {
-  return base::StringPrintf("[0x%llx + 0x%llx (%s)]",
-                            range.Base(),
-                            range.Size(),
-                            range.Is64Bit() ? "64" : "32");
-}
-
 // Map from Traits to an IMAGE_NT_HEADERSxx.
 template <class Traits>
 struct NtHeadersForTraits;
@@ -52,9 +44,7 @@
 }  // namespace
 
 PEImageReader::PEImageReader()
-    : process_reader_(nullptr),
-      module_range_(),
-      module_name_(),
+    : module_subrange_reader_(),
       initialized_() {
 }
 
@@ -67,14 +57,10 @@
                                const std::string& module_name) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 
-  process_reader_ = process_reader;
-  module_range_.SetRange(process_reader_->Is64Bit(), address, size);
-  if (!module_range_.IsValid()) {
-    LOG(WARNING) << "invalid module range for " << module_name << ": "
-                 << RangeToString(module_range_);
+  if (!module_subrange_reader_.Initialize(
+          process_reader, address, size, module_name)) {
     return false;
   }
-  module_name_ = module_name;
 
   INITIALIZATION_STATE_SET_VALID(initialized_);
   return true;
@@ -93,36 +79,34 @@
 
   if (section.Misc.VirtualSize < sizeof(process_types::CrashpadInfo<Traits>)) {
     LOG(WARNING) << "small crashpad info section size "
-                 << section.Misc.VirtualSize << ", " << module_name_;
+                 << section.Misc.VirtualSize << ", "
+                 << module_subrange_reader_.name();
     return false;
   }
 
-  WinVMAddress crashpad_info_address = Address() + section.VirtualAddress;
-  CheckedWinAddressRange crashpad_info_range(process_reader_->Is64Bit(),
-                                             crashpad_info_address,
-                                             section.Misc.VirtualSize);
-  if (!crashpad_info_range.IsValid()) {
-    LOG(WARNING) << "invalid range for crashpad info: "
-                 << RangeToString(crashpad_info_range);
+  ProcessSubrangeReader crashpad_info_subrange_reader;
+  const WinVMAddress crashpad_info_address = Address() + section.VirtualAddress;
+  if (!crashpad_info_subrange_reader.InitializeSubrange(
+          module_subrange_reader_,
+          crashpad_info_address,
+          section.Misc.VirtualSize,
+          "crashpad_info")) {
     return false;
   }
 
-  if (!module_range_.ContainsRange(crashpad_info_range)) {
-    LOG(WARNING) << "crashpad info does not fall inside module "
-                 << module_name_;
-    return false;
-  }
-
-  if (!process_reader_->ReadMemory(crashpad_info_address,
-                                   sizeof(process_types::CrashpadInfo<Traits>),
-                                   crashpad_info)) {
-    LOG(WARNING) << "could not read crashpad info " << module_name_;
+  if (!crashpad_info_subrange_reader.ReadMemory(
+          crashpad_info_address,
+          sizeof(process_types::CrashpadInfo<Traits>),
+          crashpad_info)) {
+    LOG(WARNING) << "could not read crashpad info from "
+                 << module_subrange_reader_.name();
     return false;
   }
 
   if (crashpad_info->signature != CrashpadInfo::kSignature ||
       crashpad_info->version < 1) {
-    LOG(WARNING) << "unexpected crashpad info data " << module_name_;
+    LOG(WARNING) << "unexpected crashpad info data in "
+                 << module_subrange_reader_.name();
     return false;
   }
 
@@ -132,46 +116,23 @@
 bool PEImageReader::DebugDirectoryInformation(UUID* uuid,
                                               DWORD* age,
                                               std::string* pdbname) const {
-  if (process_reader_->Is64Bit()) {
-    return ReadDebugDirectoryInformation<IMAGE_NT_HEADERS64>(
-        uuid, age, pdbname);
-  } else {
-    return ReadDebugDirectoryInformation<IMAGE_NT_HEADERS32>(
-        uuid, age, pdbname);
-  }
-}
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
-template <class NtHeadersType>
-bool PEImageReader::ReadDebugDirectoryInformation(UUID* uuid,
-                                                  DWORD* age,
-                                                  std::string* pdbname) const {
-  NtHeadersType nt_headers;
-  if (!ReadNtHeaders(&nt_headers, nullptr))
+  IMAGE_DATA_DIRECTORY data_directory;
+  if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG, &data_directory))
     return false;
 
-  if (nt_headers.FileHeader.SizeOfOptionalHeader <
-          offsetof(decltype(nt_headers.OptionalHeader),
-                   DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]) +
-              sizeof(nt_headers.OptionalHeader
-                         .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]) ||
-      nt_headers.OptionalHeader.NumberOfRvaAndSizes <=
-          IMAGE_DIRECTORY_ENTRY_DEBUG) {
-    return false;
-  }
-
-  const IMAGE_DATA_DIRECTORY& data_directory =
-      nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
-  if (data_directory.VirtualAddress == 0 || data_directory.Size == 0)
-    return false;
   IMAGE_DEBUG_DIRECTORY debug_directory;
   if (data_directory.Size % sizeof(debug_directory) != 0)
     return false;
   for (size_t offset = 0; offset < data_directory.Size;
        offset += sizeof(debug_directory)) {
-    if (!CheckedReadMemory(Address() + data_directory.VirtualAddress + offset,
-                           sizeof(debug_directory),
-                           &debug_directory)) {
-      LOG(WARNING) << "could not read data directory";
+    if (!module_subrange_reader_.ReadMemory(
+            Address() + data_directory.VirtualAddress + offset,
+            sizeof(debug_directory),
+            &debug_directory)) {
+      LOG(WARNING) << "could not read data directory from "
+                   << module_subrange_reader_.name();
       return false;
     }
 
@@ -180,21 +141,25 @@
 
     if (debug_directory.AddressOfRawData) {
       if (debug_directory.SizeOfData < sizeof(CodeViewRecordPDB70)) {
-        LOG(WARNING) << "CodeView debug entry of unexpected size";
+        LOG(WARNING) << "CodeView debug entry of unexpected size in "
+                     << module_subrange_reader_.name();
         continue;
       }
 
       scoped_ptr<char[]> data(new char[debug_directory.SizeOfData]);
-      if (!CheckedReadMemory(Address() + debug_directory.AddressOfRawData,
-                             debug_directory.SizeOfData,
-                             data.get())) {
-        LOG(WARNING) << "could not read debug directory";
+      if (!module_subrange_reader_.ReadMemory(
+              Address() + debug_directory.AddressOfRawData,
+              debug_directory.SizeOfData,
+              data.get())) {
+        LOG(WARNING) << "could not read debug directory from "
+                     << module_subrange_reader_.name();
         return false;
       }
 
       if (*reinterpret_cast<DWORD*>(data.get()) !=
           CodeViewRecordPDB70::kSignature) {
-        LOG(WARNING) << "encountered non-7.0 CodeView debug record";
+        LOG(WARNING) << "encountered non-7.0 CodeView debug record in "
+                     << module_subrange_reader_.name();
         continue;
       }
 
@@ -218,29 +183,120 @@
   return false;
 }
 
+bool PEImageReader::VSFixedFileInfo(
+    VS_FIXEDFILEINFO* vs_fixed_file_info) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  IMAGE_DATA_DIRECTORY data_directory;
+  if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE,
+                               &data_directory)) {
+    return false;
+  }
+
+  PEImageResourceReader resource_reader;
+  if (!resource_reader.Initialize(module_subrange_reader_, data_directory)) {
+    return false;
+  }
+
+  WinVMAddress address;
+  WinVMSize size;
+  if (!resource_reader.FindResourceByID(
+          reinterpret_cast<uint16_t>(VS_FILE_INFO),  // RT_VERSION
+          VS_VERSION_INFO,
+          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+          &address,
+          &size,
+          nullptr)) {
+    return false;
+  }
+
+  // This structure is not declared anywhere in the SDK, but is documented at
+  // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001.aspx.
+  struct VS_VERSIONINFO {
+    WORD wLength;
+    WORD wValueLength;
+    WORD wType;
+
+    // The structure documentation on MSDN doesn’t show the [16], but it does
+    // say that it’s supposed to be L"VS_VERSION_INFO", which is is in fact a
+    // 16-character string (including its NUL terminator).
+    WCHAR szKey[16];
+
+    WORD Padding1;
+    VS_FIXEDFILEINFO Value;
+
+    // Don’t include Children or the Padding2 that precedes it, because they may
+    // not be present.
+    // WORD Padding2;
+    // WORD Children;
+  };
+  VS_VERSIONINFO version_info;
+
+  if (size < sizeof(version_info)) {
+    LOG(WARNING) << "version info size " << size
+                 << " too small for structure of size " << sizeof(version_info)
+                 << " in " << module_subrange_reader_.name();
+    return false;
+  }
+
+  if (!module_subrange_reader_.ReadMemory(
+          address, sizeof(version_info), &version_info)) {
+    LOG(WARNING) << "could not read version info from "
+                 << module_subrange_reader_.name();
+    return false;
+  }
+
+  if (version_info.wLength < sizeof(version_info) ||
+      version_info.wValueLength != sizeof(version_info.Value) ||
+      version_info.wType != 0 ||
+      wcsncmp(version_info.szKey,
+              L"VS_VERSION_INFO",
+              arraysize(version_info.szKey)) != 0) {
+    LOG(WARNING) << "unexpected VS_VERSIONINFO in "
+                 << module_subrange_reader_.name();
+    return false;
+  }
+
+  if (version_info.Value.dwSignature != VS_FFI_SIGNATURE ||
+      version_info.Value.dwStrucVersion != VS_FFI_STRUCVERSION) {
+    LOG(WARNING) << "unexpected VS_FIXEDFILEINFO in "
+                 << module_subrange_reader_.name();
+    return false;
+  }
+
+  *vs_fixed_file_info = version_info.Value;
+  vs_fixed_file_info->dwFileFlags &= vs_fixed_file_info->dwFileFlagsMask;
+  return true;
+}
+
 template <class NtHeadersType>
 bool PEImageReader::ReadNtHeaders(NtHeadersType* nt_headers,
                                   WinVMAddress* nt_headers_address) const {
   IMAGE_DOS_HEADER dos_header;
-  if (!CheckedReadMemory(Address(), sizeof(IMAGE_DOS_HEADER), &dos_header)) {
-    LOG(WARNING) << "could not read dos header of " << module_name_;
+  if (!module_subrange_reader_.ReadMemory(
+          Address(), sizeof(IMAGE_DOS_HEADER), &dos_header)) {
+    LOG(WARNING) << "could not read dos header from "
+                 << module_subrange_reader_.name();
     return false;
   }
 
   if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) {
-    LOG(WARNING) << "invalid e_magic in dos header of " << module_name_;
+    LOG(WARNING) << "invalid e_magic in dos header of "
+                 << module_subrange_reader_.name();
     return false;
   }
 
   WinVMAddress local_nt_headers_address = Address() + dos_header.e_lfanew;
-  if (!CheckedReadMemory(
+  if (!module_subrange_reader_.ReadMemory(
           local_nt_headers_address, sizeof(NtHeadersType), nt_headers)) {
-    LOG(WARNING) << "could not read nt headers of " << module_name_;
+    LOG(WARNING) << "could not read nt headers from "
+                 << module_subrange_reader_.name();
     return false;
   }
 
   if (nt_headers->Signature != IMAGE_NT_SIGNATURE) {
-    LOG(WARNING) << "invalid signature in nt headers of " << module_name_;
+    LOG(WARNING) << "invalid signature in nt headers of "
+                 << module_subrange_reader_.name();
     return false;
   }
 
@@ -269,9 +325,10 @@
   for (DWORD i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i) {
     WinVMAddress section_address =
         first_section_address + sizeof(IMAGE_SECTION_HEADER) * i;
-    if (!CheckedReadMemory(
+    if (!module_subrange_reader_.ReadMemory(
             section_address, sizeof(IMAGE_SECTION_HEADER), section)) {
-      LOG(WARNING) << "could not read section " << i << " of " << module_name_;
+      LOG(WARNING) << "could not read section " << i << " from "
+                   << module_subrange_reader_.name();
       return false;
     }
     if (strncmp(reinterpret_cast<const char*>(section->Name),
@@ -284,20 +341,36 @@
   return false;
 }
 
-bool PEImageReader::CheckedReadMemory(WinVMAddress address,
-                                      WinVMSize size,
-                                      void* into) const {
-  CheckedWinAddressRange read_range(process_reader_->Is64Bit(), address, size);
-  if (!read_range.IsValid()) {
-    LOG(WARNING) << "invalid read range: " << RangeToString(read_range);
+bool PEImageReader::ImageDataDirectoryEntry(size_t index,
+                                            IMAGE_DATA_DIRECTORY* entry) const {
+  bool rv;
+  if (module_subrange_reader_.Is64Bit()) {
+    rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS64>(index, entry);
+  } else {
+    rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS32>(index, entry);
+  }
+
+  return rv && entry->VirtualAddress != 0 && entry->Size != 0;
+}
+
+template <class NtHeadersType>
+bool PEImageReader::ImageDataDirectoryEntryT(
+    size_t index,
+    IMAGE_DATA_DIRECTORY* entry) const {
+  NtHeadersType nt_headers;
+  if (!ReadNtHeaders(&nt_headers, nullptr)) {
     return false;
   }
-  if (!module_range_.ContainsRange(read_range)) {
-    LOG(WARNING) << "attempt to read outside of module " << module_name_
-                 << " at range: " << RangeToString(read_range);
+
+  if (nt_headers.FileHeader.SizeOfOptionalHeader <
+          offsetof(decltype(nt_headers.OptionalHeader), DataDirectory[index]) +
+              sizeof(nt_headers.OptionalHeader.DataDirectory[index]) ||
+      nt_headers.OptionalHeader.NumberOfRvaAndSizes <= index) {
     return false;
   }
-  return process_reader_->ReadMemory(address, size, into);
+
+  *entry = nt_headers.OptionalHeader.DataDirectory[index];
+  return true;
 }
 
 // Explicit instantiations with the only 2 valid template arguments to avoid
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h
index f6364d9..87e3a8f4 100644
--- a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h
@@ -20,10 +20,10 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "snapshot/win/process_subrange_reader.h"
 #include "util/misc/initialization_state_dcheck.h"
 #include "util/misc/uuid.h"
 #include "util/win/address_types.h"
-#include "util/win/checked_win_address_range.h"
 #include "util/win/process_structs.h"
 
 namespace crashpad {
@@ -51,6 +51,7 @@
 //! bitness of the remote process.
 //!
 //! \sa PEImageAnnotationsReader
+//! \sa PEImageResourceReader
 class PEImageReader {
  public:
   PEImageReader();
@@ -65,8 +66,8 @@
   //! \param[in] address The address, in the remote process' address space,
   //!     where the `IMAGE_DOS_HEADER` is located.
   //! \param[in] size The size of the image.
-  //! \param[in] name The module's name, a string to be used in logged messages.
-  //!     This string is for diagnostic purposes.
+  //! \param[in] module_name The module's name, a string to be used in logged
+  //!     messages. This string is for diagnostic purposes.
   //!
   //! \return `true` if the image was read successfully, `false` otherwise, with
   //!     an appropriate message logged.
@@ -78,12 +79,12 @@
   //! \brief Returns the image's load address.
   //!
   //! This is the value passed as \a address to Initialize().
-  WinVMAddress Address() const { return module_range_.Base(); }
+  WinVMAddress Address() const { return module_subrange_reader_.Base(); }
 
   //! \brief Returns the image's size.
   //!
   //! This is the value passed as \a size to Initialize().
-  WinVMSize Size() const { return module_range_.Size(); }
+  WinVMSize Size() const { return module_subrange_reader_.Size(); }
 
   //! \brief Obtains the module's CrashpadInfo structure.
   //!
@@ -100,25 +101,34 @@
   //! \param[out] age The age field for the pdb (the number of times it's been
   //!     relinked).
   //! \param[out] pdbname Name of the pdb file.
-  //! \return `true` on success, or `false` if the module has no debug directory
-  //!     entry.
-  bool DebugDirectoryInformation(UUID* uuid,
-                                 DWORD* age,
-                                 std::string* pdbname) const;
-
- private:
-  //! \brief Implementation helper for DebugDirectoryInformation() templated by
-  //!     `IMAGE_NT_HEADERS` type for different bitnesses.
   //!
   //! \return `true` on success, with the parameters set appropriately. `false`
   //!     on failure. This method may return `false` without logging anything in
   //!     the case of a module that does not contain relevant debugging
   //!     information but is otherwise properly structured.
-  template <class NtHeadersType>
-  bool ReadDebugDirectoryInformation(UUID* uuid,
-                                     DWORD* age,
-                                     std::string* pdbname) const;
+  bool DebugDirectoryInformation(UUID* uuid,
+                                 DWORD* age,
+                                 std::string* pdbname) const;
 
+  //! \brief Obtains the module’s `VS_FIXEDFILEINFO`, containing its version and
+  //!     type information.
+  //!
+  //! The data obtained from this method should be equivalent to what could be
+  //! obtained by calling GetModuleVersionAndType(). Avoiding that function
+  //! ensures that the data in the module loaded into the remote process will be
+  //! used as-is, without the risks associated with loading the module into the
+  //! reading process.
+  //!
+  //! \param[out] vs_fixed_file_info The VS_FIXEDFILEINFO on success.
+  //!     VS_FIXEDFILEINFO::dwFileFlags will have been masked with
+  //!     VS_FIXEDFILEINFO::dwFileFlagsMask already.
+  //!
+  //! \return `true` on success. `false` if the module does not contain this
+  //!     information, without logging any messages. `false` on failure, with
+  //!     a message logged.
+  bool VSFixedFileInfo(VS_FIXEDFILEINFO* vs_fixed_file_info) const;
+
+ private:
   //! \brief Reads the `IMAGE_NT_HEADERS` from the beginning of the image.
   //!
   //! \param[out] nt_headers The contents of the templated NtHeadersType
@@ -139,18 +149,25 @@
   bool GetSectionByName(const std::string& name,
                         IMAGE_SECTION_HEADER* section) const;
 
-  //! \brief Reads memory from target process, first checking whether the range
-  //!     requested falls inside module_range_.
+  //! \brief Finds the `IMAGE_DATA_DIRECTORY` in
+  //!     `IMAGE_OPTIONAL_HEADER::DataDirectory` at the specified \a index.
   //!
-  //! \return `true` on success, with \a into filled out, otherwise `false` and
-  //!     a message will be logged.
-  bool CheckedReadMemory(WinVMAddress address,
-                         WinVMSize size,
-                         void* into) const;
+  //! \param[in] index An `IMAGE_DIRECTORY_ENTRY_*` constant specifying the
+  //!     data to be returned.
+  //! \param[out] entry The `IMAGE_DATA_DIRECTORY` found within the module.
+  //!
+  //! \return `true` on success, with \a entry set appropriately. `false` if the
+  //!     module does not contain the specified information, without logging a
+  //!     message. `false` on failure, with a message logged.
+  bool ImageDataDirectoryEntry(size_t index, IMAGE_DATA_DIRECTORY* entry) const;
 
-  ProcessReaderWin* process_reader_;  // weak
-  CheckedWinAddressRange module_range_;
-  std::string module_name_;
+  //! \brief A templatized helper for ImageDataDirectoryEntry() to account for
+  //!     differences in \a NtHeadersType.
+  template <class NtHeadersType>
+  bool ImageDataDirectoryEntryT(size_t index,
+                                IMAGE_DATA_DIRECTORY* entry) const;
+
+  ProcessSubrangeReader module_subrange_reader_;
   InitializationStateDcheck initialized_;
 
   DISALLOW_COPY_AND_ASSIGN(PEImageReader);
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc
index 3928fee9..46795cfb 100644
--- a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc
@@ -17,9 +17,14 @@
 #define PSAPI_VERSION 1
 #include <psapi.h>
 
+#include "base/files/file_path.h"
+#include "base/strings/utf_string_conversions.h"
 #include "gtest/gtest.h"
 #include "snapshot/win/process_reader_win.h"
+#include "test/errors.h"
 #include "util/win/get_function.h"
+#include "util/win/module_version.h"
+#include "util/win/process_info.h"
 
 extern "C" IMAGE_DOS_HEADER __ImageBase;
 
@@ -28,9 +33,9 @@
 namespace {
 
 BOOL CrashpadGetModuleInformation(HANDLE process,
-                          HMODULE module,
-                          MODULEINFO* module_info,
-                          DWORD cb) {
+                                  HMODULE module,
+                                  MODULEINFO* module_info,
+                                  DWORD cb) {
   static const auto get_module_information =
       GET_FUNCTION_REQUIRED(L"psapi.dll", ::GetModuleInformation);
   return get_module_information(process, module, module_info, cb);
@@ -44,9 +49,10 @@
   HMODULE self = reinterpret_cast<HMODULE>(&__ImageBase);
   MODULEINFO module_info;
   ASSERT_TRUE(CrashpadGetModuleInformation(
-      GetCurrentProcess(), self, &module_info, sizeof(module_info)));
+      GetCurrentProcess(), self, &module_info, sizeof(module_info)))
+      << ErrorMessage("GetModuleInformation");
   EXPECT_EQ(self, module_info.lpBaseOfDll);
-  EXPECT_TRUE(pe_image_reader.Initialize(&process_reader,
+  ASSERT_TRUE(pe_image_reader.Initialize(&process_reader,
                                          reinterpret_cast<WinVMAddress>(self),
                                          module_info.SizeOfImage,
                                          "self"));
@@ -61,6 +67,107 @@
       pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix));
 }
 
+void TestVSFixedFileInfo(ProcessReaderWin* process_reader,
+                         const ProcessInfo::Module& module,
+                         bool known_dll) {
+  PEImageReader pe_image_reader;
+  ASSERT_TRUE(pe_image_reader.Initialize(process_reader,
+                                         module.dll_base,
+                                         module.size,
+                                         base::UTF16ToUTF8(module.name)));
+
+  VS_FIXEDFILEINFO observed;
+  const bool observed_rv = pe_image_reader.VSFixedFileInfo(&observed);
+  ASSERT_TRUE(observed_rv || !known_dll);
+
+  if (observed_rv) {
+    EXPECT_EQ(VS_FFI_SIGNATURE, observed.dwSignature);
+    EXPECT_EQ(VS_FFI_STRUCVERSION, observed.dwStrucVersion);
+    EXPECT_EQ(0, observed.dwFileFlags & ~observed.dwFileFlagsMask);
+    EXPECT_EQ(VOS_NT_WINDOWS32, observed.dwFileOS);
+    if (known_dll) {
+      EXPECT_EQ(VFT_DLL, observed.dwFileType);
+    } else {
+      EXPECT_TRUE(observed.dwFileType == VFT_APP ||
+                  observed.dwFileType == VFT_DLL);
+    }
+  }
+
+  base::FilePath module_path(module.name);
+
+  const DWORD version = GetVersion();
+  const int major_version = LOBYTE(LOWORD(version));
+  const int minor_version = HIBYTE(LOWORD(version));
+  if (major_version > 6 || (major_version == 6 && minor_version >= 2)) {
+    // Windows 8 or later.
+    //
+    // Use BaseName() to ensure that GetModuleVersionAndType() finds the
+    // already-loaded module with the specified name. Otherwise, dwFileVersionMS
+    // may not match. This appears to be related to the changes made in Windows
+    // 8.1 to GetVersion() and GetVersionEx() for non-manifested applications
+    module_path = module_path.BaseName();
+  }
+
+  VS_FIXEDFILEINFO expected;
+  const bool expected_rv = GetModuleVersionAndType(module_path, &expected);
+  ASSERT_TRUE(expected_rv || !known_dll);
+
+  EXPECT_EQ(expected_rv, observed_rv);
+
+  if (observed_rv && expected_rv) {
+    EXPECT_EQ(expected.dwSignature, observed.dwSignature);
+    EXPECT_EQ(expected.dwStrucVersion, observed.dwStrucVersion);
+    EXPECT_EQ(expected.dwFileVersionMS, observed.dwFileVersionMS);
+    EXPECT_EQ(expected.dwFileVersionLS, observed.dwFileVersionLS);
+    EXPECT_EQ(expected.dwProductVersionMS, observed.dwProductVersionMS);
+    EXPECT_EQ(expected.dwProductVersionLS, observed.dwProductVersionLS);
+    EXPECT_EQ(expected.dwFileFlagsMask, observed.dwFileFlagsMask);
+    EXPECT_EQ(expected.dwFileFlags, observed.dwFileFlags);
+    EXPECT_EQ(expected.dwFileOS, observed.dwFileOS);
+    EXPECT_EQ(expected.dwFileType, observed.dwFileType);
+    EXPECT_EQ(expected.dwFileSubtype, observed.dwFileSubtype);
+    EXPECT_EQ(expected.dwFileDateMS, observed.dwFileDateMS);
+    EXPECT_EQ(expected.dwFileDateLS, observed.dwFileDateLS);
+  }
+}
+
+TEST(PEImageReader, VSFixedFileInfo_OneModule) {
+  ProcessReaderWin process_reader;
+  ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(),
+                                        ProcessSuspensionState::kRunning));
+
+  const wchar_t kModuleName[] = L"kernel32.dll";
+  const HMODULE module_handle = GetModuleHandle(kModuleName);
+  ASSERT_TRUE(module_handle) << ErrorMessage("GetModuleHandle");
+
+  MODULEINFO module_info;
+  ASSERT_TRUE(CrashpadGetModuleInformation(
+      GetCurrentProcess(), module_handle, &module_info, sizeof(module_info)))
+      << ErrorMessage("GetModuleInformation");
+  EXPECT_EQ(module_handle, module_info.lpBaseOfDll);
+
+  ProcessInfo::Module module;
+  module.name = kModuleName;
+  module.dll_base = reinterpret_cast<WinVMAddress>(module_info.lpBaseOfDll);
+  module.size = module_info.SizeOfImage;
+
+  TestVSFixedFileInfo(&process_reader, module, true);
+}
+
+TEST(PEImageReader, VSFixedFileInfo_AllModules) {
+  ProcessReaderWin process_reader;
+  ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(),
+                                        ProcessSuspensionState::kRunning));
+
+  const std::vector<ProcessInfo::Module>& modules = process_reader.Modules();
+  EXPECT_GT(modules.size(), 2u);
+
+  for (const auto& module : modules) {
+    SCOPED_TRACE(base::UTF16ToUTF8(module.name));
+    TestVSFixedFileInfo(&process_reader, module, false);
+  }
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_resource_reader.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_resource_reader.cc
new file mode 100644
index 0000000..3a754a9
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_resource_reader.cc
@@ -0,0 +1,279 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "snapshot/win/pe_image_resource_reader.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace {
+
+void AddLanguageAndNeutralSublanguage(std::vector<uint16_t>* languages,
+                                      uint16_t language) {
+  languages->push_back(language);
+  if (SUBLANGID(language) != SUBLANG_NEUTRAL) {
+    languages->push_back(MAKELANGID(PRIMARYLANGID(language), SUBLANG_NEUTRAL));
+  }
+}
+
+}  // namespace
+
+namespace crashpad {
+
+PEImageResourceReader::PEImageResourceReader()
+    : resources_subrange_reader_(),
+      module_base_(0),
+      initialized_() {
+}
+
+PEImageResourceReader::~PEImageResourceReader() {}
+
+bool PEImageResourceReader::Initialize(
+    const ProcessSubrangeReader& module_subrange_reader,
+    const IMAGE_DATA_DIRECTORY& resources_directory_entry) {
+  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+
+  module_base_ = module_subrange_reader.Base();
+
+  if (!resources_subrange_reader_.InitializeSubrange(
+          module_subrange_reader,
+          module_base_ + resources_directory_entry.VirtualAddress,
+          resources_directory_entry.Size,
+          "resources")) {
+    return false;
+  }
+
+  INITIALIZATION_STATE_SET_VALID(initialized_);
+  return true;
+}
+
+bool PEImageResourceReader::FindResourceByID(uint16_t type,
+                                             uint16_t name,
+                                             uint16_t language,
+                                             WinVMAddress* address,
+                                             WinVMSize* size,
+                                             uint32_t* code_page) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  // The root resource directory is at the beginning of the resources area
+  // within the module.
+  const uint32_t name_directory_offset =
+      GetEntryFromResourceDirectoryByID(0, type, true);
+  if (!name_directory_offset) {
+    return false;
+  }
+
+  const uint32_t language_directory_offset =
+      GetEntryFromResourceDirectoryByID(name_directory_offset, name, true);
+  if (!language_directory_offset) {
+    return false;
+  }
+
+  // The definition of IMAGE_RESOURCE_DIRECTORY_ENTRY in <winnt.h> has a comment
+  // saying that its offsets are relative to “the resource directory of the data
+  // associated with this directory entry”. That could be interpreted to mean
+  // that language_directory_offset is relative to name_directory_offset, since
+  // the language directory entry is found within the name directory. This is
+  // not correct. All resource offsets are relative to the resources area within
+  // the module.
+  const uint32_t data_offset = GetEntryFromResourceDirectoryByLanguage(
+      language_directory_offset, language);
+  if (!data_offset) {
+    return false;
+  }
+
+  IMAGE_RESOURCE_DATA_ENTRY data_entry;
+  if (!resources_subrange_reader_.ReadMemory(
+          resources_subrange_reader_.Base() + data_offset,
+          sizeof(data_entry),
+          &data_entry)) {
+    LOG(WARNING) << "could not read resource data entry from "
+                 << resources_subrange_reader_.name();
+    return false;
+  }
+
+  // The definition of IMAGE_RESOURCE_DATA_ENTRY in <winnt.h> has a comment
+  // saying that OffsetToData is relative to the beginning of the resource data.
+  // This is not correct. It’s module-relative.
+  *address = module_base_ + data_entry.OffsetToData;
+  *size = data_entry.Size;
+  if (code_page) {
+    *code_page = data_entry.CodePage;
+  }
+
+  return true;
+}
+
+uint32_t PEImageResourceReader::GetEntryFromResourceDirectoryByID(
+    uint32_t language_directory_offset,
+    uint16_t id,
+    bool want_subdirectory) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY> entries_by_id;
+  if (!ReadResourceDirectory(
+          language_directory_offset, nullptr, nullptr, &entries_by_id)) {
+    return 0;
+  }
+
+  const auto entry_it =
+      std::find_if(entries_by_id.begin(),
+                   entries_by_id.end(),
+                   [id](const IMAGE_RESOURCE_DIRECTORY_ENTRY& entry) {
+                     return !entry.NameIsString && entry.Id == id;
+                   });
+  if (entry_it != entries_by_id.end()) {
+    if ((entry_it->DataIsDirectory != 0) != want_subdirectory) {
+      LOG(WARNING) << "expected " << (want_subdirectory ? "" : "non-")
+                   << "directory for entry id " << id << " in "
+                   << resources_subrange_reader_.name();
+      return 0;
+    }
+
+    return entry_it->DataIsDirectory ? entry_it->OffsetToDirectory
+                                     : entry_it->OffsetToData;
+  }
+
+  return 0;
+}
+
+uint32_t PEImageResourceReader::GetEntryFromResourceDirectoryByLanguage(
+    uint32_t resource_directory_offset,
+    uint16_t language) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY> entries_by_language;
+  if (!ReadResourceDirectory(
+          resource_directory_offset, nullptr, nullptr, &entries_by_language)) {
+    return 0;
+  }
+
+  if (entries_by_language.empty()) {
+    return 0;
+  }
+
+  // https://msdn.microsoft.com/en-us/library/cc194810.aspx
+  //
+  // TODO(mark): It seems like FindResourceEx() might do something more complex.
+  // It would be best to mimic its behavior.
+  std::vector<uint16_t> try_languages;
+  if (PRIMARYLANGID(language) != LANG_NEUTRAL) {
+    AddLanguageAndNeutralSublanguage(&try_languages, language);
+  } else {
+    if (SUBLANGID(language) != SUBLANG_SYS_DEFAULT) {
+      AddLanguageAndNeutralSublanguage(&try_languages,
+                                       LANGIDFROMLCID(GetThreadLocale()));
+      AddLanguageAndNeutralSublanguage(&try_languages,
+                                       LANGIDFROMLCID(GetUserDefaultLCID()));
+    }
+    if (SUBLANGID(language) != SUBLANG_DEFAULT) {
+      AddLanguageAndNeutralSublanguage(&try_languages,
+                                       LANGIDFROMLCID(GetSystemDefaultLCID()));
+    }
+  }
+
+  try_languages.push_back(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
+  try_languages.push_back(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT));
+
+  for (const auto try_language : try_languages) {
+    const auto entry_it = std::find_if(
+        entries_by_language.begin(),
+        entries_by_language.end(),
+        [try_language](const IMAGE_RESOURCE_DIRECTORY_ENTRY& entry) {
+          return !entry.NameIsString && entry.Id == try_language;
+        });
+    if (entry_it != entries_by_language.end()) {
+      if (entry_it->DataIsDirectory) {
+        LOG(WARNING) << "expected non-directory for entry language "
+                     << try_language << " in "
+                     << resources_subrange_reader_.name();
+        return 0;
+      }
+
+      return entry_it->OffsetToData;
+    }
+  }
+
+  // Fall back to the first entry in the list.
+  const auto& entry = entries_by_language.front();
+  if (entry.DataIsDirectory) {
+    LOG(WARNING) << "expected non-directory for entry in "
+                 << resources_subrange_reader_.name();
+    return 0;
+  }
+
+  return entry.OffsetToData;
+}
+
+bool PEImageResourceReader::ReadResourceDirectory(
+    uint32_t resource_directory_offset,
+    IMAGE_RESOURCE_DIRECTORY* resource_directory,
+    std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY>* named_entries,
+    std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY>* id_entries) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  // resource_directory is optional, but it’s still needed locally even if the
+  // caller isn’t interested in it.
+  scoped_ptr<IMAGE_RESOURCE_DIRECTORY> local_resource_directory;
+  if (!resource_directory) {
+    local_resource_directory.reset(new IMAGE_RESOURCE_DIRECTORY);
+    resource_directory = local_resource_directory.get();
+  }
+
+  const WinVMAddress address =
+      resources_subrange_reader_.Base() + resource_directory_offset;
+
+  if (!resources_subrange_reader_.ReadMemory(
+          address, sizeof(*resource_directory), resource_directory)) {
+    LOG(WARNING) << "could not read resource directory from "
+                 << resources_subrange_reader_.name();
+    return false;
+  }
+
+  if (named_entries) {
+    named_entries->clear();
+    named_entries->resize(resource_directory->NumberOfNamedEntries);
+    if (!named_entries->empty() &&
+        !resources_subrange_reader_.ReadMemory(
+            address + sizeof(*resource_directory),
+            named_entries->size() * sizeof((*named_entries)[0]),
+            &(*named_entries)[0])) {
+      LOG(WARNING) << "could not read resource directory named entries from "
+                   << resources_subrange_reader_.name();
+      return false;
+    }
+  }
+
+  if (id_entries) {
+    id_entries->clear();
+    id_entries->resize(resource_directory->NumberOfIdEntries);
+    if (!id_entries->empty() &&
+        !resources_subrange_reader_.ReadMemory(
+            address + sizeof(*resource_directory) +
+                resource_directory->NumberOfNamedEntries *
+                    sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY),
+            id_entries->size() * sizeof((*id_entries)[0]),
+            &(*id_entries)[0])) {
+      LOG(WARNING) << "could not read resource directory ID entries from "
+                   << resources_subrange_reader_.name();
+      return false;
+    }
+  }
+
+  return true;
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_resource_reader.h b/third_party/crashpad/crashpad/snapshot/win/pe_image_resource_reader.h
new file mode 100644
index 0000000..59a6d95
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_resource_reader.h
@@ -0,0 +1,179 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_SNAPSHOT_WIN_PE_IMAGE_RESOURCE_READER_H_
+#define CRASHPAD_SNAPSHOT_WIN_PE_IMAGE_RESOURCE_READER_H_
+
+#include <stdint.h>
+#include <windows.h>
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "snapshot/win/process_subrange_reader.h"
+#include "util/misc/initialization_state_dcheck.h"
+#include "util/win/address_types.h"
+
+namespace crashpad {
+
+//! \brief A reader for resources stored in PE images mapped into another
+//!     process.
+//!
+//! \sa PEImageReader
+class PEImageResourceReader {
+ public:
+  PEImageResourceReader();
+  ~PEImageResourceReader();
+
+  //! \brief Initializes the resource reader.
+  //!
+  //! \param[in] module_subrange_reader The reader for the module.
+  //! \param[in] resources_directory_entry The module’s `IMAGE_DATA_DIRECTORY`
+  //!     for its resources area. This is taken from the module’s
+  //!     `IMAGE_OPTIONAL_HEADER::DataDirectory` at index
+  //!     `IMAGE_DIRECTORY_ENTRY_RESOURCE`.
+  //!
+  //! \return `true` on success, `false` on failure with a message logged.
+  bool Initialize(const ProcessSubrangeReader& module_subrange_reader,
+                  const IMAGE_DATA_DIRECTORY& resources_directory_entry);
+
+  //! \brief Locates a resource in a module by its ID.
+  //!
+  //! This method is similar to `FindResourceEx()`, but it operates on modules
+  //! loaded in a remote process’ address space. It is not necessary to
+  //! `LoadLibrary()` a module into a process in order to use this method.
+  //!
+  //! No support is provided at present for locating resources by \a type or \a
+  //! name using strings as opposed to integer identifiers.
+  //!
+  //! Languages are scanned in the order determined by
+  //! GetEntryFromResourceDirectoryByLanguage().
+  //!
+  //! \param[in] type The integer identifier of the resource type, as in the
+  //!     `lpType` parameter of `FindResourceEx()`.
+  //! \param[in] name The integer identifier of the resource, as in the `lpName`
+  //!     parameter of `FindResourceEx()`.
+  //! \param[in] language The language of the resource, as in the `wLanguage`
+  //!     parameter of `FindResourceEx()`.
+  //! \param[out] address The address, in the remote process’ address space, of
+  //!     the resource data.
+  //! \param[out] size The size of the resource data.
+  //! \param[out] code_page The code page used to encode textual resource data.
+  //!     This parameter is optional.
+  //!
+  //! \return `true` on success, with the out parameters set appropriately.
+  //!     `false` if the resource was not found, without logging any messages.
+  //!     `false` on failure, with a message logged.
+  bool FindResourceByID(uint16_t type,
+                        uint16_t name,
+                        uint16_t language,
+                        WinVMAddress* address,
+                        WinVMSize* size,
+                        uint32_t* code_page) const;
+
+ private:
+  //! \brief Locates a resource directory entry within a resource directory by
+  //!     integer ID.
+  //!
+  //! \param[in] resource_directory_offset The offset, in the module’s resources
+  //!     area, of the resource directory to search.
+  //! \param[in] id The integer identifier of the resource to search for.
+  //! \param[in] want_subdirectory `true` if the resource directory entry is
+  //!     expected to be a resource directory itself, `false` otherwise.
+  //!
+  //! \return The offset, in the module’s resources area, of the entry that was
+  //!     found. On failure, `0`. `0` is technically a valid offset, but it
+  //!     corresponds to the root resource directory, which should never be the
+  //!     offset of another resource directory entry. If \a id was not found,
+  //!     `0` will be returned without logging anything. For other failures, a
+  //!     message will be logged.
+  uint32_t GetEntryFromResourceDirectoryByID(uint32_t resource_directory_offset,
+                                             uint16_t id,
+                                             bool want_subdirectory) const;
+
+  //! \brief Locates a resource directory entry within a resource directory by
+  //!     language.
+  //!
+  //! This method is similar to GetEntryFromResourceDirectoryByID() with \a
+  //! want_subdirectory set to `false`. Attempts are made to locate the resource
+  //! by using these languages:
+  //! <ul>
+  //!     <li>If \a language is `LANG_NEUTRAL`:</li>
+  //!     <ul>
+  //!         <li>Unless `SUBLANG_SYS_DEFAULT` is specified, the language of the
+  //!             thread’s locale, with its normal sublanguage and with
+  //!             `SUBLANG_NEUTRAL`.</li>
+  //!         <li>Unless `SUBLANG_SYS_DEFAULT` is specified, the language of the
+  //!             user’s default locale, with its normal sublanguage and with
+  //!             `SUBLANG_NEUTRAL`.</li>
+  //!         <li>Unless `SUBLANG_DEFAULT` is specified, the language of the
+  //!             system’s default locale, with its normal sublanguage and with
+  //!             `SUBLANG_NEUTRAL`.</li>
+  //!     </ul>
+  //!     <li>If \a language is not `LANG_NEUTRAL`:</li>
+  //!     <ul>
+  //!         <li>\a language</li>
+  //!         <li>\a language, with `SUBLANG_NEUTRAL`</li>
+  //!     </ul>
+  //!     <li>`LANG_NEUTRAL` with `SUBLANG_NEUTRAL`</li>
+  //!     <li>`LANG_ENGLISH` with `SUBLANG_DEFAULT`</li>
+  //!     <li>If none of the above match, the first language found</li>
+  //! </ul>
+  //!
+  //! If only a specific language is desired without any fallbacks, call
+  //! GetEntryFromResourceDirectoryByID() with the language directory’s offset
+  //! instead, passing the desired language in the \a id parameter, and `false`
+  //! for \a want_subdirectory.
+  //!
+  //! \param[in] language_directory_offset The offset, in the module’s resources
+  //!     area, of the resource directory to search.
+  //! \param[in] language The language of the resource to search for.
+  //!
+  //! \return The return value is as in GetEntryFromResourceDirectoryByID().
+  uint32_t GetEntryFromResourceDirectoryByLanguage(
+      uint32_t language_directory_offset,
+      uint16_t language) const;
+
+  //! \brief Reads a resource directory.
+  //!
+  //! \param[in] resource_directory_offset The offset, in the module’s resources
+  //!     area, of the resource directory to read.
+  //! \param[out] resource_directory The `IMAGE_RESOURCE_DIRECTORY` structure.
+  //!     This parameter is optional.
+  //! \param[out] named_entries A vector of \a
+  //!     resource_directory->NumberOfNamedEntries
+  //!     `IMAGE_RESOURCE_DIRECTORY_ENTRY` items that follow the resource
+  //!     directory. This parameter is optional.
+  //! \param[out] id_entries A vector of \a
+  //!     resource_directory->NumberOfIdEntries `IMAGE_RESOURCE_DIRECTORY_ENTRY`
+  //!     items that follow the named entries. This parameter is optional.
+  //!
+  //! \return `true` on success, with the out parameters set appropriately.
+  //!     `false` on failure with a message logged.
+  bool ReadResourceDirectory(
+      uint32_t resource_directory_offset,
+      IMAGE_RESOURCE_DIRECTORY* resource_directory,
+      std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY>* named_entries,
+      std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY>* id_entries) const;
+
+  ProcessSubrangeReader resources_subrange_reader_;
+  WinVMAddress module_base_;
+  InitializationStateDcheck initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(PEImageResourceReader);
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_SNAPSHOT_WIN_PE_IMAGE_RESOURCE_READER_H_
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_subrange_reader.cc b/third_party/crashpad/crashpad/snapshot/win/process_subrange_reader.cc
new file mode 100644
index 0000000..996fbdf
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/win/process_subrange_reader.cc
@@ -0,0 +1,104 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "snapshot/win/process_subrange_reader.h"
+
+#include "base/logging.h"
+#include "snapshot/win/process_reader_win.h"
+
+namespace crashpad {
+
+ProcessSubrangeReader::ProcessSubrangeReader()
+    : name_(),
+      range_(),
+      process_reader_(nullptr) {
+}
+
+ProcessSubrangeReader::~ProcessSubrangeReader() {
+}
+
+bool ProcessSubrangeReader::Initialize(ProcessReaderWin* process_reader,
+                                       WinVMAddress base,
+                                       WinVMSize size,
+                                       const std::string& name) {
+  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+
+  if (!InitializeInternal(process_reader, base, size, name)) {
+    return false;
+  }
+
+  INITIALIZATION_STATE_SET_VALID(initialized_);
+  return true;
+}
+
+bool ProcessSubrangeReader::InitializeSubrange(
+    const ProcessSubrangeReader& that,
+    WinVMAddress base,
+    WinVMSize size,
+    const std::string& sub_name) {
+  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+  INITIALIZATION_STATE_DCHECK_VALID(that.initialized_);
+
+  if (!InitializeInternal(
+          that.process_reader_, base, size, that.name_ + " " + sub_name)) {
+    return false;
+  }
+
+  if (!that.range_.ContainsRange(range_)) {
+    LOG(WARNING) << "range " << range_.AsString() << " outside of  range "
+                 << that.range_.AsString() << " for " << name_;
+    return false;
+  }
+
+  INITIALIZATION_STATE_SET_VALID(initialized_);
+  return true;
+}
+
+bool ProcessSubrangeReader::ReadMemory(WinVMAddress address,
+                                       WinVMSize size,
+                                       void* into) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  CheckedWinAddressRange read_range(process_reader_->Is64Bit(), address, size);
+  if (!read_range.IsValid()) {
+    LOG(WARNING) << "invalid read range " << read_range.AsString();
+    return false;
+  }
+
+  if (!range_.ContainsRange(read_range)) {
+    LOG(WARNING) << "attempt to read outside of " << name_ << " range "
+                 << range_.AsString() << " at range " << read_range.AsString();
+    return false;
+  }
+
+  return process_reader_->ReadMemory(address, size, into);
+}
+
+bool ProcessSubrangeReader::InitializeInternal(ProcessReaderWin* process_reader,
+                                               WinVMAddress base,
+                                               WinVMSize size,
+                                               const std::string& name) {
+  range_.SetRange(process_reader->Is64Bit(), base, size);
+  if (!range_.IsValid()) {
+    LOG(WARNING) << "invalid range " << range_.AsString() << " for " << name;
+    return false;
+  }
+
+  name_ = name;
+  process_reader_ = process_reader;
+
+  return true;
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_subrange_reader.h b/third_party/crashpad/crashpad/snapshot/win/process_subrange_reader.h
new file mode 100644
index 0000000..e8da592c
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/win/process_subrange_reader.h
@@ -0,0 +1,114 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_SNAPSHOT_WIN_PROCESS_SUBRANGE_READER_WIN_H_
+#define CRASHPAD_SNAPSHOT_WIN_PROCESS_SUBRANGE_READER_WIN_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "util/misc/initialization_state_dcheck.h"
+#include "util/win/address_types.h"
+#include "util/win/checked_win_address_range.h"
+
+namespace crashpad {
+
+class ProcessReaderWin;
+
+//! \brief A wrapper for ProcessReaderWin that only allows a specific subrange
+//!     to be read from.
+//!
+//! This class is useful to restrict reads to a specific address range, such as
+//! the address range occupied by a loaded module, or a specific section within
+//! a module.
+class ProcessSubrangeReader {
+ public:
+  ProcessSubrangeReader();
+  ~ProcessSubrangeReader();
+
+  //! \brief Initializes the object.
+  //!
+  //! \param[in] process_reader A reader for a remote process.
+  //! \param[in] base The base address for the range that reads should be
+  //!     restricted to.
+  //! \param[in] size The size of the range that reads should be restricted to.
+  //! \param[in] name The range’s name, a string to be used in logged messages.
+  //!     This string is for diagnostic purposes.
+  //!
+  //! \return `true` on success, `false` on failure with a message logged. The
+  //!     other methods in this class must not be called unless this method or
+  //!     InitializeSubrange() has returned true.
+  bool Initialize(ProcessReaderWin* process_reader,
+                  WinVMAddress base,
+                  WinVMSize size,
+                  const std::string& name);
+
+  //! \brief Initializes the object to a subrange of an existing
+  //!     ProcessSubrangeReader.
+  //!
+  //! The subrange identified by \a base and \a size must be contained within
+  //! the subrange in \a that.
+  //!
+  //! \param[in] that The existing ProcessSubrangeReader to base the new object
+  //!     on.
+  //! \param[in] base The base address for the range that reads should be
+  //!     restricted to.
+  //! \param[in] size The size of the range that reads should be restricted to.
+  //! \param[in] sub_name A description of the subrange, which will be appended
+  //!     to the \a name in \a that and used in logged messages. This string is
+  //!     for diagnostic purposes.
+  //!
+  //! \return `true` on success, `false` on failure with a message logged. The
+  //!     other methods in this class must not be called unless this method or
+  //!     Initialize() has returned true.
+  bool InitializeSubrange(const ProcessSubrangeReader& that,
+                          WinVMAddress base,
+                          WinVMSize size,
+                          const std::string& sub_name);
+
+  bool Is64Bit() const { return range_.Is64Bit(); }
+  WinVMAddress Base() const { return range_.Base(); }
+  WinVMAddress Size() const { return range_.Size(); }
+  const std::string& name() const { return name_; }
+
+  //! \brief Reads memory from the remote process.
+  //!
+  //! The range specified by \a address and \a size must be contained within
+  //! the range that this object is permitted to read.
+  //!
+  //! \param[in] address The address to read from.
+  //! \param[in] size The size of data to read, in bytes.
+  //! \param[out] into The buffer to read data into.
+  //!
+  //! \return `true` on success, `false` on failure with a message logged.
+  bool ReadMemory(WinVMAddress address, WinVMSize size, void* into) const;
+
+ private:
+  // Common helper for Initialize() and InitializeSubrange().
+  bool InitializeInternal(ProcessReaderWin* process_reader,
+                          WinVMAddress base,
+                          WinVMSize size,
+                          const std::string& name);
+
+  std::string name_;
+  CheckedWinAddressRange range_;
+  ProcessReaderWin* process_reader_;  // weak
+  InitializationStateDcheck initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessSubrangeReader);
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_SNAPSHOT_WIN_PROCESS_SUBRANGE_READER_WIN_H_
diff --git a/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win.cc
index 88827a5..a62bf5a 100644
--- a/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win.cc
@@ -86,35 +86,37 @@
 
   process_reader_ = process_reader;
 
-  // We use both GetVersionEx and VerQueryValue. GetVersionEx is not trustworthy
-  // after Windows 8 (depending on the application manifest) so its data is used
-  // only to fill the os_server_ field, and the rest comes from the version
+  // We use both GetVersionEx() and GetModuleVersionAndType() (which uses
+  // VerQueryValue() internally). GetVersionEx() is not trustworthy after
+  // Windows 8 (depending on the application manifest) so its data is used only
+  // to fill the os_server_ field, and the rest comes from the version
   // information stamped on kernel32.dll.
   OSVERSIONINFOEX version_info = {sizeof(version_info)};
   if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info))) {
     PLOG(WARNING) << "GetVersionEx";
   } else {
-    const wchar_t kSystemDll[] = L"kernel32.dll";
-    VS_FIXEDFILEINFO ffi;
-    if (GetModuleVersionAndType(base::FilePath(kSystemDll), &ffi)) {
-      std::string flags_string = GetStringForFileFlags(ffi.dwFileFlags);
-      os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
-      std::string os_name = GetStringForFileOS(ffi.dwFileOS);
-      os_version_major_ = ffi.dwFileVersionMS >> 16;
-      os_version_minor_ = ffi.dwFileVersionMS & 0xffff;
-      os_version_bugfix_ = ffi.dwFileVersionLS >> 16;
-      os_version_build_ =
-          base::StringPrintf("%d", ffi.dwFileVersionLS & 0xffff);
-      os_version_full_ = base::StringPrintf(
-          "%s %d.%d.%d.%s%s",
-          os_name.c_str(),
-          os_version_major_,
-          os_version_minor_,
-          os_version_bugfix_,
-          os_version_build_.c_str(),
-          flags_string.empty() ? "" : (std::string(" (") + flags_string + ")")
-                                          .c_str());
-    }
+    os_server_ = version_info.wProductType != VER_NT_WORKSTATION;
+  }
+
+  const wchar_t kSystemDll[] = L"kernel32.dll";
+  VS_FIXEDFILEINFO ffi;
+  if (GetModuleVersionAndType(base::FilePath(kSystemDll), &ffi)) {
+    std::string flags_string = GetStringForFileFlags(ffi.dwFileFlags);
+    std::string os_name = GetStringForFileOS(ffi.dwFileOS);
+    os_version_major_ = ffi.dwFileVersionMS >> 16;
+    os_version_minor_ = ffi.dwFileVersionMS & 0xffff;
+    os_version_bugfix_ = ffi.dwFileVersionLS >> 16;
+    os_version_build_ =
+        base::StringPrintf("%d", ffi.dwFileVersionLS & 0xffff);
+    os_version_full_ = base::StringPrintf(
+        "%s %d.%d.%d.%s%s",
+        os_name.c_str(),
+        os_version_major_,
+        os_version_minor_,
+        os_version_bugfix_,
+        os_version_build_.c_str(),
+        flags_string.empty() ? "" : (std::string(" (") + flags_string + ")")
+                                        .c_str());
   }
 
   INITIALIZATION_STATE_SET_VALID(initialized_);
diff --git a/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc b/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc
index 641eeba..8c122c4 100644
--- a/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc
+++ b/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc
@@ -207,7 +207,7 @@
 }
 
 void MachMultiprocess::MultiprocessChild() {
-  ScopedForbidReturn forbid_return;;
+  ScopedForbidReturn forbid_return;
 
   // local_port is not valid in the forked child process.
   ignore_result(info_->local_port.release());
diff --git a/third_party/crashpad/crashpad/test/win/win_child_process.cc b/third_party/crashpad/crashpad/test/win/win_child_process.cc
index 1f11bc7..41cacfa 100644
--- a/third_party/crashpad/crashpad/test/win/win_child_process.cc
+++ b/third_party/crashpad/crashpad/test/win/win_child_process.cc
@@ -18,12 +18,12 @@
 #include <shellapi.h>
 
 #include <string>
+#include <utility>
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "gtest/gtest.h"
-#include "util/stdlib/move.h"
 #include "util/stdlib/string_number_conversion.h"
 #include "util/string/split_string.h"
 #include "util/win/handle.h"
@@ -126,8 +126,8 @@
   if (!write_inheritable && !UnsetHandleInheritance(temp_write.get()))
     return false;
 
-  *read_handle = crashpad::move(temp_read);
-  *write_handle = crashpad::move(temp_write);
+  *read_handle = std::move(temp_read);
+  *write_handle = std::move(temp_write);
 
   return true;
 }
@@ -213,7 +213,7 @@
     return scoped_ptr<Handles>();
   }
 
-  return crashpad::move(handles_for_parent);
+  return std::move(handles_for_parent);
 }
 
 FileHandle WinChildProcess::ReadPipeHandle() const {
diff --git a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
index 50666f2..a1ad52b 100644
--- a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
+++ b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
@@ -22,6 +22,7 @@
 #include <time.h>
 
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/basictypes.h"
@@ -36,7 +37,6 @@
 #include "tools/tool_support.h"
 #include "util/file/file_io.h"
 #include "util/file/file_reader.h"
-#include "util/stdlib/move.h"
 #include "util/misc/uuid.h"
 
 namespace crashpad {
@@ -553,7 +553,7 @@
         return EXIT_FAILURE;
       }
 
-      file_reader = crashpad::move(file_path_reader);
+      file_reader = std::move(file_path_reader);
     }
 
     CrashReportDatabase::NewReport* new_report;
diff --git a/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc b/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc
index 3fe4c44..a7b6e57 100644
--- a/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc
+++ b/third_party/crashpad/crashpad/util/mach/child_port_handshake.cc
@@ -23,6 +23,7 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <utility>
 
 #include "base/logging.h"
 #include "base/mac/mach_logging.h"
@@ -37,7 +38,6 @@
 #include "util/mach/mach_message.h"
 #include "util/mach/mach_message_server.h"
 #include "util/misc/implicit_cast.h"
-#include "util/stdlib/move.h"
 #include "util/misc/random_string.h"
 
 namespace crashpad {
@@ -353,30 +353,30 @@
 
 base::ScopedFD ChildPortHandshake::ClientReadFD() {
   DCHECK(client_read_fd_.is_valid());
-  return crashpad::move(client_read_fd_);
+  return std::move(client_read_fd_);
 }
 
 base::ScopedFD ChildPortHandshake::ServerWriteFD() {
   DCHECK(server_write_fd_.is_valid());
-  return crashpad::move(server_write_fd_);
+  return std::move(server_write_fd_);
 }
 
 mach_port_t ChildPortHandshake::RunServer(PortRightType port_right_type) {
   client_read_fd_.reset();
-  return RunServerForFD(crashpad::move(server_write_fd_), port_right_type);
+  return RunServerForFD(std::move(server_write_fd_), port_right_type);
 }
 
 bool ChildPortHandshake::RunClient(mach_port_t port,
                                    mach_msg_type_name_t right_type) {
   server_write_fd_.reset();
-  return RunClientForFD(crashpad::move(client_read_fd_), port, right_type);
+  return RunClientForFD(std::move(client_read_fd_), port, right_type);
 }
 
 // static
 mach_port_t ChildPortHandshake::RunServerForFD(base::ScopedFD server_write_fd,
                                                PortRightType port_right_type) {
   ChildPortHandshakeServer server;
-  return server.RunServer(crashpad::move(server_write_fd), port_right_type);
+  return server.RunServer(std::move(server_write_fd), port_right_type);
 }
 
 // static
diff --git a/third_party/crashpad/crashpad/util/mach/child_port_handshake.h b/third_party/crashpad/crashpad/util/mach/child_port_handshake.h
index f738cda..666f59b 100644
--- a/third_party/crashpad/crashpad/util/mach/child_port_handshake.h
+++ b/third_party/crashpad/crashpad/util/mach/child_port_handshake.h
@@ -138,7 +138,7 @@
 //!     // Obtain a receive right from the parent process.
 //!     base::mac::ScopedMachReceiveRight receive_right(
 //!         ChildPortHandshake::RunServerForFD(
-//!             crashpad::move(server_write_fd),
+//!             std::move(server_write_fd),
 //!             ChildPortHandshake::PortRightType::kReceiveRight));
 //!   }
 //! \endcode
diff --git a/third_party/crashpad/crashpad/util/mach/task_memory_test.cc b/third_party/crashpad/crashpad/util/mach/task_memory_test.cc
index 2247ed2f..963bc4d 100644
--- a/third_party/crashpad/crashpad/util/mach/task_memory_test.cc
+++ b/third_party/crashpad/crashpad/util/mach/task_memory_test.cc
@@ -445,7 +445,7 @@
     return false;
   }
 
-  ADD_FAILURE() << MachErrorMessage(kr, "vm_region_64");;
+  ADD_FAILURE() << MachErrorMessage(kr, "vm_region_64");
   return false;
 }
 
diff --git a/third_party/crashpad/crashpad/util/net/http_transport.cc b/third_party/crashpad/crashpad/util/net/http_transport.cc
index 07b0b34..8587d0a 100644
--- a/third_party/crashpad/crashpad/util/net/http_transport.cc
+++ b/third_party/crashpad/crashpad/util/net/http_transport.cc
@@ -14,7 +14,8 @@
 
 #include "util/net/http_transport.h"
 
-#include "util/stdlib/move.h"
+#include <utility>
+
 #include "util/net/http_body.h"
 
 namespace crashpad {
@@ -44,7 +45,7 @@
 }
 
 void HTTPTransport::SetBodyStream(scoped_ptr<HTTPBodyStream> stream) {
-  body_stream_ = crashpad::move(stream);
+  body_stream_ = std::move(stream);
 }
 
 void HTTPTransport::SetTimeout(double timeout) {
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_test.cc b/third_party/crashpad/crashpad/util/net/http_transport_test.cc
index b59b17fd..46e7a5f7 100644
--- a/third_party/crashpad/crashpad/util/net/http_transport_test.cc
+++ b/third_party/crashpad/crashpad/util/net/http_transport_test.cc
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <utility>
 #include <vector>
 
 #include "base/files/file_path.h"
@@ -31,7 +32,6 @@
 #include "test/multiprocess_exec.h"
 #include "test/paths.h"
 #include "util/file/file_io.h"
-#include "util/stdlib/move.h"
 #include "util/misc/random_string.h"
 #include "util/net/http_body.h"
 #include "util/net/http_headers.h"
@@ -52,7 +52,7 @@
                            RequestValidator request_validator)
       : MultiprocessExec(),
         headers_(headers),
-        body_stream_(crashpad::move(body_stream)),
+        body_stream_(std::move(body_stream)),
         response_code_(http_response_code),
         request_validator_(request_validator) {
     base::FilePath server_path = Paths::TestDataRoot().Append(
@@ -103,7 +103,7 @@
     for (const auto& pair : headers_) {
       transport->SetHeader(pair.first, pair.second);
     }
-    transport->SetBodyStream(crashpad::move(body_stream_));
+    transport->SetBodyStream(std::move(body_stream_));
 
     std::string response_body;
     bool success = transport->ExecuteSynchronously(&response_body);
@@ -271,8 +271,8 @@
   headers[kContentType] = kTextPlain;
   headers[kContentLength] = base::StringPrintf("%" PRIuS, strlen(kTextBody));
 
-  HTTPTransportTestFixture test(headers, crashpad::move(body_stream), 200,
-      &UnchunkedPlainText);
+  HTTPTransportTestFixture test(
+      headers, std::move(body_stream), 200, &UnchunkedPlainText);
   test.Run();
 }
 
@@ -292,7 +292,10 @@
     headers[kContentLength] =
         base::StringPrintf("%" PRIuS, request_string.size());
   }
-  HTTPTransportTestFixture test(headers, crashpad::move(body_stream), 200,
+  HTTPTransportTestFixture test(
+      headers,
+      std::move(body_stream),
+      200,
       [](HTTPTransportTestFixture* fixture, const std::string& request) {
         size_t body_start = request.rfind("\r\n");
         EXPECT_EQ(33 * 1024u + 2, request.size() - body_start);
diff --git a/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc b/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc
index dcbde23e..1d50696 100644
--- a/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc
+++ b/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc
@@ -14,6 +14,8 @@
 
 #include "util/numeric/checked_address_range.h"
 
+#include "base/strings/stringprintf.h"
+
 #if defined(OS_MACOSX)
 #include <mach/mach.h>
 #elif defined(OS_WIN)
@@ -109,6 +111,12 @@
                     : range_32_.ContainsRange(that.range_32_);
 }
 
+template <class ValueType, class SizeType>
+std::string CheckedAddressRangeGeneric<ValueType, SizeType>::AsString() const {
+  return base::StringPrintf(
+      "0x%llx + 0x%llx (%s)", Base(), Size(), Is64Bit() ? "64" : "32");
+}
+
 // Explicit instantiations for the cases we use.
 #if defined(OS_MACOSX)
 template class CheckedAddressRangeGeneric<mach_vm_address_t, mach_vm_size_t>;
diff --git a/third_party/crashpad/crashpad/util/numeric/checked_address_range.h b/third_party/crashpad/crashpad/util/numeric/checked_address_range.h
index e9514bb..65f85fb 100644
--- a/third_party/crashpad/crashpad/util/numeric/checked_address_range.h
+++ b/third_party/crashpad/crashpad/util/numeric/checked_address_range.h
@@ -17,6 +17,8 @@
 
 #include <stdint.h>
 
+#include <string>
+
 #include "build/build_config.h"
 #include "util/numeric/checked_range.h"
 
@@ -108,6 +110,12 @@
   //! CheckedAddressRangeGeneric objects involved.
   bool ContainsRange(const CheckedAddressRangeGeneric& that) const;
 
+  //! \brief Returns a string describing the address range.
+  //!
+  //! The string will be formatted as `"0x123 + 0x45 (64)"`, where the
+  //! individual components are the address, size, and bitness.
+  std::string AsString() const;
+
  private:
 #if defined(COMPILER_MSVC)
   // MSVC cannot handle a union containing CheckedRange (with constructor, etc.)
diff --git a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.cc b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.cc
new file mode 100644
index 0000000..363022c
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.cc
@@ -0,0 +1,78 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/stdlib/aligned_allocator.h"
+
+#include <algorithm>
+
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+#include <stdlib.h>
+#elif defined(OS_WIN)
+#include <malloc.h>
+#include <xutility>
+#endif  // OS_POSIX
+
+namespace {
+
+// Throws std::bad_alloc() by calling an internal function provided by the C++
+// library to do so. This works even if C++ exceptions are disabled, causing
+// program termination if uncaught.
+void ThrowBadAlloc() {
+#if defined(OS_POSIX)
+  // This works with both libc++ and libstdc++.
+  std::__throw_bad_alloc();
+#elif defined(OS_WIN)
+  std::_Xbad_alloc();
+#endif  // OS_POSIX
+}
+
+}  // namespace
+
+namespace crashpad {
+namespace internal {
+
+void* AlignedAllocate(size_t alignment, size_t size) {
+#if defined(OS_POSIX)
+  // posix_memalign() requires that alignment be at least sizeof(void*), so the
+  // power-of-2 check needs to happen before potentially changing the alignment.
+  if (alignment == 0 || alignment & (alignment - 1)) {
+    ThrowBadAlloc();
+  }
+
+  void* pointer;
+  if (posix_memalign(&pointer, std::max(alignment, sizeof(void*)), size) != 0) {
+    ThrowBadAlloc();
+  }
+#elif defined(OS_WIN)
+  void* pointer = _aligned_malloc(size, alignment);
+  if (pointer == nullptr) {
+    ThrowBadAlloc();
+  }
+#endif  // OS_POSIX
+
+  return pointer;
+}
+
+void AlignedFree(void* pointer) {
+#if defined(OS_POSIX)
+  free(pointer);
+#elif defined(OS_WIN)
+  _aligned_free(pointer);
+#endif  // OS_POSIX
+}
+
+}  // namespace internal
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.h b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.h
new file mode 100644
index 0000000..04d3dc4
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.h
@@ -0,0 +1,140 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_STDLIB_ALIGNED_ALLOCATOR_H_
+#define CRASHPAD_UTIL_STDLIB_ALIGNED_ALLOCATOR_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <memory>
+#include <new>
+#include <utility>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "build/build_config.h"
+#include "util/stdlib/cxx.h"
+
+#if defined(COMPILER_MSVC) && _MSC_VER < 1900
+#define CRASHPAD_NOEXCEPT _NOEXCEPT
+#else
+#define CRASHPAD_NOEXCEPT noexcept
+#endif
+
+namespace crashpad {
+namespace internal {
+
+//! \brief Allocates memory with the specified alignment constraint.
+//!
+//! This function wraps `posix_memalign()` or `_aligned_malloc()`. Memory
+//! allocated by this function must be released by AlignFree().
+void* AlignedAllocate(size_t alignment, size_t size);
+
+//! \brief Frees memory allocated by AlignedAllocate().
+//!
+//! This function wraps `free()` or `_aligned_free()`.
+void AlignedFree(void* pointer);
+
+}  // namespace internal
+
+//! \brief A standard allocator that aligns its allocations as requested,
+//!     suitable for use as an allocator in standard containers.
+//!
+//! This is similar to `std::allocator<T>`, with the addition of an alignment
+//! guarantee. \a Alignment must be a power of 2. If \a Alignment is not
+//! specified, the default alignment for type \a T is used.
+template <class T, size_t Alignment = ALIGNOF(T)>
+struct AlignedAllocator {
+ public:
+  using value_type = T;
+  using pointer = T*;
+  using const_pointer = const T*;
+  using reference = T&;
+  using const_reference = const T&;
+  using size_type = size_t;
+  using difference_type = ptrdiff_t;
+
+  template <class U>
+  struct rebind {
+    using other = AlignedAllocator<U, Alignment>;
+  };
+
+  AlignedAllocator() CRASHPAD_NOEXCEPT {}
+  AlignedAllocator(const AlignedAllocator& other) CRASHPAD_NOEXCEPT {}
+
+  template <typename U>
+  AlignedAllocator(const AlignedAllocator<U, Alignment>& other)
+      CRASHPAD_NOEXCEPT {}
+
+  ~AlignedAllocator() {}
+
+  pointer address(reference x) const CRASHPAD_NOEXCEPT { return &x; }
+  const_pointer address(const_reference x) const CRASHPAD_NOEXCEPT {
+    return &x;
+  }
+
+  pointer allocate(size_type n, std::allocator<void>::const_pointer hint = 0) {
+    return reinterpret_cast<pointer>(
+        internal::AlignedAllocate(Alignment, sizeof(value_type) * n));
+  }
+
+  void deallocate(pointer p, size_type n) { internal::AlignedFree(p); }
+
+  size_type max_size() const CRASHPAD_NOEXCEPT {
+    return std::numeric_limits<size_type>::max() / sizeof(value_type);
+  }
+
+#if CXX_LIBRARY_VERSION < 2011
+  void construct(pointer p, const T& val) {
+    new (reinterpret_cast<void*>(p)) T(val);
+  }
+#else
+  template <class U, class... Args>
+  void construct(U* p, Args&&... args) {
+    new (reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...);
+  }
+#endif
+
+  template <class U>
+  void destroy(U* p) {
+    p->~U();
+  }
+};
+
+template <class T1, class T2, size_t Alignment>
+bool operator==(const AlignedAllocator<T1, Alignment>& lhs,
+                const AlignedAllocator<T2, Alignment>& rhs) CRASHPAD_NOEXCEPT {
+  return true;
+}
+
+template <class T1, class T2, size_t Alignment>
+bool operator!=(const AlignedAllocator<T1, Alignment>& lhs,
+                const AlignedAllocator<T2, Alignment>& rhs) CRASHPAD_NOEXCEPT {
+  return false;
+}
+
+//! \brief A `std::vector` using AlignedAllocator.
+//!
+//! This is similar to `std::vector<T>`, with the addition of an alignment
+//! guarantee. \a Alignment must be a power of 2. If \a Alignment is not
+//! specified, the default alignment for type \a T is used.
+template <typename T, size_t Alignment = ALIGNOF(T)>
+using AlignedVector = std::vector<T, AlignedAllocator<T, Alignment>>;
+
+}  // namespace crashpad
+
+#undef CRASHPAD_NOEXCEPT
+
+#endif  // CRASHPAD_UTIL_STDLIB_ALIGNED_ALLOCATOR_H_
diff --git a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator_test.cc b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator_test.cc
new file mode 100644
index 0000000..fe3b9e6
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator_test.cc
@@ -0,0 +1,117 @@
+// Copyright 2015 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/stdlib/aligned_allocator.h"
+
+#include <stdint.h>
+
+#include "gtest/gtest.h"
+
+#if defined(OS_WIN)
+#include <crtdbg.h>
+#endif
+
+namespace crashpad {
+namespace test {
+namespace {
+
+bool IsAligned(void* pointer, size_t alignment) {
+  uintptr_t address = reinterpret_cast<uintptr_t>(pointer);
+  return (address & (alignment - 1)) == 0;
+}
+
+TEST(AlignedAllocator, AlignedVector) {
+  // Test a structure with natural alignment.
+  struct NaturalAlignedStruct {
+    int i;
+  };
+
+  AlignedVector<NaturalAlignedStruct> natural_aligned_vector;
+  natural_aligned_vector.push_back(NaturalAlignedStruct());
+  EXPECT_TRUE(
+      IsAligned(&natural_aligned_vector[0], ALIGNOF(NaturalAlignedStruct)));
+
+  natural_aligned_vector.resize(3);
+  EXPECT_TRUE(
+      IsAligned(&natural_aligned_vector[0], ALIGNOF(NaturalAlignedStruct)));
+  EXPECT_TRUE(
+      IsAligned(&natural_aligned_vector[1], ALIGNOF(NaturalAlignedStruct)));
+  EXPECT_TRUE(
+      IsAligned(&natural_aligned_vector[2], ALIGNOF(NaturalAlignedStruct)));
+
+  // Test a structure that declares its own alignment.
+  struct ALIGNAS(32) AlignedStruct {
+    int i;
+  };
+  ASSERT_EQ(32u, ALIGNOF(AlignedStruct));
+
+  AlignedVector<AlignedStruct> aligned_vector;
+  aligned_vector.push_back(AlignedStruct());
+  EXPECT_TRUE(IsAligned(&aligned_vector[0], ALIGNOF(AlignedStruct)));
+
+  aligned_vector.resize(3);
+  EXPECT_TRUE(IsAligned(&aligned_vector[0], ALIGNOF(AlignedStruct)));
+  EXPECT_TRUE(IsAligned(&aligned_vector[1], ALIGNOF(AlignedStruct)));
+  EXPECT_TRUE(IsAligned(&aligned_vector[2], ALIGNOF(AlignedStruct)));
+
+  // Try a custom alignment. Since the structure itself doesn’t specify an
+  // alignment constraint, only the base address will be aligned to the
+  // requested boundary.
+  AlignedVector<NaturalAlignedStruct, 64> custom_aligned_vector;
+  custom_aligned_vector.push_back(NaturalAlignedStruct());
+  EXPECT_TRUE(IsAligned(&custom_aligned_vector[0], 64));
+
+  // Try a structure with a pretty big alignment request.
+  struct ALIGNAS(1024) BigAlignedStruct {
+    int i;
+  };
+  ASSERT_EQ(1024u, ALIGNOF(BigAlignedStruct));
+
+  AlignedVector<BigAlignedStruct> big_aligned_vector;
+  big_aligned_vector.push_back(BigAlignedStruct());
+  EXPECT_TRUE(IsAligned(&big_aligned_vector[0], ALIGNOF(BigAlignedStruct)));
+
+  big_aligned_vector.resize(3);
+  EXPECT_TRUE(IsAligned(&big_aligned_vector[0], ALIGNOF(BigAlignedStruct)));
+  EXPECT_TRUE(IsAligned(&big_aligned_vector[1], ALIGNOF(BigAlignedStruct)));
+  EXPECT_TRUE(IsAligned(&big_aligned_vector[2], ALIGNOF(BigAlignedStruct)));
+}
+
+void BadAlignmentTest() {
+#if defined(OS_WIN)
+  // Suppress the assertion MessageBox() normally displayed by the CRT in debug
+  // mode.
+  int previous = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
+
+  // In release mode, _CrtSetReportMode() is #defined to ((int)0), so |previous|
+  // would appear unused.
+  ALLOW_UNUSED_LOCAL(previous);
+#endif
+
+  // Alignment constraints must be powers of 2. 7 is not valid.
+  AlignedVector<int, 7> bad_aligned_vector;
+  bad_aligned_vector.push_back(0);
+
+#if defined(OS_WIN)
+  _CrtSetReportMode(_CRT_ASSERT, previous);
+#endif
+}
+
+TEST(AlignedAllocatorDeathTest, BadAlignment) {
+  ASSERT_DEATH(BadAlignmentTest(), "");
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/stdlib/move.h b/third_party/crashpad/crashpad/util/stdlib/move.h
deleted file mode 100644
index b6f15bc..0000000
--- a/third_party/crashpad/crashpad/util/stdlib/move.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CRASHPAD_UTIL_STDLIB_MOVE_H_
-#define CRASHPAD_UTIL_STDLIB_MOVE_H_
-
-#include "util/stdlib/cxx.h"
-
-namespace crashpad {
-
-#if CXX_LIBRARY_VERSION >= 2011
-//! \brief A typedef for std::remove_reference until C++11 library support is
-//     always available.
-template <typename T>
-using remove_reference = std::remove_reference<T>;
-#else
-//! \brief A replacement for std::remove_reference until C++11 library support
-//     is always available.
-template <class T>
-struct remove_reference { using type = T; };
-template <class T>
-struct remove_reference<T&> { using type = T; };
-#endif  // CXX_LIBRARY_VERSION
-
-#if CXX_LIBRARY_VERSION >= 2011
-//! \brief A wrapper around std::move() until C++11 library support is
-//     always available.
-template <typename T>
-typename std::remove_reference<T>::type&& move(T&& t) {
-  return std::move(t);
-}
-#else
-//! \brief A replacement for std::move() until C++11 library support is
-//     always available.
-template <typename T>
-typename remove_reference<T>::type&& move(T&& t) {
-  return static_cast<typename remove_reference<T>::type&&>(t);
-}
-#endif  // CXX_LIBRARY_VERSION
-
-}  // namespace crashpad
-
-#endif  // CRASHPAD_UTIL_STDLIB_MOVE_H_
diff --git a/third_party/crashpad/crashpad/util/util.gyp b/third_party/crashpad/crashpad/util/util.gyp
index eb5f898..83f2c559 100644
--- a/third_party/crashpad/crashpad/util/util.gyp
+++ b/third_party/crashpad/crashpad/util/util.gyp
@@ -128,9 +128,10 @@
         'posix/process_info_mac.cc',
         'posix/symbolic_constants_posix.cc',
         'posix/symbolic_constants_posix.h',
+        'stdlib/aligned_allocator.cc',
+        'stdlib/aligned_allocator.h',
         'stdlib/cxx.h',
         'stdlib/map_insert.h',
-        'stdlib/move.h',
         'stdlib/objc.h',
         'stdlib/pointer_container.h',
         'stdlib/string_number_conversion.cc',
diff --git a/third_party/crashpad/crashpad/util/util_test.gyp b/third_party/crashpad/crashpad/util/util_test.gyp
index 2d94ea71..f5adc03 100644
--- a/third_party/crashpad/crashpad/util/util_test.gyp
+++ b/third_party/crashpad/crashpad/util/util_test.gyp
@@ -72,6 +72,7 @@
         'numeric/int128_test.cc',
         'posix/process_info_test.cc',
         'posix/symbolic_constants_posix_test.cc',
+        'stdlib/aligned_allocator_test.cc',
         'stdlib/map_insert_test.cc',
         'stdlib/string_number_conversion_test.cc',
         'stdlib/strlcpy_test.cc',
diff --git a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
index 4273523..5559efb 100644
--- a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
+++ b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
@@ -17,6 +17,8 @@
 #include <sddl.h>
 #include <string.h>
 
+#include <utility>
+
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/rand_util.h"
@@ -26,7 +28,6 @@
 #include "snapshot/crashpad_info_client_options.h"
 #include "snapshot/win/process_snapshot_win.h"
 #include "util/file/file_writer.h"
-#include "util/stdlib/move.h"
 #include "util/misc/random_string.h"
 #include "util/misc/tri_state.h"
 #include "util/misc/uuid.h"
@@ -180,7 +181,7 @@
             CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
         non_crash_dump_completed_event_(
             CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
-        process_(crashpad::move(process)),
+        process_(std::move(process)),
         crash_exception_information_address_(
             crash_exception_information_address),
         non_crash_exception_information_address_(
diff --git a/third_party/crashpad/crashpad/util/win/module_version.h b/third_party/crashpad/crashpad/util/win/module_version.h
index be56eb9d..afc2a508 100644
--- a/third_party/crashpad/crashpad/util/win/module_version.h
+++ b/third_party/crashpad/crashpad/util/win/module_version.h
@@ -24,9 +24,15 @@
 //! \brief Retrieve the type and version information from a given module (exe,
 //!     dll, etc.)
 //!
+//! This function calls `GetFileVersionInfo()`, which can implicitly call
+//! `LoadLibrary()` to load \a path into the calling process. Do not call this
+//! function on an untrusted module, because there is a risk of executing the
+//! module’s code.
+//!
 //! \param[in] path The path to the module to be inspected.
-//! \param[out] vs_fixedfileinfo The `VS_FIXEDFILEINFO` on success.
-//!    `dwFileFlags`  will have been masked with `dwFileFlagsMask` already.
+//! \param[out] vs_fixedfileinfo The VS_FIXEDFILEINFO on success.
+//!     VS_FIXEDFILEINFO::dwFileFlags will have been masked with
+//!     VS_FIXEDFILEINFO::dwFileFlagsMask already.
 //!
 //! \return `true` on success, or `false` on failure with a message logged. If
 //!     the module has no `VERSIONINFO` resource, `false` will be returned
diff --git a/third_party/crashpad/crashpad/util/win/process_info.cc b/third_party/crashpad/crashpad/util/win/process_info.cc
index 2ac3a98..5628e04 100644
--- a/third_party/crashpad/crashpad/util/win/process_info.cc
+++ b/third_party/crashpad/crashpad/util/win/process_info.cc
@@ -224,7 +224,7 @@
                      ProcessInfo* process_info) {
   typename Traits::Pointer peb_address;
   if (!AssignIfInRange(&peb_address, peb_address_vmaddr)) {
-    LOG(ERROR) << base::StringPrintf("peb address 0x%x out of range",
+    LOG(ERROR) << base::StringPrintf("peb address 0x%llx out of range",
                                      peb_address_vmaddr);
     return false;
   }
@@ -589,7 +589,8 @@
   return true;
 }
 
-const std::vector<MEMORY_BASIC_INFORMATION64>& ProcessInfo::MemoryInfo() const {
+const ProcessInfo::MemoryBasicInformation64Vector& ProcessInfo::MemoryInfo()
+    const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return memory_info_;
 }
@@ -629,11 +630,11 @@
 
 std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap(
     const CheckedRange<WinVMAddress, WinVMSize>& range,
-    const std::vector<MEMORY_BASIC_INFORMATION64>& memory_info) {
+    const ProcessInfo::MemoryBasicInformation64Vector& memory_info) {
   using Range = CheckedRange<WinVMAddress, WinVMSize>;
 
   // Find all the ranges that overlap the target range, maintaining their order.
-  std::vector<MEMORY_BASIC_INFORMATION64> overlapping;
+  ProcessInfo::MemoryBasicInformation64Vector overlapping;
   for (const auto& mi : memory_info) {
     static_assert(base::is_same<decltype(mi.BaseAddress), WinVMAddress>::value,
                   "expected range address to be WinVMAddress");
diff --git a/third_party/crashpad/crashpad/util/win/process_info.h b/third_party/crashpad/crashpad/util/win/process_info.h
index fb1b8b3..0362445 100644
--- a/third_party/crashpad/crashpad/util/win/process_info.h
+++ b/third_party/crashpad/crashpad/util/win/process_info.h
@@ -24,6 +24,7 @@
 #include "base/basictypes.h"
 #include "util/misc/initialization_state_dcheck.h"
 #include "util/numeric/checked_range.h"
+#include "util/stdlib/aligned_allocator.h"
 #include "util/win/address_types.h"
 
 namespace crashpad {
@@ -32,6 +33,10 @@
 //!     primarily of information stored in the Process Environment Block.
 class ProcessInfo {
  public:
+  //! \brief The return type of MemoryInfo(), for convenience.
+  using MemoryBasicInformation64Vector =
+      AlignedVector<MEMORY_BASIC_INFORMATION64>;
+
   //! \brief Contains information about a module loaded into a process.
   struct Module {
     Module();
@@ -124,7 +129,7 @@
   bool Modules(std::vector<Module>* modules) const;
 
   //! \brief Retrieves information about all pages mapped into the process.
-  const std::vector<MEMORY_BASIC_INFORMATION64>& MemoryInfo() const;
+  const MemoryBasicInformation64Vector& MemoryInfo() const;
 
   //! \brief Given a range to be read from the target process, returns a vector
   //!     of ranges, representing the readable portions of the original range.
@@ -174,7 +179,19 @@
   WinVMAddress peb_address_;
   WinVMSize peb_size_;
   std::vector<Module> modules_;
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info_;
+
+  // memory_info_ is a MemoryBasicInformation64Vector instead of a
+  // std::vector<MEMORY_BASIC_INFORMATION64> because MEMORY_BASIC_INFORMATION64
+  // is declared with __declspec(align(16)), but std::vector<> does not maintain
+  // this alignment on 32-bit x86. clang-cl (but not MSVC cl) takes advantage of
+  // the presumed alignment and emits SSE instructions that require aligned
+  // storage. clang-cl should relax (unfortunately), but in the mean time, this
+  // provides aligned storage. See https://crbug.com/564691 and
+  // http://llvm.org/PR25779.
+  //
+  // TODO(mark): Remove this workaround when http://llvm.org/PR25779 is fixed
+  // and the fix is present in the clang-cl that compiles this code.
+  MemoryBasicInformation64Vector memory_info_;
 
   // Handles() is logically const, but updates this member on first retrieval.
   // See https://crashpad.chromium.org/bug/9.
@@ -195,7 +212,7 @@
 //! ProcessInfo::GetReadableRanges().
 std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap(
     const CheckedRange<WinVMAddress, WinVMSize>& range,
-    const std::vector<MEMORY_BASIC_INFORMATION64>& memory_info);
+    const ProcessInfo::MemoryBasicInformation64Vector& memory_info);
 
 }  // namespace crashpad
 
diff --git a/third_party/crashpad/crashpad/util/win/process_info_test.cc b/third_party/crashpad/crashpad/util/win/process_info_test.cc
index e5bde2f..6917ed9 100644
--- a/third_party/crashpad/crashpad/util/win/process_info_test.cc
+++ b/third_party/crashpad/crashpad/util/win/process_info_test.cc
@@ -59,7 +59,7 @@
                                WinVMAddress code_address) {
   // Make sure the child code address is an code page address with the right
   // information.
-  const std::vector<MEMORY_BASIC_INFORMATION64>& memory_info =
+  const ProcessInfo::MemoryBasicInformation64Vector& memory_info =
       process_info.MemoryInfo();
   bool found_region = false;
   for (const auto& mi : memory_info) {
@@ -199,7 +199,7 @@
 #endif  // ARCH_CPU_64_BITS
 
 TEST(ProcessInfo, AccessibleRangesNone) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -215,7 +215,7 @@
 }
 
 TEST(ProcessInfo, AccessibleRangesOneInside) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -233,7 +233,7 @@
 }
 
 TEST(ProcessInfo, AccessibleRangesOneTruncatedSize) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -256,7 +256,7 @@
 }
 
 TEST(ProcessInfo, AccessibleRangesOneMovedStart) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -279,7 +279,7 @@
 }
 
 TEST(ProcessInfo, ReserveIsInaccessible) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -302,7 +302,7 @@
 }
 
 TEST(ProcessInfo, PageGuardIsInaccessible) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -327,7 +327,7 @@
 }
 
 TEST(ProcessInfo, PageNoAccessIsInaccessible) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -352,7 +352,7 @@
 }
 
 TEST(ProcessInfo, AccessibleRangesCoalesced) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -380,7 +380,7 @@
 }
 
 TEST(ProcessInfo, AccessibleRangesMiddleUnavailable) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 0;
@@ -410,7 +410,7 @@
 }
 
 TEST(ProcessInfo, RequestedBeforeMap) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 10;
@@ -428,7 +428,7 @@
 }
 
 TEST(ProcessInfo, RequestedAfterMap) {
-  std::vector<MEMORY_BASIC_INFORMATION64> memory_info;
+  ProcessInfo::MemoryBasicInformation64Vector memory_info;
   MEMORY_BASIC_INFORMATION64 mbi = {0};
 
   mbi.BaseAddress = 10;
diff --git a/third_party/crashpad/update.py b/third_party/crashpad/update.py
new file mode 100755
index 0000000..97d3bd5
--- /dev/null
+++ b/third_party/crashpad/update.py
@@ -0,0 +1,218 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright 2015 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 argparse
+import os
+import re
+import subprocess
+import sys
+import textwrap
+
+
+def SubprocessCheckCall0Or1(args):
+    """Like subprocss.check_call(), but allows a return code of 1.
+
+    Returns True if the subprocess exits with code 0, False if it exits with
+    code 1, and re-raises the subprocess.check_call() exception otherwise.
+    """
+    try:
+        subprocess.check_call(args)
+    except subprocess.CalledProcessError, e:
+        if e.returncode != 1:
+            raise
+        return False
+
+    return True
+
+
+def GitMergeBaseIsAncestor(ancestor, descendant):
+    """Determines whether |ancestor| is an ancestor of |descendant|.
+    """
+    return SubprocessCheckCall0Or1(
+        ['git', 'merge-base', '--is-ancestor', ancestor, descendant])
+
+
+def main(args):
+    parser = argparse.ArgumentParser(
+        description='Update the in-tree copy of an imported project')
+    parser.add_argument(
+        '--repository',
+        default='https://chromium.googlesource.com/crashpad/crashpad',
+        help='The imported project\'s remote fetch URL',
+        metavar='URL')
+    parser.add_argument(
+        '--subtree',
+        default='third_party/crashpad/crashpad',
+        help='The imported project\'s location in this project\'s tree',
+        metavar='PATH')
+    parser.add_argument(
+        '--update-to',
+        default='FETCH_HEAD',
+        help='What to update the imported project to',
+        metavar='COMMITISH')
+    parser.add_argument(
+        '--fetch-ref',
+        default='HEAD',
+        help='The remote ref to fetch',
+        metavar='REF')
+    parser.add_argument(
+        '--readme',
+        help='The README.chromium file describing the imported project',
+        metavar='FILE',
+        dest='readme_path')
+    parsed = parser.parse_args(args)
+
+    original_head = (
+        subprocess.check_output(['git', 'rev-parse', 'HEAD']).rstrip())
+
+    # Read the README, because that’s what it’s for. Extract some things from
+    # it, and save it to be able to update it later.
+    readme_path = (parsed.readme_path or
+                   os.path.join(os.path.dirname(__file__ or '.'),
+                                'README.chromium'))
+    readme_content_old = open(readme_path).read()
+
+    project_name_match = re.search(
+        r'^Name:\s+(.*)$', readme_content_old, re.MULTILINE)
+    project_name = project_name_match.group(1)
+
+    # Extract the original commit hash from the README.
+    revision_match = re.search(r'^Revision:\s+([0-9a-fA-F]{40})($|\s)',
+                               readme_content_old,
+                               re.MULTILINE)
+    revision_old = revision_match.group(1)
+
+    subprocess.check_call(['git', 'fetch', parsed.repository, parsed.fetch_ref])
+
+    # Make sure that parsed.update_to is an ancestor of FETCH_HEAD, and
+    # revision_old is an ancestor of parsed.update_to. This prevents the use of
+    # hashes that are known to git but that don’t make sense in the context of
+    # the update operation.
+    if not GitMergeBaseIsAncestor(parsed.update_to, 'FETCH_HEAD'):
+        raise Exception('update_to is not an ancestor of FETCH_HEAD',
+                        parsed.update_to,
+                        'FETCH_HEAD')
+    if not GitMergeBaseIsAncestor(revision_old, parsed.update_to):
+        raise Exception('revision_old is not an ancestor of update_to',
+                        revision_old,
+                        parsed.update_to)
+
+    update_range = revision_old + '..' + parsed.update_to
+
+    # This cherry-picks each change in the window from the upstream project into
+    # the current branch.
+    assisted_cherry_pick = False
+    try:
+        if not SubprocessCheckCall0Or1(['git',
+                                        'cherry-pick',
+                                        '--keep-redundant-commits',
+                                        '--strategy=subtree',
+                                        '-Xsubtree=' + parsed.subtree,
+                                        '-x',
+                                        update_range]):
+            assisted_cherry_pick = True
+            print >>sys.stderr, ("""
+Please fix the errors above and run "git cherry-pick --continue".
+Press Enter when "git cherry-pick" completes.
+You may use a new shell for this, or ^Z if job control is available.
+Press ^C to abort.
+""")
+            raw_input()
+    except:
+        # ^C, signal, or something else.
+        print >>sys.stderr, 'Aborting...'
+        subprocess.call(['git', 'cherry-pick', '--abort'])
+        raise
+
+    # Get an abbreviated hash and subject line for each commit in the window,
+    # sorted in chronological order.
+    log_lines = subprocess.check_output(['git',
+                                         '-c',
+                                         'core.abbrev=12',
+                                         'log',
+                                         '--abbrev-commit',
+                                         '--pretty=oneline',
+                                         '--reverse',
+                                         update_range]).splitlines(False)
+
+    if assisted_cherry_pick:
+        # If the user had to help, count the number of cherry-picked commits,
+        # expecting it to match.
+        cherry_picked_commits = int(subprocess.check_output(
+            ['git', 'rev-list', '--count', original_head + '..HEAD']))
+        if cherry_picked_commits != len(log_lines):
+            print >>sys.stderr, 'Something smells fishy, aborting anyway...'
+            subprocess.call(['git', 'cherry-pick', '--abort'])
+            raise Exception('not all commits were cherry-picked',
+                            len(log_lines),
+                            cherry_picked_commits)
+
+    # Make a nice commit message. Start with the full commit hash.
+    revision_new = subprocess.check_output(
+        ['git', 'rev-parse', parsed.update_to]).rstrip()
+    new_message = 'Update ' + project_name + ' to ' + revision_new + '\n\n'
+
+    # Wrap everything to 72 characters, with a hanging indent.
+    wrapper = textwrap.TextWrapper(width=72, subsequent_indent = ' ' * 13)
+    for line in log_lines:
+        # Strip trailing periods from subjects.
+        if line.endswith('.'):
+            line = line[:-1]
+
+        # If any subjects have what look like commit hashes in them, truncate
+        # them to 12 characters.
+        line = re.sub(r'(\s)([0-9a-fA-F]{12})([0-9a-fA-F]{28})($|\s)',
+                      r'\1\2\4',
+                      line)
+
+        new_message += '\n'.join(wrapper.wrap(line)) + '\n'
+
+    # Update the README with the new hash.
+    readme_content_new = re.sub(
+        r'^(Revision:\s+)([0-9a-fA-F]{40})($|\s.*?$)',
+        r'\g<1>' + revision_new,
+        readme_content_old,
+        1,
+        re.MULTILINE)
+
+    # If the in-tree copy has no changes relative to the upstream, clear the
+    # “Local Modifications” section of the README.
+    has_local_modifications = True
+    if SubprocessCheckCall0Or1(['git',
+                                'diff-tree',
+                                '--quiet',
+                                parsed.update_to,
+                                'HEAD:' + parsed.subtree]):
+        has_local_modifications = False
+
+        readme_content_new = re.sub(r'\nLocal Modifications:\n.*$',
+                                    '\nLocal Modifications:\nNone.',
+                                    readme_content_new,
+                                    1)
+
+    # This soft-reset causes all of the cherry-picks to show up as staged,
+    # which will have the effect of squashing them along with the README update
+    # when committed below.
+    subprocess.check_call(['git', 'reset', '--soft', original_head])
+
+    # Write the new README.
+    open(readme_path, 'w').write(readme_content_new)
+
+    # Commit everything.
+    subprocess.check_call(['git', 'add', readme_path])
+    subprocess.check_call(['git', 'commit', '--message=' + new_message])
+
+    if has_local_modifications:
+        print >>sys.stderr, (
+            'Remember to check the Local Modifications section in ' +
+            readme_path)
+
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
diff --git a/third_party/freetype-android/README.chromium b/third_party/freetype-android/README.chromium
index 126a660..f82eb5d 100644
--- a/third_party/freetype-android/README.chromium
+++ b/third_party/freetype-android/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-6-2
-Revision: 66cf29b1bc869b44863b0de2115bd017dfcce849
+Version: VER-2-6-2-updates
+Revision: a512b0fe7a8d9db0e5aa9c0a4db1e92cb861722d
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
 License File: src/docs/FTL.TXT
diff --git a/third_party/libjingle/BUILD.gn b/third_party/libjingle/BUILD.gn
index f2639466..5a2510a 100644
--- a/third_party/libjingle/BUILD.gn
+++ b/third_party/libjingle/BUILD.gn
@@ -321,6 +321,8 @@
       "source/talk/app/webrtc/mediastreamhandler.cc",
       "source/talk/app/webrtc/mediastreamhandler.h",
       "source/talk/app/webrtc/mediastreaminterface.h",
+      "source/talk/app/webrtc/mediastreamobserver.cc",
+      "source/talk/app/webrtc/mediastreamobserver.h",
       "source/talk/app/webrtc/mediastreamprovider.h",
       "source/talk/app/webrtc/mediastreamproxy.h",
       "source/talk/app/webrtc/mediastreamtrack.h",
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp
index 9fce241..d8417b7a 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -280,6 +280,8 @@
             '<(libjingle_source)/talk/app/webrtc/mediastreamhandler.cc',
             '<(libjingle_source)/talk/app/webrtc/mediastreamhandler.h',
             '<(libjingle_source)/talk/app/webrtc/mediastreaminterface.h',
+            '<(libjingle_source)/talk/app/webrtc/mediastreamobserver.cc',
+            '<(libjingle_source)/talk/app/webrtc/mediastreamobserver.h',
             '<(libjingle_source)/talk/app/webrtc/mediastreamprovider.h',
             '<(libjingle_source)/talk/app/webrtc/mediastreamproxy.h',
             '<(libjingle_source)/talk/app/webrtc/mediastreamtrack.h',
diff --git a/third_party/libpng/README.chromium b/third_party/libpng/README.chromium
index 2ac56157..80860bd 100644
--- a/third_party/libpng/README.chromium
+++ b/third_party/libpng/README.chromium
@@ -15,3 +15,4 @@
 
 - Unset PNG_NO_READ_PACK on Android in pngusr.h, required by freetype to support
   color glyphs.
+- Configure PNG chunk user limits (crbug.com/117369)
diff --git a/third_party/libpng/pngusr.h b/third_party/libpng/pngusr.h
index fabae6e..39cdb596 100644
--- a/third_party/libpng/pngusr.h
+++ b/third_party/libpng/pngusr.h
@@ -116,8 +116,13 @@
 #define PNG_NO_ZALLOC_ZERO
 #define PNG_NO_ERROR_NUMBERS
 #undef PNG_NO_EASY_ACCESS
-#define PNG_NO_USER_LIMITS
-#define PNG_NO_SET_USER_LIMITS
+
+/* Set recommended chunk limits: see https://crbug.com/117369 */
+#undef PNG_NO_USER_LIMITS
+#undef PNG_NO_SET_USER_LIMITS
+#define PNG_USER_CHUNK_CACHE_MAX 128
+#define PNG_USER_CHUNK_MALLOC_MAX 4000000L
+
 #define PNG_NO_TIME_RFC1123
 #undef PNG_NO_INFO_IMAGE
 #undef PNG_NO_PROGRESSIVE_READ
diff --git a/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h b/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h
deleted file mode 100644
index 88ab603a..0000000
--- a/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_extension_autogen.h
+++ /dev/null
@@ -1,568 +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.
-
-// This file is auto-generated from
-// gpu/command_buffer/build_gles2_cmd_buffer.py
-// It's formatted by clang-format using chromium coding style:
-//    clang-format -i -style=chromium filename
-// DO NOT EDIT!
-
-VISIT_GL_CALL(ShallowFinishCHROMIUM, void, (), ())
-VISIT_GL_CALL(ShallowFlushCHROMIUM, void, (), ())
-VISIT_GL_CALL(OrderingBarrierCHROMIUM, void, (), ())
-VISIT_GL_CALL(
-    BlitFramebufferCHROMIUM,
-    void,
-    (GLint srcX0,
-     GLint srcY0,
-     GLint srcX1,
-     GLint srcY1,
-     GLint dstX0,
-     GLint dstY0,
-     GLint dstX1,
-     GLint dstY1,
-     GLbitfield mask,
-     GLenum filter),
-    (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter))
-VISIT_GL_CALL(RenderbufferStorageMultisampleCHROMIUM,
-              void,
-              (GLenum target,
-               GLsizei samples,
-               GLenum internalformat,
-               GLsizei width,
-               GLsizei height),
-              (target, samples, internalformat, width, height))
-VISIT_GL_CALL(RenderbufferStorageMultisampleEXT,
-              void,
-              (GLenum target,
-               GLsizei samples,
-               GLenum internalformat,
-               GLsizei width,
-               GLsizei height),
-              (target, samples, internalformat, width, height))
-VISIT_GL_CALL(FramebufferTexture2DMultisampleEXT,
-              void,
-              (GLenum target,
-               GLenum attachment,
-               GLenum textarget,
-               GLuint texture,
-               GLint level,
-               GLsizei samples),
-              (target, attachment, textarget, texture, level, samples))
-VISIT_GL_CALL(TexStorage2DEXT,
-              void,
-              (GLenum target,
-               GLsizei levels,
-               GLenum internalFormat,
-               GLsizei width,
-               GLsizei height),
-              (target, levels, internalFormat, width, height))
-VISIT_GL_CALL(GenQueriesEXT, void, (GLsizei n, GLuint* queries), (n, queries))
-VISIT_GL_CALL(DeleteQueriesEXT,
-              void,
-              (GLsizei n, const GLuint* queries),
-              (n, queries))
-VISIT_GL_CALL(QueryCounterEXT, void, (GLuint id, GLenum target), (id, target))
-VISIT_GL_CALL(IsQueryEXT, GLboolean, (GLuint id), (id))
-VISIT_GL_CALL(BeginQueryEXT, void, (GLenum target, GLuint id), (target, id))
-VISIT_GL_CALL(EndQueryEXT, void, (GLenum target), (target))
-VISIT_GL_CALL(GetQueryivEXT,
-              void,
-              (GLenum target, GLenum pname, GLint* params),
-              (target, pname, params))
-VISIT_GL_CALL(GetQueryObjectivEXT,
-              void,
-              (GLuint id, GLenum pname, GLint* params),
-              (id, pname, params))
-VISIT_GL_CALL(GetQueryObjectuivEXT,
-              void,
-              (GLuint id, GLenum pname, GLuint* params),
-              (id, pname, params))
-VISIT_GL_CALL(GetQueryObjecti64vEXT,
-              void,
-              (GLuint id, GLenum pname, GLint64* params),
-              (id, pname, params))
-VISIT_GL_CALL(GetQueryObjectui64vEXT,
-              void,
-              (GLuint id, GLenum pname, GLuint64* params),
-              (id, pname, params))
-VISIT_GL_CALL(SetDisjointValueSyncCHROMIUM, void, (), ())
-VISIT_GL_CALL(InsertEventMarkerEXT,
-              void,
-              (GLsizei length, const GLchar* marker),
-              (length, marker))
-VISIT_GL_CALL(PushGroupMarkerEXT,
-              void,
-              (GLsizei length, const GLchar* marker),
-              (length, marker))
-VISIT_GL_CALL(PopGroupMarkerEXT, void, (), ())
-VISIT_GL_CALL(GenVertexArraysOES,
-              void,
-              (GLsizei n, GLuint* arrays),
-              (n, arrays))
-VISIT_GL_CALL(DeleteVertexArraysOES,
-              void,
-              (GLsizei n, const GLuint* arrays),
-              (n, arrays))
-VISIT_GL_CALL(IsVertexArrayOES, GLboolean, (GLuint array), (array))
-VISIT_GL_CALL(BindVertexArrayOES, void, (GLuint array), (array))
-VISIT_GL_CALL(SwapBuffers, void, (), ())
-VISIT_GL_CALL(GetMaxValueInBufferCHROMIUM,
-              GLuint,
-              (GLuint buffer_id, GLsizei count, GLenum type, GLuint offset),
-              (buffer_id, count, type, offset))
-VISIT_GL_CALL(EnableFeatureCHROMIUM,
-              GLboolean,
-              (const char* feature),
-              (feature))
-VISIT_GL_CALL(MapBufferCHROMIUM,
-              void*,
-              (GLuint target, GLenum access),
-              (target, access))
-VISIT_GL_CALL(UnmapBufferCHROMIUM, GLboolean, (GLuint target), (target))
-VISIT_GL_CALL(MapBufferSubDataCHROMIUM,
-              void*,
-              (GLuint target, GLintptr offset, GLsizeiptr size, GLenum access),
-              (target, offset, size, access))
-VISIT_GL_CALL(UnmapBufferSubDataCHROMIUM, void, (const void* mem), (mem))
-VISIT_GL_CALL(
-    MapTexSubImage2DCHROMIUM,
-    void*,
-    (GLenum target,
-     GLint level,
-     GLint xoffset,
-     GLint yoffset,
-     GLsizei width,
-     GLsizei height,
-     GLenum format,
-     GLenum type,
-     GLenum access),
-    (target, level, xoffset, yoffset, width, height, format, type, access))
-VISIT_GL_CALL(UnmapTexSubImage2DCHROMIUM, void, (const void* mem), (mem))
-VISIT_GL_CALL(ResizeCHROMIUM,
-              void,
-              (GLuint width, GLuint height, GLfloat scale_factor),
-              (width, height, scale_factor))
-VISIT_GL_CALL(GetRequestableExtensionsCHROMIUM, const GLchar*, (), ())
-VISIT_GL_CALL(RequestExtensionCHROMIUM,
-              void,
-              (const char* extension),
-              (extension))
-VISIT_GL_CALL(GetProgramInfoCHROMIUM,
-              void,
-              (GLuint program, GLsizei bufsize, GLsizei* size, void* info),
-              (program, bufsize, size, info))
-VISIT_GL_CALL(CreateStreamTextureCHROMIUM, GLuint, (GLuint texture), (texture))
-VISIT_GL_CALL(
-    CreateImageCHROMIUM,
-    GLuint,
-    (ClientBuffer buffer, GLsizei width, GLsizei height, GLenum internalformat),
-    (buffer, width, height, internalformat))
-VISIT_GL_CALL(DestroyImageCHROMIUM, void, (GLuint image_id), (image_id))
-VISIT_GL_CALL(
-    CreateGpuMemoryBufferImageCHROMIUM,
-    GLuint,
-    (GLsizei width, GLsizei height, GLenum internalformat, GLenum usage),
-    (width, height, internalformat, usage))
-VISIT_GL_CALL(GetTranslatedShaderSourceANGLE,
-              void,
-              (GLuint shader, GLsizei bufsize, GLsizei* length, char* source),
-              (shader, bufsize, length, source))
-VISIT_GL_CALL(PostSubBufferCHROMIUM,
-              void,
-              (GLint x, GLint y, GLint width, GLint height),
-              (x, y, width, height))
-VISIT_GL_CALL(TexImageIOSurface2DCHROMIUM,
-              void,
-              (GLenum target,
-               GLsizei width,
-               GLsizei height,
-               GLuint ioSurfaceId,
-               GLuint plane),
-              (target, width, height, ioSurfaceId, plane))
-VISIT_GL_CALL(CopyTextureCHROMIUM,
-              void,
-              (GLenum target,
-               GLenum source_id,
-               GLenum dest_id,
-               GLint internalformat,
-               GLenum dest_type,
-               GLboolean unpack_flip_y,
-               GLboolean unpack_premultiply_alpha,
-               GLboolean unpack_unmultiply_alpha),
-              (target,
-               source_id,
-               dest_id,
-               internalformat,
-               dest_type,
-               unpack_flip_y,
-               unpack_premultiply_alpha,
-               unpack_unmultiply_alpha))
-VISIT_GL_CALL(CopySubTextureCHROMIUM,
-              void,
-              (GLenum target,
-               GLenum source_id,
-               GLenum dest_id,
-               GLint xoffset,
-               GLint yoffset,
-               GLint x,
-               GLint y,
-               GLsizei width,
-               GLsizei height,
-               GLboolean unpack_flip_y,
-               GLboolean unpack_premultiply_alpha,
-               GLboolean unpack_unmultiply_alpha),
-              (target,
-               source_id,
-               dest_id,
-               xoffset,
-               yoffset,
-               x,
-               y,
-               width,
-               height,
-               unpack_flip_y,
-               unpack_premultiply_alpha,
-               unpack_unmultiply_alpha))
-VISIT_GL_CALL(CompressedCopyTextureCHROMIUM,
-              void,
-              (GLenum target, GLenum source_id, GLenum dest_id),
-              (target, source_id, dest_id))
-VISIT_GL_CALL(
-    CompressedCopySubTextureCHROMIUM,
-    void,
-    (GLenum target,
-     GLenum source_id,
-     GLenum dest_id,
-     GLint xoffset,
-     GLint yoffset,
-     GLint x,
-     GLint y,
-     GLsizei width,
-     GLsizei height),
-    (target, source_id, dest_id, xoffset, yoffset, x, y, width, height))
-VISIT_GL_CALL(DrawArraysInstancedANGLE,
-              void,
-              (GLenum mode, GLint first, GLsizei count, GLsizei primcount),
-              (mode, first, count, primcount))
-VISIT_GL_CALL(DrawElementsInstancedANGLE,
-              void,
-              (GLenum mode,
-               GLsizei count,
-               GLenum type,
-               const void* indices,
-               GLsizei primcount),
-              (mode, count, type, indices, primcount))
-VISIT_GL_CALL(VertexAttribDivisorANGLE,
-              void,
-              (GLuint index, GLuint divisor),
-              (index, divisor))
-VISIT_GL_CALL(GenMailboxCHROMIUM, void, (GLbyte * mailbox), (mailbox))
-VISIT_GL_CALL(ProduceTextureCHROMIUM,
-              void,
-              (GLenum target, const GLbyte* mailbox),
-              (target, mailbox))
-VISIT_GL_CALL(ProduceTextureDirectCHROMIUM,
-              void,
-              (GLuint texture, GLenum target, const GLbyte* mailbox),
-              (texture, target, mailbox))
-VISIT_GL_CALL(ConsumeTextureCHROMIUM,
-              void,
-              (GLenum target, const GLbyte* mailbox),
-              (target, mailbox))
-VISIT_GL_CALL(CreateAndConsumeTextureCHROMIUM,
-              GLuint,
-              (GLenum target, const GLbyte* mailbox),
-              (target, mailbox))
-VISIT_GL_CALL(BindUniformLocationCHROMIUM,
-              void,
-              (GLuint program, GLint location, const char* name),
-              (program, location, name))
-VISIT_GL_CALL(GenValuebuffersCHROMIUM,
-              void,
-              (GLsizei n, GLuint* buffers),
-              (n, buffers))
-VISIT_GL_CALL(DeleteValuebuffersCHROMIUM,
-              void,
-              (GLsizei n, const GLuint* valuebuffers),
-              (n, valuebuffers))
-VISIT_GL_CALL(IsValuebufferCHROMIUM,
-              GLboolean,
-              (GLuint valuebuffer),
-              (valuebuffer))
-VISIT_GL_CALL(BindValuebufferCHROMIUM,
-              void,
-              (GLenum target, GLuint valuebuffer),
-              (target, valuebuffer))
-VISIT_GL_CALL(SubscribeValueCHROMIUM,
-              void,
-              (GLenum target, GLenum subscription),
-              (target, subscription))
-VISIT_GL_CALL(PopulateSubscribedValuesCHROMIUM, void, (GLenum target), (target))
-VISIT_GL_CALL(UniformValuebufferCHROMIUM,
-              void,
-              (GLint location, GLenum target, GLenum subscription),
-              (location, target, subscription))
-VISIT_GL_CALL(BindTexImage2DCHROMIUM,
-              void,
-              (GLenum target, GLint imageId),
-              (target, imageId))
-VISIT_GL_CALL(ReleaseTexImage2DCHROMIUM,
-              void,
-              (GLenum target, GLint imageId),
-              (target, imageId))
-VISIT_GL_CALL(TraceBeginCHROMIUM,
-              void,
-              (const char* category_name, const char* trace_name),
-              (category_name, trace_name))
-VISIT_GL_CALL(TraceEndCHROMIUM, void, (), ())
-VISIT_GL_CALL(DiscardFramebufferEXT,
-              void,
-              (GLenum target, GLsizei count, const GLenum* attachments),
-              (target, count, attachments))
-VISIT_GL_CALL(LoseContextCHROMIUM,
-              void,
-              (GLenum current, GLenum other),
-              (current, other))
-VISIT_GL_CALL(InsertSyncPointCHROMIUM, GLuint, (), ())
-VISIT_GL_CALL(WaitSyncPointCHROMIUM, void, (GLuint sync_point), (sync_point))
-VISIT_GL_CALL(InsertFenceSyncCHROMIUM, GLuint64, (), ())
-VISIT_GL_CALL(GenSyncTokenCHROMIUM,
-              void,
-              (GLuint64 fence_sync, GLbyte* sync_token),
-              (fence_sync, sync_token))
-VISIT_GL_CALL(GenUnverifiedSyncTokenCHROMIUM,
-              void,
-              (GLuint64 fence_sync, GLbyte* sync_token),
-              (fence_sync, sync_token))
-VISIT_GL_CALL(WaitSyncTokenCHROMIUM,
-              void,
-              (const GLbyte* sync_token),
-              (sync_token))
-VISIT_GL_CALL(DrawBuffersEXT,
-              void,
-              (GLsizei count, const GLenum* bufs),
-              (count, bufs))
-VISIT_GL_CALL(DiscardBackbufferCHROMIUM, void, (), ())
-VISIT_GL_CALL(ScheduleOverlayPlaneCHROMIUM,
-              void,
-              (GLint plane_z_order,
-               GLenum plane_transform,
-               GLuint overlay_texture_id,
-               GLint bounds_x,
-               GLint bounds_y,
-               GLint bounds_width,
-               GLint bounds_height,
-               GLfloat uv_x,
-               GLfloat uv_y,
-               GLfloat uv_width,
-               GLfloat uv_height),
-              (plane_z_order,
-               plane_transform,
-               overlay_texture_id,
-               bounds_x,
-               bounds_y,
-               bounds_width,
-               bounds_height,
-               uv_x,
-               uv_y,
-               uv_width,
-               uv_height))
-VISIT_GL_CALL(SwapInterval, void, (GLint interval), (interval))
-VISIT_GL_CALL(FlushDriverCachesCHROMIUM, void, (), ())
-VISIT_GL_CALL(MatrixLoadfCHROMIUM,
-              void,
-              (GLenum matrixMode, const GLfloat* m),
-              (matrixMode, m))
-VISIT_GL_CALL(MatrixLoadIdentityCHROMIUM,
-              void,
-              (GLenum matrixMode),
-              (matrixMode))
-VISIT_GL_CALL(GenPathsCHROMIUM, GLuint, (GLsizei range), (range))
-VISIT_GL_CALL(DeletePathsCHROMIUM,
-              void,
-              (GLuint path, GLsizei range),
-              (path, range))
-VISIT_GL_CALL(IsPathCHROMIUM, GLboolean, (GLuint path), (path))
-VISIT_GL_CALL(PathCommandsCHROMIUM,
-              void,
-              (GLuint path,
-               GLsizei numCommands,
-               const GLubyte* commands,
-               GLsizei numCoords,
-               GLenum coordType,
-               const GLvoid* coords),
-              (path, numCommands, commands, numCoords, coordType, coords))
-VISIT_GL_CALL(PathParameterfCHROMIUM,
-              void,
-              (GLuint path, GLenum pname, GLfloat value),
-              (path, pname, value))
-VISIT_GL_CALL(PathParameteriCHROMIUM,
-              void,
-              (GLuint path, GLenum pname, GLint value),
-              (path, pname, value))
-VISIT_GL_CALL(PathStencilFuncCHROMIUM,
-              void,
-              (GLenum func, GLint ref, GLuint mask),
-              (func, ref, mask))
-VISIT_GL_CALL(StencilFillPathCHROMIUM,
-              void,
-              (GLuint path, GLenum fillMode, GLuint mask),
-              (path, fillMode, mask))
-VISIT_GL_CALL(StencilStrokePathCHROMIUM,
-              void,
-              (GLuint path, GLint reference, GLuint mask),
-              (path, reference, mask))
-VISIT_GL_CALL(CoverFillPathCHROMIUM,
-              void,
-              (GLuint path, GLenum coverMode),
-              (path, coverMode))
-VISIT_GL_CALL(CoverStrokePathCHROMIUM,
-              void,
-              (GLuint path, GLenum coverMode),
-              (path, coverMode))
-VISIT_GL_CALL(StencilThenCoverFillPathCHROMIUM,
-              void,
-              (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode),
-              (path, fillMode, mask, coverMode))
-VISIT_GL_CALL(StencilThenCoverStrokePathCHROMIUM,
-              void,
-              (GLuint path, GLint reference, GLuint mask, GLenum coverMode),
-              (path, reference, mask, coverMode))
-VISIT_GL_CALL(StencilFillPathInstancedCHROMIUM,
-              void,
-              (GLsizei numPaths,
-               GLenum pathNameType,
-               const GLvoid* paths,
-               GLuint pathBase,
-               GLenum fillMode,
-               GLuint mask,
-               GLenum transformType,
-               const GLfloat* transformValues),
-              (numPaths,
-               pathNameType,
-               paths,
-               pathBase,
-               fillMode,
-               mask,
-               transformType,
-               transformValues))
-VISIT_GL_CALL(StencilStrokePathInstancedCHROMIUM,
-              void,
-              (GLsizei numPaths,
-               GLenum pathNameType,
-               const GLvoid* paths,
-               GLuint pathBase,
-               GLint reference,
-               GLuint mask,
-               GLenum transformType,
-               const GLfloat* transformValues),
-              (numPaths,
-               pathNameType,
-               paths,
-               pathBase,
-               reference,
-               mask,
-               transformType,
-               transformValues))
-VISIT_GL_CALL(CoverFillPathInstancedCHROMIUM,
-              void,
-              (GLsizei numPaths,
-               GLenum pathNameType,
-               const GLvoid* paths,
-               GLuint pathBase,
-               GLenum coverMode,
-               GLenum transformType,
-               const GLfloat* transformValues),
-              (numPaths,
-               pathNameType,
-               paths,
-               pathBase,
-               coverMode,
-               transformType,
-               transformValues))
-VISIT_GL_CALL(CoverStrokePathInstancedCHROMIUM,
-              void,
-              (GLsizei numPaths,
-               GLenum pathNameType,
-               const GLvoid* paths,
-               GLuint pathBase,
-               GLenum coverMode,
-               GLenum transformType,
-               const GLfloat* transformValues),
-              (numPaths,
-               pathNameType,
-               paths,
-               pathBase,
-               coverMode,
-               transformType,
-               transformValues))
-VISIT_GL_CALL(StencilThenCoverFillPathInstancedCHROMIUM,
-              void,
-              (GLsizei numPaths,
-               GLenum pathNameType,
-               const GLvoid* paths,
-               GLuint pathBase,
-               GLenum fillMode,
-               GLuint mask,
-               GLenum coverMode,
-               GLenum transformType,
-               const GLfloat* transformValues),
-              (numPaths,
-               pathNameType,
-               paths,
-               pathBase,
-               fillMode,
-               mask,
-               coverMode,
-               transformType,
-               transformValues))
-VISIT_GL_CALL(StencilThenCoverStrokePathInstancedCHROMIUM,
-              void,
-              (GLsizei numPaths,
-               GLenum pathNameType,
-               const GLvoid* paths,
-               GLuint pathBase,
-               GLint reference,
-               GLuint mask,
-               GLenum coverMode,
-               GLenum transformType,
-               const GLfloat* transformValues),
-              (numPaths,
-               pathNameType,
-               paths,
-               pathBase,
-               reference,
-               mask,
-               coverMode,
-               transformType,
-               transformValues))
-VISIT_GL_CALL(BindFragmentInputLocationCHROMIUM,
-              void,
-              (GLuint program, GLint location, const char* name),
-              (program, location, name))
-VISIT_GL_CALL(ProgramPathFragmentInputGenCHROMIUM,
-              void,
-              (GLuint program,
-               GLint location,
-               GLenum genMode,
-               GLint components,
-               const GLfloat* coeffs),
-              (program, location, genMode, components, coeffs))
-VISIT_GL_CALL(GetGraphicsResetStatusKHR, GLenum, (), ())
-VISIT_GL_CALL(BlendBarrierKHR, void, (), ())
-VISIT_GL_CALL(ApplyScreenSpaceAntialiasingCHROMIUM, void, (), ())
-VISIT_GL_CALL(
-    BindFragDataLocationIndexedEXT,
-    void,
-    (GLuint program, GLuint colorNumber, GLuint index, const char* name),
-    (program, colorNumber, index, name))
-VISIT_GL_CALL(BindFragDataLocationEXT,
-              void,
-              (GLuint program, GLuint colorNumber, const char* name),
-              (program, colorNumber, name))
-VISIT_GL_CALL(GetFragDataIndexEXT,
-              GLint,
-              (GLuint program, const char* name),
-              (program, name))
diff --git a/tools/clang/empty_string/EmptyStringConverter.cpp b/tools/clang/empty_string/EmptyStringConverter.cpp
index d056755a..fce692f 100644
--- a/tools/clang/empty_string/EmptyStringConverter.cpp
+++ b/tools/clang/empty_string/EmptyStringConverter.cpp
@@ -8,8 +8,8 @@
 // should be run using the tools/clang/scripts/run_tool.py helper.
 
 #include <memory>
-#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Tooling/CommonOptionsParser.h"
@@ -17,24 +17,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Support/CommandLine.h"
 
-using clang::ast_matchers::MatchFinder;
-using clang::ast_matchers::argumentCountIs;
-using clang::ast_matchers::bindTemporaryExpr;
-using clang::ast_matchers::constructorDecl;
-using clang::ast_matchers::constructExpr;
-using clang::ast_matchers::defaultArgExpr;
-using clang::ast_matchers::expr;
-using clang::ast_matchers::forEach;
-using clang::ast_matchers::has;
-using clang::ast_matchers::hasArgument;
-using clang::ast_matchers::hasDeclaration;
-using clang::ast_matchers::hasName;
-using clang::ast_matchers::id;
-using clang::ast_matchers::methodDecl;
-using clang::ast_matchers::newExpr;
-using clang::ast_matchers::ofClass;
-using clang::ast_matchers::stringLiteral;
-using clang::ast_matchers::varDecl;
+using namespace clang::ast_matchers;
 using clang::tooling::CommonOptionsParser;
 using clang::tooling::Replacement;
 using clang::tooling::Replacements;
@@ -97,25 +80,24 @@
 };
 
 void EmptyStringConverter::SetupMatchers(MatchFinder* match_finder) {
-  const clang::ast_matchers::StatementMatcher& constructor_call =
-      id("call",
-         constructExpr(
-             hasDeclaration(methodDecl(ofClass(hasName("std::basic_string")))),
-             argumentCountIs(2),
-             hasArgument(0, id("literal", stringLiteral())),
-             hasArgument(1, defaultArgExpr())));
+  const clang::ast_matchers::StatementMatcher& constructor_call = id(
+      "call",
+      cxxConstructExpr(
+          hasDeclaration(cxxMethodDecl(ofClass(hasName("std::basic_string")))),
+          argumentCountIs(2), hasArgument(0, id("literal", stringLiteral())),
+          hasArgument(1, cxxDefaultArgExpr())));
 
   // Note that expr(has()) in the matcher is significant; the Clang AST wraps
   // calls to the std::string constructor with exprWithCleanups nodes. Without
   // the expr(has()) matcher, the first and last rules would not match anything!
   match_finder->addMatcher(varDecl(forEach(expr(has(constructor_call)))),
                            &constructor_callback_);
-  match_finder->addMatcher(newExpr(has(constructor_call)),
+  match_finder->addMatcher(cxxNewExpr(has(constructor_call)),
                            &constructor_callback_);
-  match_finder->addMatcher(bindTemporaryExpr(has(constructor_call)),
+  match_finder->addMatcher(cxxBindTemporaryExpr(has(constructor_call)),
                            &temporary_callback_);
   match_finder->addMatcher(
-      constructorDecl(forEach(expr(has(constructor_call)))),
+      cxxConstructorDecl(forEach(expr(has(constructor_call)))),
       &initializer_callback_);
 }
 
@@ -160,8 +142,7 @@
     replacements_->insert(Replacement(*result.SourceManager, literal, ""));
   } else {
     replacements_->insert(
-        Replacement(*result.SourceManager,
-                    call,
+        Replacement(*result.SourceManager, call,
                     literal->isWide() ? "std::wstring()" : "std::string()"));
   }
 }
@@ -196,8 +177,9 @@
   // tools.
   llvm::outs() << "==== BEGIN EDITS ====\n";
   for (const auto& r : replacements) {
-    llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset() << ":::"
-                 << r.getLength() << ":::" << r.getReplacementText() << "\n";
+    llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
+                 << ":::" << r.getLength() << ":::" << r.getReplacementText()
+                 << "\n";
   }
   llvm::outs() << "==== END EDITS ====\n";
 
diff --git a/tools/clang/empty_string/tests/test-expected.cc b/tools/clang/empty_string/tests/test-expected.cc
index 6762e375..3ae6702 100644
--- a/tools/clang/empty_string/tests/test-expected.cc
+++ b/tools/clang/empty_string/tests/test-expected.cc
@@ -13,8 +13,8 @@
 
 // Tests for std::string allocated with new.
 void TestNew() {
-  std::string* a = new std::string, *b = new std::string("abc"),
-               *c = new std::string, *d = new std::string();
+  std::string *a = new std::string, *b = new std::string("abc"),
+              *c = new std::string, *d = new std::string();
 }
 
 // Tests for std::string construction in initializer lists.
@@ -43,4 +43,3 @@
   TestWideTemporaries(std::wstring(), std::wstring());
   TestWideTemporaries(std::wstring(), std::wstring());
 }
-
diff --git a/tools/clang/scripts/test_tool.py b/tools/clang/scripts/test_tool.py
index 1f64be4..986216c 100755
--- a/tools/clang/scripts/test_tool.py
+++ b/tools/clang/scripts/test_tool.py
@@ -83,6 +83,10 @@
       print 'run_tool failed:\n%s' % stdout
       sys.exit(1)
 
+    args = ['git', 'cl', 'format']
+    args.extend(actual_files)
+    subprocess.check_call(args)
+
     passed = 0
     failed = 0
     for expected, actual in zip(expected_files, actual_files):
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index a3fdd61..3ec0723 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -382,6 +382,7 @@
         'type': contents.get('mb_type', ''),
         'gn_args': gn_args,
         'gyp_defines': gyp_defines,
+        'gyp_crosscompile': False,
     }
 
   def ReadConfigFile(self):
@@ -782,6 +783,7 @@
     # Ensure that we have an environment that only contains
     # the exact values of the GYP variables we need.
     env = os.environ.copy()
+    env['GYP_GENERATORS'] = 'ninja'
     if 'GYP_CHROMIUM_NO_ACTION' in env:
       del env['GYP_CHROMIUM_NO_ACTION']
     if 'GYP_CROSSCOMPILE' in env:
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 24ab831..e7b935b 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -7372,6 +7372,34 @@
   </summary>
 </histogram>
 
+<histogram name="DirectWrite.Fonts.Proxy.LoaderType"
+    enum="DirectWriteFontLoaderType">
+  <owner>kulshin@chromium.org</owner>
+  <summary>
+    The codepath that was used to load a font family. This is logged in the
+    browser every time a renderer attempts to load a font family, once per font
+    file.
+  </summary>
+</histogram>
+
+<histogram name="DirectWrite.Fonts.Proxy.LoadFamilyResult"
+    enum="DirectWriteLoadFamilyResult">
+  <owner>kulshin@chromium.org</owner>
+  <summary>
+    The outcome of attempting to load a font family in the renderer (success vs
+    failure and number of families). This is logged in the renderer once per
+    family that is loaded.
+  </summary>
+</histogram>
+
+<histogram name="DirectWrite.Fonts.Proxy.LoadFamilyTime" units="milliseconds">
+  <owner>kulshin@chromium.org</owner>
+  <summary>
+    The time taken to load a font family, excluding glyph data. This is logged
+    in the renderer once per family that is loaded.
+  </summary>
+</histogram>
+
 <histogram name="DisabledExtension.ExtensionWipedStatus" enum="BooleanWiped">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Whether an extension has been wiped out.</summary>
@@ -42453,6 +42481,25 @@
   </summary>
 </histogram>
 
+<histogram name="Sdch3.UsageInterval" units="milliseconds">
+  <owner>rdsmith@chromium.org</owner>
+  <obsolete>
+    Use Sdch3.UsageInterval2 instead.
+  </obsolete>
+  <summary>
+    The amount of time from the last time an SDCH dictionary was used.  For the
+    first use of a dictionary, the maximum time is used.
+  </summary>
+</histogram>
+
+<histogram name="Sdch3.UsageInterval2" units="milliseconds">
+  <owner>rdsmith@chromium.org</owner>
+  <summary>
+    The amount of time from the last time an SDCH dictionary was used.  Not
+    recorded on first dictionary use.
+  </summary>
+</histogram>
+
 <histogram name="Search.AddSearchProvider" enum="AddSearchProvider">
   <obsolete>
     Use Search.AddSearchProvider2 instead.
@@ -58941,6 +58988,21 @@
   <int value="1" label="Failed"/>
 </enum>
 
+<enum name="DirectWriteFontLoaderType" type="int">
+  <int value="0" label="File: system font directory"/>
+  <int value="1" label="File: sandbox whitelisted"/>
+  <int value="2" label="File: outside sandbox whitelist"/>
+  <int value="3" label="Other"/>
+</enum>
+
+<enum name="DirectWriteLoadFamilyResult" type="int">
+  <int value="0" label="Success: single family"/>
+  <int value="1" label="Success: matched from collection"/>
+  <int value="2" label="Error: multiple families"/>
+  <int value="3" label="Error: no families"/>
+  <int value="4" label="Error: failed to create colleciton"/>
+</enum>
+
 <enum name="DistillableType" type="int">
   <int value="0" label="Not distillable"/>
   <int value="1" label="Non-mobile-friendly Distillable"/>
diff --git a/tools/perf/benchmarks/start_with_url2.py b/tools/perf/benchmarks/start_with_url.py
similarity index 100%
rename from tools/perf/benchmarks/start_with_url2.py
rename to tools/perf/benchmarks/start_with_url.py
diff --git a/tools/perf/docs/perf_bot_sheriffing.md b/tools/perf/docs/perf_bot_sheriffing.md
index 419b692..89290d9 100644
--- a/tools/perf/docs/perf_bot_sheriffing.md
+++ b/tools/perf/docs/perf_bot_sheriffing.md
@@ -8,7 +8,7 @@
   * [Keeping the chromium.perf waterfall green](#chromiumperf)
      * [Handling Test Failures](#testfailures)
      * [Handling Device and Bot Failures](#botfailures)
-     * [Follow up on failures and keep state](#followup)
+     * [Follow up on failures](#followup)
   * [Triaging Data Stoppage Alerts](#datastoppage)
 
 ###<a name="chromiumperf"></a> Keeping the chromium.perf waterfall green
@@ -33,10 +33,7 @@
       it easier to see a summary.
    2. [Waterfall view](https://uberchromegw.corp.google.com/i/chromium.perf/waterfall)
       shows more details, including recent changes.
-   3. [Sheriff-o-Matic](https://sheriff-o-matic.appspot.com/chromium.perf)
-      attempts to group and summarize test failures with bug links. But it is
-      much more useful if all sheriffs use it.
-   4. [Firefighter](https://chromiumperfstats.appspot.com/) shows traces of
+   3. [Firefighter](https://chromiumperfstats.appspot.com/) shows traces of
       recent builds. It takes url parameter arguments:
       * **master** can be chromium.perf, tryserver.chromium.perf
       * **builder** can be a builder or tester name, like
@@ -46,9 +43,9 @@
 You can see a list of all previously filed bugs using the **[Performance-Waterfall](https://code.google.com/p/chromium/issues/list?can=2&q=label%3APerformance-Waterfall)**
 label in crbug.
 
-Please also check the **[perf status](https://docs.google.com/document/d/1kIMZ8jNA2--4JsCtUJ_OprnlfT6aM3BfHrQ8o4s3bDI/edit#)**
-doc and keep it up to date throughout your shift with known issues and ongoing
-problems.
+Please also check the recent
+**[perf-sheriffs@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/perf-sheriffs)**
+postings for important announcements about bot turndowns and other known issues.
 
 ####<a name="testfailures"></a> Handling Test Failures
 
@@ -158,7 +155,7 @@
 For both types of failures, please file a bug with [this template](https://code.google.com/p/chromium/issues/entry?labels=Pri-1,Performance-Waterfall,Performance-Sheriff,Infra-Labs,OS-Android&comment=Link+to+buildbot+status+page:&summary=Device+offline+on+chromium.perf)
 which will add an issue to the infra labs queue.
 
-####<a name="followup"></a> Follow up on failures and keep state
+####<a name="followup"></a> Follow up on failures
 
 **[Pri-0 bugs](https://code.google.com/p/chromium/issues/list?can=2&q=label%3APerformance-Waterfall+label%3APri-0)**
 should have an owner or contact on speed infra team and be worked on as top
@@ -170,7 +167,8 @@
 
 **[Pri-2 bugs](https://code.google.com/p/chromium/issues/list?can=2&q=label%3APerformance-Waterfall+label%3APri-2)**
 are for disabled tests. These should be pinged weekly, and work towards fixing
-should be ongoing when the sheriff is not working on a Pri-1 issue.
+should be ongoing when the sheriff is not working on a Pri-1 issue. Here is the
+[list of Pri-2 bugs that have not been pinged in a week](https://code.google.com/p/chromium/issues/list?can=2&q=label:Performance-Waterfall%20label:Pri-2%20modified-before:today-7&sort=modified)
 
 If you need help triaging, here are the common labels you should use:
    * **Performance-Waterfall** should go on all bugs you file about the bots,
diff --git a/tools/telemetry/telemetry/internal/platform/android_device.py b/tools/telemetry/telemetry/internal/platform/android_device.py
index b3448b69..bcddb60a 100644
--- a/tools/telemetry/telemetry/internal/platform/android_device.py
+++ b/tools/telemetry/telemetry/internal/platform/android_device.py
@@ -129,7 +129,11 @@
 
 
 def _HasValidAdb():
-  """Returns true if adb is present."""
+  """Returns true if adb is present.
+
+  Note that this currently will return True even if the adb that's present
+  cannot run on this system.
+  """
   if os.name != 'posix' or cros_device.IsRunningOnCrOS():
     return False
 
@@ -186,6 +190,10 @@
       devices = AndroidDevice.GetAllConnectedDevices(blacklist)
   finally:
     if not devices and _HasValidAdb():
-      adb_wrapper.AdbWrapper.KillServer()
+      try:
+        adb_wrapper.AdbWrapper.KillServer()
+      except device_errors.NoAdbError as e:
+        logging.warning(
+            'adb reported as present, but NoAdbError thrown: %s', str(e))
 
   return devices
diff --git a/ui/events/ozone/BUILD.gn b/ui/events/ozone/BUILD.gn
index 2bef777..b1f7953 100644
--- a/ui/events/ozone/BUILD.gn
+++ b/ui/events/ozone/BUILD.gn
@@ -137,6 +137,7 @@
       "//ui/events/devices",
       "//ui/events/platform",
       "//ui/gfx",
+      "//ui/ozone:ozone_base",
     ]
 
     public_configs = [ ":evdev" ]
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
index d14e499..9624ec2a 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -34,7 +34,6 @@
 #include "ui/events/ozone/evdev/touch_evdev_types.h"
 #include "ui/events/ozone/evdev/touch_noise/touch_noise_finder.h"
 #include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
 
 namespace {
 
diff --git a/ui/gfx/win/direct_write.cc b/ui/gfx/win/direct_write.cc
index 38c926a..9c8250b 100644
--- a/ui/gfx/win/direct_write.cc
+++ b/ui/gfx/win/direct_write.cc
@@ -4,8 +4,6 @@
 
 #include "ui/gfx/win/direct_write.h"
 
-#include <dwrite.h>
-
 #include "base/basictypes.h"
 #include "base/command_line.h"
 #include "base/metrics/field_trial.h"
@@ -57,12 +55,7 @@
   return group_name != "Disabled";
 }
 
-void MaybeInitializeDirectWrite() {
-  static bool tried_dwrite_initialize = false;
-  if (tried_dwrite_initialize)
-    return;
-  tried_dwrite_initialize = true;
-
+void CreateDWriteFactory(IDWriteFactory** factory) {
   if (!ShouldUseDirectWrite() ||
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableDirectWriteForUI)) {
@@ -81,13 +74,26 @@
   if (!dwrite_create_factory_proc)
     return;
 
-  base::win::ScopedComPtr<IDWriteFactory> factory;
-
   // Failure to create the DirectWrite factory indicates a corrupt dll.
-  if (FAILED(dwrite_create_factory_proc(
-          DWRITE_FACTORY_TYPE_SHARED,
-        __uuidof(IDWriteFactory),
-        reinterpret_cast<IUnknown**>(factory.Receive()))))
+  base::win::ScopedComPtr<IUnknown> factory_unknown;
+  if (FAILED(dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
+                                        __uuidof(IDWriteFactory),
+                                        factory_unknown.Receive()))) {
+    return;
+  }
+  factory_unknown.QueryInterface<IDWriteFactory>(factory);
+}
+
+void MaybeInitializeDirectWrite() {
+  static bool tried_dwrite_initialize = false;
+  if (tried_dwrite_initialize)
+    return;
+  tried_dwrite_initialize = true;
+
+  base::win::ScopedComPtr<IDWriteFactory> factory;
+  CreateDWriteFactory(factory.Receive());
+
+  if (factory == nullptr)
     return;
 
   // The skia call to create a new DirectWrite font manager instance can fail
diff --git a/ui/gfx/win/direct_write.h b/ui/gfx/win/direct_write.h
index f16e45c..ec22a00 100644
--- a/ui/gfx/win/direct_write.h
+++ b/ui/gfx/win/direct_write.h
@@ -5,6 +5,8 @@
 #ifndef UI_GFX_WIN_DIRECT_WRITE_H_
 #define UI_GFX_WIN_DIRECT_WRITE_H_
 
+#include <dwrite.h>
+
 #include "ui/gfx/gfx_export.h"
 
 namespace gfx {
@@ -18,6 +20,9 @@
 // Returns true if we are using DirectWrite for font metrics and rendering.
 GFX_EXPORT bool IsDirectWriteEnabled();
 
+// Creates a DirectWrite factory, if using DirectWrite.
+GFX_EXPORT void CreateDWriteFactory(IDWriteFactory** factory);
+
 }  // namespace win
 }  // namespace gfx
 
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn
index 34622c4..32746189 100644
--- a/ui/ozone/BUILD.gn
+++ b/ui/ozone/BUILD.gn
@@ -57,34 +57,6 @@
 # GYP version: ui/ozone/ozone.gyp:ozone_base
 component("ozone_base") {
   sources = [
-    "public/cursor_factory_ozone.cc",
-    "public/cursor_factory_ozone.h",
-    "public/gpu_platform_support.cc",
-    "public/gpu_platform_support.h",
-    "public/gpu_platform_support_host.cc",
-    "public/gpu_platform_support_host.h",
-    "public/overlay_candidates_ozone.cc",
-    "public/overlay_candidates_ozone.h",
-    "public/overlay_manager_ozone.h",
-    "public/surface_factory_ozone.cc",
-    "public/surface_factory_ozone.h",
-    "public/surface_ozone_canvas.h",
-    "public/surface_ozone_egl.cc",
-    "public/surface_ozone_egl.h",
-    "public/system_input_injector.h",
-  ]
-
-  defines = [ "OZONE_BASE_IMPLEMENTATION" ]
-
-  deps = [
-    "//base",
-    "//skia",
-    "//ui/gfx/geometry",
-  ]
-}
-
-component("ozone") {
-  sources = [
     "common/display_mode_proxy.cc",
     "common/display_mode_proxy.h",
     "common/display_snapshot_proxy.cc",
@@ -104,18 +76,53 @@
     "common/stub_client_native_pixmap_factory.h",
     "common/stub_overlay_manager.cc",
     "common/stub_overlay_manager.h",
+    "public/cursor_factory_ozone.cc",
+    "public/cursor_factory_ozone.h",
+    "public/gpu_platform_support.cc",
+    "public/gpu_platform_support.h",
+    "public/gpu_platform_support_host.cc",
+    "public/gpu_platform_support_host.h",
+    "public/input_controller.cc",
+    "public/input_controller.h",
+    "public/overlay_candidates_ozone.cc",
+    "public/overlay_candidates_ozone.h",
+    "public/overlay_manager_ozone.h",
+    "public/ozone_switches.cc",
+    "public/ozone_switches.h",
+    "public/surface_factory_ozone.cc",
+    "public/surface_factory_ozone.h",
+    "public/surface_ozone_canvas.h",
+    "public/surface_ozone_egl.cc",
+    "public/surface_ozone_egl.h",
+    "public/system_input_injector.h",
+  ]
+
+  defines = [ "OZONE_BASE_IMPLEMENTATION" ]
+
+  deps = [
+    "//base",
+    "//ipc",
+    "//skia",
+    "//ui/display/types",
+    "//ui/display/util",
+    "//ui/events",
+    "//ui/events:dom_keycode_converter",
+    "//ui/gfx",
+    "//ui/gfx/geometry",
+    "//ui/gfx/ipc",
+  ]
+}
+
+component("ozone") {
+  sources = [
     "platform_selection.cc",
     "platform_selection.h",
     "public/client_native_pixmap_factory.cc",
     "public/client_native_pixmap_factory.h",
-    "public/input_controller.cc",
-    "public/input_controller.h",
     "public/ozone_gpu_test_helper.cc",
     "public/ozone_gpu_test_helper.h",
     "public/ozone_platform.cc",
     "public/ozone_platform.h",
-    "public/ozone_switches.cc",
-    "public/ozone_switches.h",
     constructor_list_cc_file,
     platform_list_cc_file,
     platform_list_h_file,
diff --git a/ui/ozone/common/stub_client_native_pixmap_factory.h b/ui/ozone/common/stub_client_native_pixmap_factory.h
index a38a557..27192f7 100644
--- a/ui/ozone/common/stub_client_native_pixmap_factory.h
+++ b/ui/ozone/common/stub_client_native_pixmap_factory.h
@@ -5,7 +5,7 @@
 #ifndef UI_OZONE_COMMON_STUB_CLIENT_NATIVE_PIXMAP_FACTORY_H_
 #define UI_OZONE_COMMON_STUB_CLIENT_NATIVE_PIXMAP_FACTORY_H_
 
-#include "ui/ozone/public/client_native_pixmap_factory.h"
+#include "ui/ozone/public/client_native_pixmap_factory.h"  // nogncheck
 
 namespace ui {
 
diff --git a/ui/ozone/demo/BUILD.gn b/ui/ozone/demo/BUILD.gn
index f0ba120..70b2ded5 100644
--- a/ui/ozone/demo/BUILD.gn
+++ b/ui/ozone/demo/BUILD.gn
@@ -26,10 +26,14 @@
     "//base",
     "//build/config/sanitizers:deps",
     "//skia",
+    "//ui/display/types",
+    "//ui/events",
+    "//ui/events:dom_keycode_converter",
     "//ui/events/ozone:events_ozone_layout",
     "//ui/gfx/geometry",
     "//ui/gl",
     "//ui/ozone",
     "//ui/ozone:ozone_base",
+    "//ui/platform_window",
   ]
 }
diff --git a/ui/ozone/platform/caca/BUILD.gn b/ui/ozone/platform/caca/BUILD.gn
index 71510edc..4f92fce 100644
--- a/ui/ozone/platform/caca/BUILD.gn
+++ b/ui/ozone/platform/caca/BUILD.gn
@@ -23,9 +23,12 @@
   deps = [
     "//base",
     "//skia",
+    "//ui/events",
     "//ui/events/ozone:events_ozone_layout",
     "//ui/events/platform",
+    "//ui/gfx",
     "//ui/gfx/geometry",
+    "//ui/ozone:ozone_base",
   ]
 
   configs += [ ":libcaca" ]
diff --git a/ui/ozone/platform/caca/ozone_platform_caca.cc b/ui/ozone/platform/caca/ozone_platform_caca.cc
index 3a5a3e9b..2a9f4c02 100644
--- a/ui/ozone/platform/caca/ozone_platform_caca.cc
+++ b/ui/ozone/platform/caca/ozone_platform_caca.cc
@@ -15,7 +15,7 @@
 #include "ui/ozone/public/gpu_platform_support.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_platform.h"  // nogncheck
 #include "ui/ozone/public/system_input_injector.h"
 
 namespace ui {
diff --git a/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc b/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
index a55c3462..2173d6b 100644
--- a/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
+++ b/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/ozone/public/client_native_pixmap.h"
-#include "ui/ozone/public/client_native_pixmap_factory.h"
+#include "ui/ozone/public/client_native_pixmap_factory.h"  // nogncheck
 
 namespace ui {
 namespace {
diff --git a/ui/ozone/platform/cast/overlay_manager_cast.cc b/ui/ozone/platform/cast/overlay_manager_cast.cc
index 0d9d30c..f261887 100644
--- a/ui/ozone/platform/cast/overlay_manager_cast.cc
+++ b/ui/ozone/platform/cast/overlay_manager_cast.cc
@@ -36,21 +36,11 @@
   }
 }
 
-bool ExactlyEqual(const chromecast::RectF& r1, const chromecast::RectF& r2) {
-  return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width &&
-         r1.height == r2.height;
-}
-
 class OverlayCandidatesCast : public OverlayCandidatesOzone {
  public:
-  OverlayCandidatesCast()
-      : transform_(gfx::OVERLAY_TRANSFORM_INVALID), display_rect_(0, 0, 0, 0) {}
+  OverlayCandidatesCast() {}
 
   void CheckOverlaySupport(OverlaySurfaceCandidateList* surfaces) override;
-
- private:
-  gfx::OverlayTransform transform_;
-  chromecast::RectF display_rect_;
 };
 
 void OverlayCandidatesCast::CheckOverlaySupport(
@@ -70,16 +60,9 @@
         candidate.display_rect.width(), candidate.display_rect.height());
 
     // Update video plane geometry + transform to match compositor quad.
-    if (candidate.transform != transform_ ||
-        !ExactlyEqual(display_rect, display_rect_)) {
-      transform_ = candidate.transform;
-      display_rect_ = display_rect;
+    chromecast::media::VideoPlaneController::GetInstance()->SetGeometry(
+        display_rect, ConvertTransform(candidate.transform));
 
-      chromecast::media::VideoPlaneController* video_plane =
-          chromecast::media::VideoPlaneController::GetInstance();
-      video_plane->SetGeometry(display_rect,
-                               ConvertTransform(candidate.transform));
-    }
     return;
   }
 }
diff --git a/ui/ozone/platform/cast/ozone_platform_cast.cc b/ui/ozone/platform/cast/ozone_platform_cast.cc
index 338fac22..ec9f8a1 100644
--- a/ui/ozone/platform/cast/ozone_platform_cast.cc
+++ b/ui/ozone/platform/cast/ozone_platform_cast.cc
@@ -16,7 +16,7 @@
 #include "ui/ozone/public/cursor_factory_ozone.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_platform.h"  // nogncheck
 #include "ui/ozone/public/system_input_injector.h"
 
 using chromecast::CastEglPlatform;
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn
index 02c5c348..59ede14 100644
--- a/ui/ozone/platform/drm/BUILD.gn
+++ b/ui/ozone/platform/drm/BUILD.gn
@@ -24,7 +24,6 @@
     "common/scoped_drm_types.h",
     "gpu/crtc_controller.cc",
     "gpu/crtc_controller.h",
-    "gpu/display_change_observer.h",
     "gpu/drm_buffer.cc",
     "gpu/drm_buffer.h",
     "gpu/drm_console_buffer.cc",
@@ -115,11 +114,13 @@
     "//ui/display/util",
     "//ui/events",
     "//ui/events/devices",
+    "//ui/events/ozone:events_ozone",
     "//ui/events/ozone:events_ozone_evdev",
     "//ui/events/ozone:events_ozone_layout",
     "//ui/events/platform",
     "//ui/gfx",
     "//ui/gfx/geometry",
+    "//ui/ozone:ozone_base",
   ]
 
   configs += [ ":libdrm" ]
@@ -162,6 +163,7 @@
   ]
 
   deps = [
+    ":gbm",
     "//skia",
     "//testing/gtest",
     "//ui/gfx",
diff --git a/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc b/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
index 7226665..4a09465 100644
--- a/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
+++ b/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
@@ -5,7 +5,7 @@
 #include "ui/ozone/platform/drm/client_native_pixmap_factory_gbm.h"
 
 #include "ui/gfx/native_pixmap_handle_ozone.h"
-#include "ui/ozone/public/client_native_pixmap_factory.h"
+#include "ui/ozone/public/client_native_pixmap_factory.h"  // nogncheck
 
 #if defined(USE_VGEM_MAP)
 #include "ui/ozone/platform/drm/common/client_native_pixmap_vgem.h"
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index b18238e..34570f0 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -19,7 +19,7 @@
 #include "ui/ozone/platform/drm/gpu/gbm_device.h"
 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
 #include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h"
-#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_platform.h"  // nogncheck
 #include "ui/ozone/public/surface_factory_ozone.h"
 
 namespace {
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc
index 5bb3744..d8ee6a2c 100644
--- a/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -36,7 +36,7 @@
 #include "ui/ozone/public/cursor_factory_ozone.h"
 #include "ui/ozone/public/gpu_platform_support.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
-#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_platform.h"  // nogncheck
 #include "ui/ozone/public/ozone_switches.h"
 
 #if defined(USE_XKBCOMMON)
diff --git a/ui/ozone/platform/egltest/BUILD.gn b/ui/ozone/platform/egltest/BUILD.gn
index 9afd7f7..d6bca6c 100644
--- a/ui/ozone/platform/egltest/BUILD.gn
+++ b/ui/ozone/platform/egltest/BUILD.gn
@@ -18,11 +18,14 @@
   deps = [
     ":eglplatform_shim",
     "//base",
+    "//ui/events",
     "//ui/events/devices",
+    "//ui/events/ozone:events_ozone",
     "//ui/events/ozone:events_ozone_evdev",
     "//ui/events/ozone:events_ozone_layout",
     "//ui/events/platform",
     "//ui/gfx",
+    "//ui/ozone:ozone_base",
   ]
 }
 
diff --git a/ui/ozone/platform/egltest/ozone_platform_egltest.cc b/ui/ozone/platform/egltest/ozone_platform_egltest.cc
index 1bf2d2bb..4cc7f23 100644
--- a/ui/ozone/platform/egltest/ozone_platform_egltest.cc
+++ b/ui/ozone/platform/egltest/ozone_platform_egltest.cc
@@ -27,7 +27,7 @@
 #include "ui/ozone/public/cursor_factory_ozone.h"
 #include "ui/ozone/public/gpu_platform_support.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
-#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_platform.h"  // nogncheck
 #include "ui/ozone/public/ozone_switches.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 #include "ui/ozone/public/surface_ozone_egl.h"
diff --git a/ui/ozone/platform/headless/BUILD.gn b/ui/ozone/platform/headless/BUILD.gn
index e473a62..54ed505 100644
--- a/ui/ozone/platform/headless/BUILD.gn
+++ b/ui/ozone/platform/headless/BUILD.gn
@@ -20,8 +20,10 @@
     "//base",
     "//skia",
     "//ui/base",
+    "//ui/events",
     "//ui/events/ozone:events_ozone_layout",
     "//ui/events/platform",
     "//ui/gfx/geometry",
+    "//ui/ozone:ozone_base",
   ]
 }
diff --git a/ui/ozone/platform/headless/ozone_platform_headless.cc b/ui/ozone/platform/headless/ozone_platform_headless.cc
index 0fc1f19c..21f75dcb 100644
--- a/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -19,7 +19,7 @@
 #include "ui/ozone/public/gpu_platform_support.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_platform.h"  // nogncheck
 #include "ui/ozone/public/ozone_switches.h"
 #include "ui/ozone/public/system_input_injector.h"