diff --git a/DEPS b/DEPS
index a1a7c2c77..d7c09a1 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # 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': '4cba40134b7bb9cbf18e191c373986cb7373943c',
+  'v8_revision': '937b5e9fe4c6d49bec9189f6f0d84fbde2240ad4',
   # 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.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '49eb11f63eb4d552d634833a01d2710208ba0523',
+  'catapult_revision': 'f15e8a5937fde19035306787e7a3b5676eaa434e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/base/values.cc b/base/values.cc
index 765cf90..0bcddbdd 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -78,7 +78,7 @@
 // static
 std::unique_ptr<Value> Value::CreateWithCopiedBuffer(const char* buffer,
                                                      size_t size) {
-  return MakeUnique<Value>(std::vector<char>(buffer, buffer + size));
+  return MakeUnique<Value>(BlobStorage(buffer, buffer + size));
 }
 
 Value::Value(const Value& that) {
@@ -158,11 +158,11 @@
 
 Value::Value(StringPiece in_string) : Value(in_string.as_string()) {}
 
-Value::Value(const std::vector<char>& in_blob) : type_(Type::BINARY) {
+Value::Value(const BlobStorage& in_blob) : type_(Type::BINARY) {
   binary_value_.Init(in_blob);
 }
 
-Value::Value(std::vector<char>&& in_blob) noexcept : type_(Type::BINARY) {
+Value::Value(BlobStorage&& in_blob) noexcept : type_(Type::BINARY) {
   binary_value_.Init(std::move(in_blob));
 }
 
@@ -224,7 +224,7 @@
   return *string_value_;
 }
 
-const std::vector<char>& Value::GetBlob() const {
+const Value::BlobStorage& Value::GetBlob() const {
   CHECK(is_blob());
   return *binary_value_;
 }
@@ -1076,14 +1076,10 @@
   if (!in_value)
     return false;
 
-  if (index >= list_->size()) {
-    // Pad out any intermediate indexes with null settings
-    while (index > list_->size())
-      Append(MakeUnique<Value>());
-    Append(std::move(in_value));
-  } else {
-    (*list_)[index] = std::move(*in_value);
-  }
+  if (index >= list_->size())
+    list_->resize(index + 1);
+
+  (*list_)[index] = std::move(*in_value);
   return true;
 }
 
@@ -1234,37 +1230,35 @@
 }
 
 void ListValue::AppendBoolean(bool in_value) {
-  Append(MakeUnique<Value>(in_value));
+  list_->emplace_back(in_value);
 }
 
 void ListValue::AppendInteger(int in_value) {
-  Append(MakeUnique<Value>(in_value));
+  list_->emplace_back(in_value);
 }
 
 void ListValue::AppendDouble(double in_value) {
-  Append(MakeUnique<Value>(in_value));
+  list_->emplace_back(in_value);
 }
 
 void ListValue::AppendString(StringPiece in_value) {
-  Append(MakeUnique<Value>(in_value));
+  list_->emplace_back(in_value);
 }
 
 void ListValue::AppendString(const string16& in_value) {
-  Append(MakeUnique<Value>(in_value));
+  list_->emplace_back(in_value);
 }
 
 void ListValue::AppendStrings(const std::vector<std::string>& in_values) {
-  for (std::vector<std::string>::const_iterator it = in_values.begin();
-       it != in_values.end(); ++it) {
-    AppendString(*it);
-  }
+  list_->reserve(list_->size() + in_values.size());
+  for (const auto& in_value : in_values)
+    list_->emplace_back(in_value);
 }
 
 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
-  for (std::vector<string16>::const_iterator it = in_values.begin();
-       it != in_values.end(); ++it) {
-    AppendString(*it);
-  }
+  list_->reserve(list_->size() + in_values.size());
+  for (const auto& in_value : in_values)
+    list_->emplace_back(in_value);
 }
 
 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
diff --git a/base/values.h b/base/values.h
index 782a8ba..badf118 100644
--- a/base/values.h
+++ b/base/values.h
@@ -48,6 +48,7 @@
 // See the file-level comment above for more information.
 class BASE_EXPORT Value {
  public:
+  using BlobStorage = std::vector<char>;
   using DictStorage = base::flat_map<std::string, std::unique_ptr<Value>>;
   using ListStorage = std::vector<Value>;
 
@@ -66,7 +67,7 @@
   // For situations where you want to keep ownership of your buffer, this
   // factory method creates a new BinaryValue by copying the contents of the
   // buffer that's passed in.
-  // DEPRECATED, use MakeUnique<Value>(const std::vector<char>&) instead.
+  // DEPRECATED, use MakeUnique<Value>(const BlobStorage&) instead.
   // TODO(crbug.com/646113): Delete this and migrate callsites.
   static std::unique_ptr<Value> CreateWithCopiedBuffer(const char* buffer,
                                                        size_t size);
@@ -92,8 +93,8 @@
   explicit Value(const string16& in_string);
   explicit Value(StringPiece in_string);
 
-  explicit Value(const std::vector<char>& in_blob);
-  explicit Value(std::vector<char>&& in_blob) noexcept;
+  explicit Value(const BlobStorage& in_blob);
+  explicit Value(BlobStorage&& in_blob) noexcept;
 
   explicit Value(DictStorage&& in_dict) noexcept;
 
@@ -128,7 +129,7 @@
   int GetInt() const;
   double GetDouble() const;  // Implicitly converts from int if necessary.
   const std::string& GetString() const;
-  const std::vector<char>& GetBlob() const;
+  const BlobStorage& GetBlob() const;
 
   size_t GetSize() const;         // DEPRECATED, use GetBlob().size() instead.
   const char* GetBuffer() const;  // DEPRECATED, use GetBlob().data() instead.
@@ -193,7 +194,7 @@
     int int_value_;
     double double_value_;
     ManualConstructor<std::string> string_value_;
-    ManualConstructor<std::vector<char>> binary_value_;
+    ManualConstructor<BlobStorage> binary_value_;
     ManualConstructor<DictStorage> dict_;
     ManualConstructor<ListStorage> list_;
   };
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index ae9165806..97807ef 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -28,7 +28,7 @@
   static_assert(std::is_nothrow_constructible<Value, std::string&&>::value,
                 "IsNothrowMoveConstructibleFromString");
   static_assert(
-      std::is_nothrow_constructible<Value, std::vector<char>&&>::value,
+      std::is_nothrow_constructible<Value, Value::BlobStorage&&>::value,
       "IsNothrowMoveConstructibleFromBlob");
   static_assert(std::is_nothrow_move_assignable<Value>::value,
                 "IsNothrowMoveAssignable");
@@ -100,9 +100,10 @@
 }
 
 TEST(ValuesTest, ConstructBinary) {
-  Value value(std::vector<char>({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}));
+  Value value(Value::BlobStorage({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}));
   EXPECT_EQ(Value::Type::BINARY, value.type());
-  EXPECT_EQ(std::vector<char>({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}), value.GetBlob());
+  EXPECT_EQ(Value::BlobStorage({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}),
+            value.GetBlob());
 }
 
 TEST(ValuesTest, ConstructDict) {
@@ -180,7 +181,7 @@
 }
 
 TEST(ValuesTest, CopyBinary) {
-  Value value(std::vector<char>({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}));
+  Value value(Value::BlobStorage({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}));
   Value copied_value(value);
   EXPECT_EQ(value.type(), copied_value.type());
   EXPECT_EQ(value.GetBlob(), copied_value.GetBlob());
@@ -299,7 +300,7 @@
 }
 
 TEST(ValuesTest, MoveBinary) {
-  const std::vector<char> buffer = {0xF, 0x0, 0x0, 0xB, 0xA, 0x2};
+  const Value::BlobStorage buffer = {0xF, 0x0, 0x0, 0xB, 0xA, 0x2};
   Value value(buffer);
   Value moved_value(std::move(value));
   EXPECT_EQ(Value::Type::BINARY, moved_value.type());
@@ -449,7 +450,7 @@
   ASSERT_EQ(0U, binary->GetSize());
 
   // Test the common case of a non-empty buffer
-  std::vector<char> buffer(15);
+  Value::BlobStorage buffer(15);
   char* original_buffer = buffer.data();
   binary.reset(new Value(std::move(buffer)));
   ASSERT_TRUE(binary.get());
@@ -673,7 +674,7 @@
   Value* original_string16 = scoped_string16.get();
   original_dict.Set("string16", std::move(scoped_string16));
 
-  std::vector<char> original_buffer(42, '!');
+  Value::BlobStorage original_buffer(42, '!');
   std::unique_ptr<Value> scoped_binary(new Value(std::move(original_buffer)));
   Value* original_binary = scoped_binary.get();
   original_dict.Set("binary", std::move(scoped_binary));
@@ -917,8 +918,8 @@
   EXPECT_FALSE(string1 >= string2);
 
   // Test Binary Values.
-  Value binary1(std::vector<char>{0x01});
-  Value binary2(std::vector<char>{0x02});
+  Value binary1(Value::BlobStorage{0x01});
+  Value binary2(Value::BlobStorage{0x02});
   EXPECT_FALSE(binary1 == binary2);
   EXPECT_NE(binary1, binary2);
   EXPECT_LT(binary1, binary2);
@@ -1006,7 +1007,7 @@
   Value* original_string16 = scoped_string16.get();
   original_dict.Set("string16", std::move(scoped_string16));
 
-  std::vector<char> original_buffer(42, '!');
+  Value::BlobStorage original_buffer(42, '!');
   std::unique_ptr<Value> scoped_binary(new Value(std::move(original_buffer)));
   Value* original_binary = scoped_binary.get();
   original_dict.Set("binary", std::move(scoped_binary));
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index c62ac3a..f7918544 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -647,8 +647,6 @@
     "test/test_occlusion_tracker.h",
     "test/test_shared_bitmap_manager.cc",
     "test/test_shared_bitmap_manager.h",
-    "test/test_skcanvas.cc",
-    "test/test_skcanvas.h",
     "test/test_task_graph_runner.cc",
     "test/test_task_graph_runner.h",
     "test/test_texture.cc",
@@ -766,7 +764,6 @@
     "output/texture_mailbox_deleter_unittest.cc",
     "paint/discardable_image_map_unittest.cc",
     "paint/display_item_list_unittest.cc",
-    "paint/paint_op_buffer_unittest.cc",
     "quads/draw_polygon_unittest.cc",
     "quads/draw_quad_unittest.cc",
     "quads/nine_patch_generator_unittest.cc",
@@ -937,7 +934,6 @@
     "//cc/ipc",
     "//cc/ipc:interfaces",
     "//cc/paint",
-    "//cc/paint",
     "//cc/surfaces",
     "//cc/surfaces:surface_id",
     "//gpu",
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index 11f9fdac..3af5dee 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -32,19 +32,13 @@
     "paint_canvas.cc",
     "paint_canvas.h",
     "paint_export.h",
-    "paint_flags.cc",
     "paint_flags.h",
     "paint_image.cc",
     "paint_image.h",
-    "paint_op_buffer.cc",
-    "paint_op_buffer.h",
-    "paint_record.cc",
     "paint_record.h",
     "paint_recorder.cc",
     "paint_recorder.h",
     "paint_shader.h",
-    "record_paint_canvas.cc",
-    "record_paint_canvas.h",
     "skia_paint_canvas.cc",
     "skia_paint_canvas.h",
     "transform_display_item.cc",
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc
index c1b069548..8359948 100644
--- a/cc/paint/display_item_list.cc
+++ b/cc/paint/display_item_list.cc
@@ -100,13 +100,9 @@
       if (canvas->quickReject(item.picture->cullRect()))
         break;
 
-      // TODO(enne): Maybe the PaintRecord itself could know whether this
-      // was needed?  It's not clear whether these save/restore semantics
-      // that SkPicture handles during playback are things that should be
-      // kept around.
-      canvas->save();
+      // SkPicture always does a wrapping save/restore on the canvas, so it is
+      // not necessary here.
       item.picture->playback(canvas, callback);
-      canvas->restore();
       break;
     }
     case DisplayItem::FLOAT_CLIP: {
@@ -180,33 +176,6 @@
   canvas->restore();
 }
 
-// Atttempts to merge a CompositingDisplayItem and DrawingDisplayItem
-// into a single "draw with alpha".  This function returns true if
-// it was successful.  If false, then the caller is responsible for
-// drawing these items.  This is a DisplayItemList version of the
-// SkRecord optimization SkRecordNoopSaveLayerDrawRestores.
-static bool MergeAndDrawIfPossible(const CompositingDisplayItem& save_item,
-                                   const DrawingDisplayItem& draw_item,
-                                   SkCanvas* canvas) {
-  if (save_item.color_filter)
-    return false;
-  if (save_item.xfermode != SkBlendMode::kSrcOver)
-    return false;
-  // TODO(enne): I believe that lcd_text_requires_opaque_layer is not
-  // relevant here and that lcd text is preserved post merge, but I haven't
-  // tested that.
-  const PaintRecord* record = draw_item.picture.get();
-  if (record->approximateOpCount() != 1)
-    return false;
-
-  const PaintOp* op = record->GetFirstOp();
-  if (!op->IsDrawOp())
-    return false;
-
-  op->RasterWithAlpha(canvas, save_item.alpha);
-  return true;
-}
-
 void DisplayItemList::Raster(SkCanvas* canvas,
                              SkPicture::AbortCallback* callback) const {
   gfx::Rect canvas_playback_rect;
@@ -215,33 +184,14 @@
 
   std::vector<size_t> indices;
   rtree_.Search(canvas_playback_rect, &indices);
-  for (size_t i = 0; i < indices.size(); ++i) {
+  for (size_t index : indices) {
+    RasterItem(items_[index], canvas, callback);
+
     // We use a callback during solid color analysis on the compositor thread to
     // break out early. Since we're handling a sequence of pictures via rtree
     // query results ourselves, we have to respect the callback and early out.
     if (callback && callback->abort())
       break;
-
-    const DisplayItem& item = items_[indices[i]];
-    // Optimize empty begin/end compositing and merge begin/draw/end compositing
-    // where possible.
-    // TODO(enne): remove empty clips here too?
-    // TODO(enne): does this happen recursively? Or is this good enough?
-    if (i < indices.size() - 2 && item.type == DisplayItem::COMPOSITING) {
-      const DisplayItem& second = items_[indices[i + 1]];
-      const DisplayItem& third = items_[indices[i + 2]];
-      if (second.type == DisplayItem::DRAWING &&
-          third.type == DisplayItem::END_COMPOSITING) {
-        if (MergeAndDrawIfPossible(
-                static_cast<const CompositingDisplayItem&>(item),
-                static_cast<const DrawingDisplayItem&>(second), canvas)) {
-          i += 2;
-          continue;
-        }
-      }
-    }
-
-    RasterItem(item, canvas, callback);
   }
 }
 
diff --git a/cc/paint/display_item_list_unittest.cc b/cc/paint/display_item_list_unittest.cc
index b166229c6..f1b9e75 100644
--- a/cc/paint/display_item_list_unittest.cc
+++ b/cc/paint/display_item_list_unittest.cc
@@ -17,17 +17,16 @@
 #include "cc/paint/compositing_display_item.h"
 #include "cc/paint/drawing_display_item.h"
 #include "cc/paint/filter_display_item.h"
+
 #include "cc/paint/float_clip_display_item.h"
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_flags.h"
 #include "cc/paint/paint_record.h"
 #include "cc/paint/paint_recorder.h"
-#include "cc/paint/skia_paint_canvas.h"
 #include "cc/paint/transform_display_item.h"
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/pixel_test_utils.h"
 #include "cc/test/skia_common.h"
-#include "cc/test/test_skcanvas.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -81,19 +80,6 @@
   return recorder.finishRecordingAsPicture();
 }
 
-sk_sp<const PaintRecord> CreateRectPictureWithAlpha(const gfx::Rect& bounds,
-                                                    uint8_t alpha) {
-  PaintRecorder recorder;
-  PaintCanvas* canvas =
-      recorder.beginRecording(bounds.width(), bounds.height());
-  PaintFlags flags;
-  flags.setAlpha(alpha);
-  canvas->drawRect(
-      SkRect::MakeXYWH(bounds.x(), bounds.y(), bounds.width(), bounds.height()),
-      flags);
-  return recorder.finishRecordingAsPicture();
-}
-
 void AppendFirstSerializationTestPicture(scoped_refptr<DisplayItemList> list,
                                          const gfx::Size& layer_size) {
   gfx::PointF offset(2.f, 3.f);
@@ -718,110 +704,4 @@
   EXPECT_RECT_EQ(filter_bounds, list->VisualRectForTesting(3));
 }
 
-// Verify that raster time optimizations for compositing item / draw single op /
-// end compositing item can be collapsed together into a single draw op
-// with the opacity from the compositing item folded in.
-TEST(DisplayItemListTest, SaveDrawRestore) {
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendDrawingItem<DrawingDisplayItem>(
-      kVisualRect, CreateRectPictureWithAlpha(kVisualRect, 40));
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(0, canvas.save_count_);
-  EXPECT_EQ(0, canvas.restore_count_);
-  EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_);
-
-  float expected_alpha = 80 * 40 / 255.f;
-  EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f);
-}
-
-// Verify that compositing item / end compositing item is a noop.
-// Here we're testing that Skia does an optimization that skips
-// save/restore with nothing in between.  If skia stops doing this
-// then we should reimplement this optimization in display list raster.
-TEST(DisplayItemListTest, SaveRestoreNoops) {
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      255, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      255, SkBlendMode::kSrc, nullptr, nullptr, false);
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(0, canvas.save_count_);
-  EXPECT_EQ(0, canvas.restore_count_);
-}
-
-// The same as SaveDrawRestore, but with save flags that prevent the
-// optimization.
-TEST(DisplayItemListTest, SaveDrawRestoreFail_BadSaveFlags) {
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  // Use a blend mode that's not compatible with the SaveDrawRestore
-  // optimization.
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrc, nullptr, nullptr, false);
-  list->CreateAndAppendDrawingItem<DrawingDisplayItem>(
-      kVisualRect, CreateRectPictureWithAlpha(kVisualRect, 40));
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_);
-  EXPECT_LE(40, canvas.paint_.getAlpha());
-}
-
-// The same as SaveDrawRestore, but with too many ops in the PaintRecord.
-TEST(DisplayItemListTest, SaveDrawRestoreFail_TooManyOps) {
-  sk_sp<const PaintRecord> record;
-  {
-    PaintRecorder recorder;
-    PaintCanvas* canvas =
-        recorder.beginRecording(kVisualRect.width(), kVisualRect.height());
-    PaintFlags flags;
-    flags.setAlpha(40);
-    canvas->drawRect(gfx::RectToSkRect(kVisualRect), flags);
-    // Add an extra op here.
-    canvas->drawRect(gfx::RectToSkRect(kVisualRect), flags);
-    record = recorder.finishRecordingAsPicture();
-  }
-  EXPECT_GT(record->approximateOpCount(), 1);
-
-  auto list = make_scoped_refptr(new DisplayItemList);
-
-  list->CreateAndAppendPairedBeginItem<CompositingDisplayItem>(
-      80, SkBlendMode::kSrcOver, nullptr, nullptr, false);
-  list->CreateAndAppendDrawingItem<DrawingDisplayItem>(kVisualRect,
-                                                       std::move(record));
-  list->CreateAndAppendPairedEndItem<EndCompositingDisplayItem>();
-  list->Finalize();
-
-  SaveCountingCanvas canvas;
-  list->Raster(&canvas, nullptr);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(gfx::RectToSkRect(kVisualRect), canvas.draw_rect_);
-  EXPECT_LE(40, canvas.paint_.getAlpha());
-}
-
 }  // namespace cc
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h
index d45e84b..6b9a0df 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -11,24 +11,19 @@
 #include "build/build_config.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_image.h"
+#include "cc/paint/paint_record.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 
 namespace cc {
 
 class DisplayItemList;
 class PaintFlags;
-class PaintOpBuffer;
-
-using PaintRecord = PaintOpBuffer;
 
 class CC_PAINT_EXPORT PaintCanvas {
  public:
   virtual ~PaintCanvas() {}
 
   virtual SkMetaData& getMetaData() = 0;
-
-  // TODO(enne): this only appears to mostly be used to determine if this is
-  // recording or not, so could be simplified or removed.
   virtual SkImageInfo imageInfo() const = 0;
 
   // TODO(enne): It would be nice to get rid of flush() entirely, as it
@@ -47,7 +42,7 @@
                            int y) = 0;
   virtual int save() = 0;
   virtual int saveLayer(const SkRect* bounds, const PaintFlags* flags) = 0;
-  virtual int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) = 0;
+  virtual int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) = 0;
 
   virtual void restore() = 0;
   virtual int getSaveCount() const = 0;
@@ -98,8 +93,6 @@
   virtual bool getDeviceClipBounds(SkIRect* bounds) const = 0;
   virtual void drawColor(SkColor color, SkBlendMode mode) = 0;
   void drawColor(SkColor color) { drawColor(color, SkBlendMode::kSrcOver); }
-
-  // TODO(enne): This is a synonym for drawColor with kSrc.  Remove it.
   virtual void clear(SkColor color) = 0;
 
   virtual void drawLine(SkScalar x0,
diff --git a/cc/paint/paint_flags.cc b/cc/paint/paint_flags.cc
deleted file mode 100644
index e16a8bb..0000000
--- a/cc/paint/paint_flags.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/paint/paint_flags.h"
-
-namespace cc {
-
-bool PaintFlags::IsSimpleOpacity() const {
-  uint32_t color = getColor();
-  if (SK_ColorTRANSPARENT != SkColorSetA(color, SK_AlphaTRANSPARENT))
-    return false;
-  if (!isSrcOver())
-    return false;
-  if (getLooper())
-    return false;
-  if (getPathEffect())
-    return false;
-  if (getShader())
-    return false;
-  if (getMaskFilter())
-    return false;
-  if (getColorFilter())
-    return false;
-  if (getImageFilter())
-    return false;
-  return true;
-}
-
-bool PaintFlags::SupportsFoldingAlpha() const {
-  if (!isSrcOver())
-    return false;
-  if (getColorFilter())
-    return false;
-  if (getImageFilter())
-    return false;
-  if (getLooper())
-    return false;
-  return true;
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h
index 37b460d6..b7e96c6 100644
--- a/cc/paint/paint_flags.h
+++ b/cc/paint/paint_flags.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "cc/paint/paint_export.h"
+#include "cc/paint/paint_shader.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
 #include "third_party/skia/include/core/SkDrawLooper.h"
@@ -18,8 +19,6 @@
 
 namespace cc {
 
-using PaintShader = SkShader;
-
 class CC_PAINT_EXPORT PaintFlags {
  public:
   enum Style {
@@ -199,14 +198,6 @@
     return paint_.computeFastBounds(orig, storage);
   }
 
-  bool operator==(const PaintFlags& flags) { return flags.paint_ == paint_; }
-  bool operator!=(const PaintFlags& flags) { return flags.paint_ != paint_; }
-
-  // Returns true if this just represents an opacity blend when
-  // used as saveLayer flags.
-  bool IsSimpleOpacity() const;
-  bool SupportsFoldingAlpha() const;
-
  private:
   friend const SkPaint& ToSkPaint(const PaintFlags& flags);
   friend const SkPaint* ToSkPaint(const PaintFlags* flags);
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc
index d34d05d..70644ed 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -12,9 +12,6 @@
     : sk_image_(std::move(sk_image)),
       animation_type_(animation_type),
       completion_state_(completion_state) {}
-
-PaintImage::PaintImage(const PaintImage& image) = default;
-
 PaintImage::~PaintImage() = default;
 
 }  // namespace cc
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h
index c772316..0ed1edd 100644
--- a/cc/paint/paint_image.h
+++ b/cc/paint/paint_image.h
@@ -23,7 +23,6 @@
   PaintImage(sk_sp<const SkImage> sk_image,
              AnimationType animation_type,
              CompletionState completion_state);
-  PaintImage(const PaintImage& image);
   ~PaintImage();
 
   const sk_sp<const SkImage>& sk_image() const { return sk_image_; }
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
deleted file mode 100644
index fa62a41..0000000
--- a/cc/paint/paint_op_buffer.cc
+++ /dev/null
@@ -1,566 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/paint/paint_op_buffer.h"
-
-#include "cc/paint/display_item_list.h"
-#include "cc/paint/paint_record.h"
-#include "third_party/skia/include/core/SkAnnotation.h"
-
-namespace cc {
-
-#define TYPES(M)           \
-  M(AnnotateOp)            \
-  M(ClipPathOp)            \
-  M(ClipRectOp)            \
-  M(ClipRRectOp)           \
-  M(ConcatOp)              \
-  M(DrawArcOp)             \
-  M(DrawCircleOp)          \
-  M(DrawColorOp)           \
-  M(DrawDisplayItemListOp) \
-  M(DrawDRRectOp)          \
-  M(DrawImageOp)           \
-  M(DrawImageRectOp)       \
-  M(DrawIRectOp)           \
-  M(DrawLineOp)            \
-  M(DrawOvalOp)            \
-  M(DrawPathOp)            \
-  M(DrawPosTextOp)         \
-  M(DrawRecordOp)          \
-  M(DrawRectOp)            \
-  M(DrawRRectOp)           \
-  M(DrawTextOp)            \
-  M(DrawTextBlobOp)        \
-  M(NoopOp)                \
-  M(RestoreOp)             \
-  M(RotateOp)              \
-  M(SaveOp)                \
-  M(SaveLayerOp)           \
-  M(SaveLayerAlphaOp)      \
-  M(ScaleOp)               \
-  M(SetMatrixOp)           \
-  M(TranslateOp)
-
-// Helper template to share common code for RasterWithAlpha when paint ops
-// have or don't have PaintFlags.
-template <typename T, bool HasFlags>
-struct Rasterizer {
-  static void Raster(const T* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    // Paint ops with kHasPaintFlags need to declare RasterWithPaintFlags
-    // otherwise, the paint op needs its own Raster function.  Without its
-    // own, this becomes an infinite loop as PaintOp::Raster calls itself.
-    static_assert(
-        !std::is_same<decltype(&PaintOp::Raster), decltype(&T::Raster)>::value,
-        "No Raster function");
-
-    op->Raster(canvas);
-  }
-  static void RasterWithAlpha(const T* op, SkCanvas* canvas, uint8_t alpha) {
-    DCHECK(T::kIsDrawOp);
-    // TODO(enne): is it ok to just drop the bounds here?
-    canvas->saveLayerAlpha(nullptr, alpha);
-    op->Raster(canvas);
-    canvas->restore();
-  }
-};
-
-template <typename T>
-struct Rasterizer<T, true> {
-  static void Raster(const T* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    op->RasterWithFlags(canvas, op->flags);
-  }
-  static void RasterWithAlpha(const T* op, SkCanvas* canvas, uint8_t alpha) {
-    DCHECK(T::kIsDrawOp);
-    SkMatrix unused_matrix;
-    if (alpha == 255) {
-      Raster(op, canvas, unused_matrix);
-    } else if (op->flags.SupportsFoldingAlpha()) {
-      PaintFlags flags = op->flags;
-      flags.setAlpha(SkMulDiv255Round(flags.getAlpha(), alpha));
-      op->RasterWithFlags(canvas, flags);
-    } else {
-      canvas->saveLayerAlpha(nullptr, alpha);
-      op->RasterWithFlags(canvas, op->flags);
-      canvas->restore();
-    }
-  }
-};
-
-template <>
-struct Rasterizer<SetMatrixOp, false> {
-  static void Raster(const SetMatrixOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    op->Raster(canvas, original_ctm);
-  }
-  static void RasterWithAlpha(const SetMatrixOp* op,
-                              SkCanvas* canvas,
-                              uint8_t alpha) {
-    NOTREACHED();
-  }
-};
-
-template <>
-struct Rasterizer<DrawRecordOp, false> {
-  static void Raster(const DrawRecordOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    op->Raster(canvas);
-  }
-  static void RasterWithAlpha(const DrawRecordOp* op,
-                              SkCanvas* canvas,
-                              uint8_t alpha) {
-    // This "looking into records" optimization is done here instead of
-    // in the PaintOpBuffer::Raster function as DisplayItemList calls
-    // into RasterWithAlpha directly.
-    if (op->record->approximateOpCount() == 1) {
-      PaintOp* single_op = op->record->GetFirstOp();
-      // RasterWithAlpha only supported for draw ops.
-      if (single_op->IsDrawOp()) {
-        single_op->RasterWithAlpha(canvas, alpha);
-        return;
-      }
-    }
-
-    canvas->saveLayerAlpha(nullptr, alpha);
-    op->Raster(canvas);
-    canvas->restore();
-  }
-};
-
-// TODO(enne): partially specialize RasterWithAlpha for draw color?
-
-static constexpr size_t kNumOpTypes =
-    static_cast<size_t>(PaintOpType::LastPaintOpType) + 1;
-
-// Verify that every op is in the TYPES macro.
-#define M(T) +1
-static_assert(kNumOpTypes == TYPES(M), "Missing op in list");
-#undef M
-
-using RasterFunction = void (*)(const PaintOp* op,
-                                SkCanvas* canvas,
-                                const SkMatrix& original_ctm);
-#define M(T)                                                              \
-  [](const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm) { \
-    Rasterizer<T, T::kHasPaintFlags>::Raster(static_cast<const T*>(op),   \
-                                             canvas, original_ctm);       \
-  },
-static const RasterFunction g_raster_functions[kNumOpTypes] = {TYPES(M)};
-#undef M
-
-using RasterAlphaFunction = void (*)(const PaintOp* op,
-                                     SkCanvas* canvas,
-                                     uint8_t alpha);
-#define M(T) \
-  T::kIsDrawOp ? \
-  [](const PaintOp* op, SkCanvas* canvas, uint8_t alpha) { \
-    Rasterizer<T, T::kHasPaintFlags>::RasterWithAlpha( \
-        static_cast<const T*>(op), canvas, alpha); \
-  } : static_cast<RasterAlphaFunction>(nullptr),
-static const RasterAlphaFunction g_raster_alpha_functions[kNumOpTypes] = {
-    TYPES(M)};
-#undef M
-
-// Most state ops (matrix, clip, save, restore) have a trivial destructor.
-// TODO(enne): evaluate if we need the nullptr optimization or if
-// we even need to differentiate trivial destructors here.
-using VoidFunction = void (*)(PaintOp* op);
-#define M(T)                                           \
-  !std::is_trivially_destructible<T>::value            \
-      ? [](PaintOp* op) { static_cast<T*>(op)->~T(); } \
-      : static_cast<VoidFunction>(nullptr),
-static const VoidFunction g_destructor_functions[kNumOpTypes] = {TYPES(M)};
-#undef M
-
-#define M(T) T::kIsDrawOp,
-static bool g_is_draw_op[kNumOpTypes] = {TYPES(M)};
-#undef M
-
-#define M(T)                                         \
-  static_assert(sizeof(T) <= sizeof(LargestPaintOp), \
-                #T " must be no bigger than LargestPaintOp");
-TYPES(M);
-#undef M
-
-#undef TYPES
-
-SkRect PaintOp::kUnsetRect = {SK_ScalarInfinity, 0, 0, 0};
-
-void AnnotateOp::Raster(SkCanvas* canvas) const {
-  switch (annotation_type) {
-    case PaintCanvas::AnnotationType::URL:
-      SkAnnotateRectWithURL(canvas, rect, data.get());
-      break;
-    case PaintCanvas::AnnotationType::LINK_TO_DESTINATION:
-      SkAnnotateLinkToDestination(canvas, rect, data.get());
-      break;
-    case PaintCanvas::AnnotationType::NAMED_DESTINATION: {
-      SkPoint point = SkPoint::Make(rect.x(), rect.y());
-      SkAnnotateNamedDestination(canvas, point, data.get());
-      break;
-    }
-  }
-}
-
-void ClipPathOp::Raster(SkCanvas* canvas) const {
-  canvas->clipPath(path, op, antialias);
-}
-
-void ClipRectOp::Raster(SkCanvas* canvas) const {
-  canvas->clipRect(rect, op, antialias);
-}
-
-void ClipRRectOp::Raster(SkCanvas* canvas) const {
-  canvas->clipRRect(rrect, op, antialias);
-}
-
-void ConcatOp::Raster(SkCanvas* canvas) const {
-  canvas->concat(matrix);
-}
-
-void DrawArcOp::RasterWithFlags(SkCanvas* canvas,
-                                const PaintFlags& flags) const {
-  canvas->drawArc(oval, start_angle, sweep_angle, use_center, ToSkPaint(flags));
-}
-
-void DrawCircleOp::RasterWithFlags(SkCanvas* canvas,
-                                   const PaintFlags& flags) const {
-  canvas->drawCircle(cx, cy, radius, ToSkPaint(flags));
-}
-
-void DrawColorOp::Raster(SkCanvas* canvas) const {
-  canvas->drawColor(color, mode);
-}
-
-void DrawDisplayItemListOp::Raster(SkCanvas* canvas) const {
-  list->Raster(canvas, nullptr);
-}
-
-void DrawDRRectOp::RasterWithFlags(SkCanvas* canvas,
-                                   const PaintFlags& flags) const {
-  canvas->drawDRRect(outer, inner, ToSkPaint(flags));
-}
-
-void DrawImageOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  canvas->drawImage(image.sk_image().get(), left, top, ToSkPaint(&flags));
-}
-
-void DrawImageRectOp::RasterWithFlags(SkCanvas* canvas,
-                                      const PaintFlags& flags) const {
-  // TODO(enne): Probably PaintCanvas should just use the skia enum directly.
-  SkCanvas::SrcRectConstraint skconstraint =
-      static_cast<SkCanvas::SrcRectConstraint>(constraint);
-  canvas->drawImageRect(image.sk_image().get(), src, dst, ToSkPaint(&flags),
-                        skconstraint);
-}
-
-void DrawIRectOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  canvas->drawIRect(rect, ToSkPaint(flags));
-}
-
-void DrawLineOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawLine(x0, y0, x1, y1, ToSkPaint(flags));
-}
-
-void DrawOvalOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawOval(oval, ToSkPaint(flags));
-}
-
-void DrawPathOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawPath(path, ToSkPaint(flags));
-}
-
-void DrawPosTextOp::RasterWithFlags(SkCanvas* canvas,
-                                    const PaintFlags& flags) const {
-  canvas->drawPosText(paint_op_data(this), bytes, paint_op_array<SkPoint>(this),
-                      ToSkPaint(flags));
-}
-
-void DrawRecordOp::Raster(SkCanvas* canvas) const {
-  record->playback(canvas);
-}
-
-void DrawRectOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawRect(rect, ToSkPaint(flags));
-}
-
-void DrawRRectOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  canvas->drawRRect(rrect, ToSkPaint(flags));
-}
-
-void DrawTextOp::RasterWithFlags(SkCanvas* canvas,
-                                 const PaintFlags& flags) const {
-  canvas->drawText(paint_op_data(this), bytes, x, y, ToSkPaint(flags));
-}
-
-void DrawTextBlobOp::RasterWithFlags(SkCanvas* canvas,
-                                     const PaintFlags& flags) const {
-  canvas->drawTextBlob(blob.get(), x, y, ToSkPaint(flags));
-}
-
-void RestoreOp::Raster(SkCanvas* canvas) const {
-  canvas->restore();
-}
-
-void RotateOp::Raster(SkCanvas* canvas) const {
-  canvas->rotate(degrees);
-}
-
-void SaveOp::Raster(SkCanvas* canvas) const {
-  canvas->save();
-}
-
-void SaveLayerOp::RasterWithFlags(SkCanvas* canvas,
-                                  const PaintFlags& flags) const {
-  // See PaintOp::kUnsetRect
-  bool unset = bounds.left() == SK_ScalarInfinity;
-
-  canvas->saveLayer(unset ? nullptr : &bounds, ToSkPaint(&flags));
-}
-
-void SaveLayerAlphaOp::Raster(SkCanvas* canvas) const {
-  // See PaintOp::kUnsetRect
-  bool unset = bounds.left() == SK_ScalarInfinity;
-  canvas->saveLayerAlpha(unset ? nullptr : &bounds, alpha);
-}
-
-void ScaleOp::Raster(SkCanvas* canvas) const {
-  canvas->scale(sx, sy);
-}
-
-void SetMatrixOp::Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const {
-  canvas->setMatrix(SkMatrix::Concat(original_ctm, matrix));
-}
-
-void TranslateOp::Raster(SkCanvas* canvas) const {
-  canvas->translate(dx, dy);
-}
-
-bool PaintOp::IsDrawOp() const {
-  return g_is_draw_op[type];
-}
-
-void PaintOp::Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const {
-  g_raster_functions[type](this, canvas, original_ctm);
-}
-
-void PaintOp::RasterWithAlpha(SkCanvas* canvas, uint8_t alpha) const {
-  g_raster_alpha_functions[type](this, canvas, alpha);
-}
-
-int ClipPathOp::CountSlowPaths() const {
-  return antialias && !path.isConvex() ? 1 : 0;
-}
-
-int DrawLineOp::CountSlowPaths() const {
-  if (const SkPathEffect* effect = flags.getPathEffect()) {
-    SkPathEffect::DashInfo info;
-    SkPathEffect::DashType dashType = effect->asADash(&info);
-    if (flags.getStrokeCap() != PaintFlags::kRound_Cap &&
-        dashType == SkPathEffect::kDash_DashType && info.fCount == 2) {
-      // The PaintFlags will count this as 1, so uncount that here as
-      // this kind of line is special cased and not slow.
-      return -1;
-    }
-  }
-  return 0;
-}
-
-int DrawPathOp::CountSlowPaths() const {
-  // This logic is copied from SkPathCounter instead of attempting to expose
-  // that from Skia.
-  if (!flags.isAntiAlias() || path.isConvex())
-    return 0;
-
-  PaintFlags::Style paintStyle = flags.getStyle();
-  const SkRect& pathBounds = path.getBounds();
-  if (paintStyle == PaintFlags::kStroke_Style && flags.getStrokeWidth() == 0) {
-    // AA hairline concave path is not slow.
-    return 0;
-  } else if (paintStyle == PaintFlags::kFill_Style &&
-             pathBounds.width() < 64.f && pathBounds.height() < 64.f &&
-             !path.isVolatile()) {
-    // AADF eligible concave path is not slow.
-    return 0;
-  } else {
-    return 1;
-  }
-}
-
-AnnotateOp::AnnotateOp(PaintCanvas::AnnotationType annotation_type,
-                       const SkRect& rect,
-                       sk_sp<SkData> data)
-    : annotation_type(annotation_type), rect(rect), data(std::move(data)) {}
-
-AnnotateOp::~AnnotateOp() = default;
-
-DrawDisplayItemListOp::DrawDisplayItemListOp(
-    scoped_refptr<DisplayItemList> list)
-    : list(list) {}
-
-size_t DrawDisplayItemListOp::AdditionalBytesUsed() const {
-  return list->ApproximateMemoryUsage();
-}
-
-DrawDisplayItemListOp::DrawDisplayItemListOp(const DrawDisplayItemListOp& op) =
-    default;
-
-DrawDisplayItemListOp& DrawDisplayItemListOp::operator=(
-    const DrawDisplayItemListOp& op) = default;
-
-DrawDisplayItemListOp::~DrawDisplayItemListOp() = default;
-
-DrawImageOp::DrawImageOp(const PaintImage& image,
-                         SkScalar left,
-                         SkScalar top,
-                         const PaintFlags* flags)
-    : image(image),
-      left(left),
-      top(top),
-      flags(flags ? *flags : PaintFlags()) {}
-
-DrawImageOp::~DrawImageOp() = default;
-
-DrawImageRectOp::DrawImageRectOp(const PaintImage& image,
-                                 const SkRect& src,
-                                 const SkRect& dst,
-                                 const PaintFlags* flags,
-                                 PaintCanvas::SrcRectConstraint constraint)
-    : image(image),
-      flags(flags ? *flags : PaintFlags()),
-      src(src),
-      dst(dst),
-      constraint(constraint) {}
-
-DrawImageRectOp::~DrawImageRectOp() = default;
-
-DrawPosTextOp::DrawPosTextOp(size_t bytes,
-                             size_t count,
-                             const PaintFlags& flags)
-    : PaintOpWithDataArray(bytes, count), flags(flags) {}
-
-DrawPosTextOp::~DrawPosTextOp() = default;
-
-DrawRecordOp::DrawRecordOp(sk_sp<const PaintRecord> record)
-    : record(std::move(record)) {}
-
-DrawRecordOp::~DrawRecordOp() = default;
-
-size_t DrawRecordOp::AdditionalBytesUsed() const {
-  return record->approximateBytesUsed();
-}
-
-DrawTextBlobOp::DrawTextBlobOp(sk_sp<SkTextBlob> blob,
-                               SkScalar x,
-                               SkScalar y,
-                               const PaintFlags& flags)
-    : blob(std::move(blob)), x(x), y(y), flags(flags) {}
-
-DrawTextBlobOp::~DrawTextBlobOp() = default;
-
-PaintOpBuffer::PaintOpBuffer() : cull_rect_(SkRect::MakeEmpty()) {}
-
-PaintOpBuffer::PaintOpBuffer(const SkRect& cull_rect) : cull_rect_(cull_rect) {}
-
-PaintOpBuffer::~PaintOpBuffer() {
-  Reset();
-}
-
-void PaintOpBuffer::Reset() {
-  for (auto* op : Iterator(this)) {
-    auto func = g_destructor_functions[op->type];
-    if (func)
-      func(op);
-  }
-
-  // Leave data_ allocated, reserved_ unchanged.
-  used_ = 0;
-  op_count_ = 0;
-  num_slow_paths_ = 0;
-}
-
-void PaintOpBuffer::playback(SkCanvas* canvas) const {
-  // TODO(enne): a PaintRecord that contains a SetMatrix assumes that the
-  // SetMatrix is local to that PaintRecord itself.  Said differently, if you
-  // translate(x, y), then draw a paint record with a SetMatrix(identity),
-  // the translation should be preserved instead of clobbering the top level
-  // transform.  This could probably be done more efficiently.
-  SkMatrix original = canvas->getTotalMatrix();
-
-  for (Iterator iter(this); iter; ++iter) {
-    // Optimize out save/restores or save/draw/restore that can be a single
-    // draw.  See also: similar code in SkRecordOpts and cc's DisplayItemList.
-    // TODO(enne): consider making this recursive?
-    const PaintOp* op = *iter;
-    if (op->GetType() == PaintOpType::SaveLayerAlpha) {
-      const PaintOp* second = iter.peek1();
-      if (second) {
-        if (second->GetType() == PaintOpType::Restore) {
-          ++iter;
-          continue;
-        }
-        if (second->IsDrawOp()) {
-          const PaintOp* third = iter.peek2();
-          if (third && third->GetType() == PaintOpType::Restore) {
-            const SaveLayerAlphaOp* save_op =
-                static_cast<const SaveLayerAlphaOp*>(op);
-            second->RasterWithAlpha(canvas, save_op->alpha);
-            ++iter;
-            ++iter;
-            continue;
-          }
-        }
-      }
-    }
-    // TODO(enne): skip SaveLayer followed by restore with nothing in
-    // between, however SaveLayer with image filters on it (or maybe
-    // other PaintFlags options) are not a noop.  Figure out what these
-    // are so we can skip them correctly.
-
-    op->Raster(canvas, original);
-  }
-}
-
-void PaintOpBuffer::playback(SkCanvas* canvas,
-                             SkPicture::AbortCallback* callback) const {
-  // The abort callback is only used for analysis, in general, so
-  // this playback code can be more straightforward and not do the
-  // optimizations in the other function.
-  if (!callback) {
-    playback(canvas);
-    return;
-  }
-
-  SkMatrix original = canvas->getTotalMatrix();
-
-  // TODO(enne): ideally callers would just iterate themselves and we
-  // can remove the entire notion of an abort callback.
-  for (auto* op : Iterator(this)) {
-    op->Raster(canvas, original);
-    if (callback && callback->abort())
-      return;
-  }
-}
-
-void PaintOpBuffer::ShrinkToFit() {
-  if (!used_ || used_ == reserved_)
-    return;
-  data_.realloc(used_);
-  reserved_ = used_;
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
deleted file mode 100644
index 333a290..0000000
--- a/cc/paint/paint_op_buffer.h
+++ /dev/null
@@ -1,787 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_PAINT_PAINT_OP_BUFFER_H_
-#define CC_PAINT_PAINT_OP_BUFFER_H_
-
-#include <stdint.h>
-
-#include "base/logging.h"
-#include "cc/paint/paint_canvas.h"
-#include "cc/paint/paint_export.h"
-#include "cc/paint/paint_flags.h"
-#include "third_party/skia/include/core/SkPicture.h"
-#include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/core/SkTextBlob.h"
-
-// PaintOpBuffer is a reimplementation of SkLiteDL.
-// See: third_party/skia/src/core/SkLiteDL.h.
-
-namespace cc {
-
-class DisplayItemList;
-
-class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix {
- public:
-  explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) {
-    (void)getType();
-  }
-};
-
-class CC_PAINT_EXPORT ThreadsafePath : public SkPath {
- public:
-  explicit ThreadsafePath(const SkPath& path) : SkPath(path) {
-    updateBoundsCache();
-  }
-};
-
-enum class PaintOpType : uint8_t {
-  Annotate,
-  ClipPath,
-  ClipRect,
-  ClipRRect,
-  Concat,
-  DrawArc,
-  DrawCircle,
-  DrawColor,
-  DrawDisplayItemList,
-  DrawDRRect,
-  DrawImage,
-  DrawImageRect,
-  DrawIRect,
-  DrawLine,
-  DrawOval,
-  DrawPath,
-  DrawPosText,
-  DrawRecord,
-  DrawRect,
-  DrawRRect,
-  DrawText,
-  DrawTextBlob,
-  Noop,
-  Restore,
-  Rotate,
-  Save,
-  SaveLayer,
-  SaveLayerAlpha,
-  Scale,
-  SetMatrix,
-  Translate,
-  LastPaintOpType = Translate,
-};
-
-struct CC_PAINT_EXPORT PaintOp {
-  uint32_t type : 8;
-  uint32_t skip : 24;
-
-  PaintOpType GetType() const { return static_cast<PaintOpType>(type); }
-
-  void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
-  bool IsDrawOp() const;
-
-  // Only valid for draw ops.
-  void RasterWithAlpha(SkCanvas* canvas, uint8_t alpha) const;
-
-  int CountSlowPaths() const { return 0; }
-
-  // Returns the number of bytes used by this op in referenced sub records
-  // and display lists.  This doesn't count other objects like paths or blobs.
-  size_t AdditionalBytesUsed() const { return 0; }
-
-  static constexpr bool kIsDrawOp = false;
-  // If an op has |kHasPaintFlags| set to true, it must:
-  // (1) Provide a PaintFlags member called |flags|
-  // (2) Provide a RasterWithFlags function instead of a Raster function.
-  static constexpr bool kHasPaintFlags = false;
-  static SkRect kUnsetRect;
-};
-
-struct CC_PAINT_EXPORT PaintOpWithData : PaintOp {
-  // Having data is just a helper for ops that have a varying amount of data and
-  // want a way to store that inline.  This is for ops that pass in a
-  // void* and a length.
-  explicit PaintOpWithData(size_t bytes) : bytes(bytes) {}
-
-  // Get data out by calling paint_op_data.  This can't be part of the class
-  // because it needs to know the size of the derived type.
-  size_t bytes;
-};
-
-template <typename T>
-const void* paint_op_data(const T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithData>::value,
-                "T is not a PaintOpWithData");
-  // Arbitrary data for a PaintOp is stored after the PaintOp itself
-  // in the PaintOpBuffer.  Therefore, to access this data, it's
-  // pointer math to increment past the size of T.  Accessing the
-  // next op in the buffer is ((char*)op) + op->skip, with the data
-  // fitting between.
-  return op + 1;
-}
-
-template <typename T>
-void* paint_op_data(T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithData>::value,
-                "T is not a PaintOpWithData");
-  return op + 1;
-}
-
-struct CC_PAINT_EXPORT PaintOpWithDataArrayBase : PaintOpWithData {
-  // Helper class for static asserts in push functions.
-  using PaintOpWithData::PaintOpWithData;
-};
-
-template <typename T>
-struct CC_PAINT_EXPORT PaintOpWithDataArray : PaintOpWithDataArrayBase {
-  // Paint op that has a T[count] and a char[bytes].
-  PaintOpWithDataArray(size_t bytes, size_t count)
-      : PaintOpWithDataArrayBase(bytes), count(count) {}
-  // Use paint_op_array to get array data.
-
-  size_t count;
-};
-
-template <typename M, typename T>
-const M* paint_op_array(const T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value,
-                "T is not a PaintOpWithDataArray");
-  // See comment in paint_op_data.  Array data is stored after
-  // any void* data.  Memory layout here is: |op|data|array data|next op|
-  return SkTAddOffset<const M>(op + 1, op->bytes);
-}
-template <typename M, typename T>
-M* paint_op_array(T* op) {
-  static_assert(std::is_convertible<T, PaintOpWithDataArrayBase>::value,
-                "T is not a PaintOpWithDataArray");
-  return SkTAddOffset<M>(op + 1, op->bytes);
-}
-
-struct CC_PAINT_EXPORT AnnotateOp final : PaintOp {
-  enum class AnnotationType {
-    URL,
-    LinkToDestination,
-    NamedDestination,
-  };
-
-  static constexpr PaintOpType kType = PaintOpType::Annotate;
-  AnnotateOp(PaintCanvas::AnnotationType annotation_type,
-             const SkRect& rect,
-             sk_sp<SkData> data);
-  ~AnnotateOp();
-  void Raster(SkCanvas* canvas) const;
-
-  PaintCanvas::AnnotationType annotation_type;
-  SkRect rect;
-  sk_sp<SkData> data;
-};
-
-struct CC_PAINT_EXPORT ClipPathOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::ClipPath;
-  ClipPathOp(SkPath path, SkClipOp op, bool antialias)
-      : path(path), op(op), antialias(antialias) {}
-  void Raster(SkCanvas* canvas) const;
-  int CountSlowPaths() const;
-
-  ThreadsafePath path;
-  SkClipOp op;
-  bool antialias;
-};
-
-struct CC_PAINT_EXPORT ClipRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::ClipRect;
-  ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias)
-      : rect(rect), op(op), antialias(antialias) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkRect rect;
-  SkClipOp op;
-  bool antialias;
-};
-
-struct CC_PAINT_EXPORT ClipRRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::ClipRRect;
-  ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias)
-      : rrect(rrect), op(op), antialias(antialias) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkRRect rrect;
-  SkClipOp op;
-  bool antialias;
-};
-
-struct CC_PAINT_EXPORT ConcatOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Concat;
-  explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {}
-  void Raster(SkCanvas* canvas) const;
-
-  ThreadsafeMatrix matrix;
-};
-
-struct CC_PAINT_EXPORT DrawArcOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawArc;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawArcOp(const SkRect& oval,
-            SkScalar start_angle,
-            SkScalar sweep_angle,
-            bool use_center,
-            const PaintFlags& flags)
-      : oval(oval),
-        start_angle(start_angle),
-        sweep_angle(sweep_angle),
-        use_center(use_center),
-        flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect oval;
-  SkScalar start_angle;
-  SkScalar sweep_angle;
-  bool use_center;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawCircleOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawCircle;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawCircleOp(SkScalar cx,
-               SkScalar cy,
-               SkScalar radius,
-               const PaintFlags& flags)
-      : cx(cx), cy(cy), radius(radius), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkScalar cx;
-  SkScalar cy;
-  SkScalar radius;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawColorOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawColor;
-  static constexpr bool kIsDrawOp = true;
-  DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkColor color;
-  SkBlendMode mode;
-};
-
-struct CC_PAINT_EXPORT DrawDisplayItemListOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawDisplayItemList;
-  static constexpr bool kIsDrawOp = true;
-  explicit DrawDisplayItemListOp(scoped_refptr<DisplayItemList> list);
-  // Windows wants to generate these when types are exported, so
-  // provide them here explicitly so that DisplayItemList doesn't have
-  // to be defined in this header.
-  DrawDisplayItemListOp(const DrawDisplayItemListOp& op);
-  DrawDisplayItemListOp& operator=(const DrawDisplayItemListOp& op);
-  ~DrawDisplayItemListOp();
-  void Raster(SkCanvas* canvas) const;
-  size_t AdditionalBytesUsed() const;
-  // TODO(enne): DisplayItemList should know number of slow paths.
-
-  scoped_refptr<DisplayItemList> list;
-};
-
-struct CC_PAINT_EXPORT DrawDRRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawDRRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawDRRectOp(const SkRRect& outer,
-               const SkRRect& inner,
-               const PaintFlags& flags)
-      : outer(outer), inner(inner), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRRect outer;
-  SkRRect inner;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawImageOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawImage;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawImageOp(const PaintImage& image,
-              SkScalar left,
-              SkScalar top,
-              const PaintFlags* flags);
-  ~DrawImageOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  PaintImage image;
-  SkScalar left;
-  SkScalar top;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawImageRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawImageRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawImageRectOp(const PaintImage& image,
-                  const SkRect& src,
-                  const SkRect& dst,
-                  const PaintFlags* flags,
-                  PaintCanvas::SrcRectConstraint constraint);
-  ~DrawImageRectOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  PaintImage image;
-  PaintFlags flags;
-  SkRect src;
-  SkRect dst;
-  PaintCanvas::SrcRectConstraint constraint;
-};
-
-struct CC_PAINT_EXPORT DrawIRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawIRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawIRectOp(const SkIRect& rect, const PaintFlags& flags)
-      : rect(rect), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkIRect rect;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawLineOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawLine;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawLineOp(SkScalar x0,
-             SkScalar y0,
-             SkScalar x1,
-             SkScalar y1,
-             const PaintFlags& flags)
-      : x0(x0), y0(y0), x1(x1), y1(y1), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-  int CountSlowPaths() const;
-
-  SkScalar x0;
-  SkScalar y0;
-  SkScalar x1;
-  SkScalar y1;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawOvalOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawOval;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawOvalOp(const SkRect& oval, const PaintFlags& flags)
-      : oval(oval), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect oval;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawPathOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawPath;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawPathOp(const SkPath& path, const PaintFlags& flags)
-      : path(path), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-  int CountSlowPaths() const;
-
-  ThreadsafePath path;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawPosTextOp final : PaintOpWithDataArray<SkPoint> {
-  static constexpr PaintOpType kType = PaintOpType::DrawPosText;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags);
-  ~DrawPosTextOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawRecordOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawRecord;
-  static constexpr bool kIsDrawOp = true;
-  explicit DrawRecordOp(sk_sp<const PaintRecord> record);
-  ~DrawRecordOp();
-  void Raster(SkCanvas* canvas) const;
-  size_t AdditionalBytesUsed() const;
-
-  sk_sp<const PaintRecord> record;
-};
-
-struct CC_PAINT_EXPORT DrawRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawRectOp(const SkRect& rect, const PaintFlags& flags)
-      : rect(rect), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect rect;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawRRectOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawRRect;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags)
-      : rrect(rrect), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRRect rrect;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawTextOp final : PaintOpWithData {
-  static constexpr PaintOpType kType = PaintOpType::DrawText;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags)
-      : PaintOpWithData(bytes), x(x), y(y), flags(flags) {}
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkScalar x;
-  SkScalar y;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT DrawTextBlobOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::DrawTextBlob;
-  static constexpr bool kIsDrawOp = true;
-  static constexpr bool kHasPaintFlags = true;
-  DrawTextBlobOp(sk_sp<SkTextBlob> blob,
-                 SkScalar x,
-                 SkScalar y,
-                 const PaintFlags& flags);
-  ~DrawTextBlobOp();
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  sk_sp<SkTextBlob> blob;
-  SkScalar x;
-  SkScalar y;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT NoopOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Noop;
-  void Raster(SkCanvas* canvas) const {}
-};
-
-struct CC_PAINT_EXPORT RestoreOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Restore;
-  void Raster(SkCanvas* canvas) const;
-};
-
-struct CC_PAINT_EXPORT RotateOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Rotate;
-  explicit RotateOp(SkScalar degrees) : degrees(degrees) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkScalar degrees;
-};
-
-struct CC_PAINT_EXPORT SaveOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Save;
-  void Raster(SkCanvas* canvas) const;
-};
-
-struct CC_PAINT_EXPORT SaveLayerOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::SaveLayer;
-  static constexpr bool kHasPaintFlags = true;
-  SaveLayerOp(const SkRect* bounds, const PaintFlags* flags)
-      : bounds(bounds ? *bounds : kUnsetRect) {
-    if (flags)
-      this->flags = *flags;
-  }
-  void RasterWithFlags(SkCanvas* canvas, const PaintFlags& flags) const;
-
-  SkRect bounds;
-  PaintFlags flags;
-};
-
-struct CC_PAINT_EXPORT SaveLayerAlphaOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha;
-  SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha)
-      : bounds(bounds ? *bounds : kUnsetRect), alpha(alpha) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkRect bounds;
-  uint8_t alpha;
-};
-
-struct CC_PAINT_EXPORT ScaleOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Scale;
-  ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkScalar sx;
-  SkScalar sy;
-};
-
-struct CC_PAINT_EXPORT SetMatrixOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::SetMatrix;
-  explicit SetMatrixOp(const SkMatrix& matrix) : matrix(matrix) {}
-  // This is the only op that needs the original ctm of the SkCanvas
-  // used for raster (since SetMatrix is relative to the recording origin and
-  // shouldn't clobber the SkCanvas raster origin).
-  //
-  // TODO(enne): Find some cleaner way to do this, possibly by making
-  // all SetMatrix calls Concat??
-  void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
-
-  ThreadsafeMatrix matrix;
-};
-
-struct CC_PAINT_EXPORT TranslateOp final : PaintOp {
-  static constexpr PaintOpType kType = PaintOpType::Translate;
-  TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
-  void Raster(SkCanvas* canvas) const;
-
-  SkScalar dx;
-  SkScalar dy;
-};
-
-using LargestPaintOp = DrawDRRectOp;
-
-class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
- public:
-  enum { kInitialBufferSize = 4096 };
-
-  PaintOpBuffer();
-  explicit PaintOpBuffer(const SkRect& cull_rect);
-  ~PaintOpBuffer() override;
-
-  void Reset();
-
-  void playback(SkCanvas* canvas) const;
-  void playback(SkCanvas* canvas, SkPicture::AbortCallback* callback) const;
-
-  // TODO(enne): These are no longer approximate.  Rename these.
-  int approximateOpCount() const { return op_count_; }
-  size_t approximateBytesUsed() const {
-    return sizeof(*this) + reserved_ + subrecord_bytes_used_;
-  }
-  int numSlowPaths() const { return num_slow_paths_; }
-
-  // Resize the PaintOpBuffer to exactly fit the current amount of used space.
-  void ShrinkToFit();
-
-  const SkRect& cullRect() const { return cull_rect_; }
-
-  PaintOp* GetFirstOp() const {
-    return reinterpret_cast<PaintOp*>(const_cast<char*>(&first_op_[0]));
-  }
-
-  template <typename T, typename... Args>
-  void push(Args&&... args) {
-    static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp.");
-    static_assert(!std::is_convertible<T, PaintOpWithData>::value,
-                  "Type needs to use push_with_data");
-    push_internal<T>(0, std::forward<Args>(args)...);
-  }
-
-  template <typename T, typename... Args>
-  void push_with_data(const void* data, size_t bytes, Args&&... args) {
-    static_assert(std::is_convertible<T, PaintOpWithData>::value,
-                  "T is not a PaintOpWithData");
-#if !defined(OS_CHROMEOS)
-    // TODO(enne): non-linux chromeos builds think that DrawTextOp
-    // can be converted to a PaintOpWithDataArrayBase.  OOPS.
-    static_assert(!std::is_convertible<T, PaintOpWithDataArrayBase>::value,
-                  "Type needs to use push_with_data_array");
-#endif
-    DCHECK_GE(bytes, 0u);
-    T* op = push_internal<T>(bytes, bytes, std::forward<Args>(args)...);
-    memcpy(paint_op_data(op), data, bytes);
-
-#if DCHECK_IS_ON()
-    // Double check the data fits between op and next op and doesn't clobber.
-    char* op_start = reinterpret_cast<char*>(op);
-    char* op_end = op_start + sizeof(T);
-    char* next_op = op_start + op->skip;
-    char* data_start = reinterpret_cast<char*>(paint_op_data(op));
-    char* data_end = data_start + bytes;
-    DCHECK_GE(data_start, op_end);
-    DCHECK_LT(data_start, next_op);
-    DCHECK_LE(data_end, next_op);
-#endif
-  }
-
-  template <typename T, typename M, typename... Args>
-  void push_with_data_array(const void* data,
-                            size_t bytes,
-                            const M* array,
-                            size_t count,
-                            Args&&... args) {
-    static_assert(std::is_convertible<T, PaintOpWithDataArray<M>>::value,
-                  "T is not a PaintOpWithDataArray");
-    DCHECK_GE(bytes, 0u);
-    DCHECK_GE(count, 0u);
-    size_t array_size = sizeof(M) * count;
-    size_t total_size = bytes + array_size;
-    T* op =
-        push_internal<T>(total_size, bytes, count, std::forward<Args>(args)...);
-    memcpy(paint_op_data(op), data, bytes);
-    memcpy(paint_op_array<M>(op), array, array_size);
-
-#if DCHECK_IS_ON()
-    // Double check data and array don't clobber op, next op, or each other
-    char* op_start = reinterpret_cast<char*>(op);
-    char* op_end = op_start + sizeof(T);
-    char* next_op = op_start + op->skip;
-    char* data_start = reinterpret_cast<char*>(paint_op_data(op));
-    char* data_end = data_start + bytes;
-    char* array_start = reinterpret_cast<char*>(paint_op_array<M>(op));
-    char* array_end = array_start + array_size;
-    DCHECK_GE(data_start, op_end);
-    DCHECK_LE(data_start, array_start);
-    DCHECK_GE(array_start, data_end);
-    DCHECK_LE(array_end, next_op);
-#endif
-  }
-
-  class Iterator {
-   public:
-    explicit Iterator(const PaintOpBuffer* buffer)
-        : buffer_(buffer), ptr_(buffer_->data_.get()) {}
-
-    PaintOp* operator->() const {
-      return op_idx_ ? reinterpret_cast<PaintOp*>(ptr_) : buffer_->GetFirstOp();
-    }
-    PaintOp* operator*() const { return operator->(); }
-    Iterator begin() { return Iterator(buffer_, buffer_->data_.get(), 0); }
-    Iterator end() {
-      return Iterator(buffer_, buffer_->data_.get() + buffer_->used_,
-                      buffer_->approximateOpCount());
-    }
-    bool operator!=(const Iterator& other) {
-      // Not valid to compare iterators on different buffers.
-      DCHECK_EQ(other.buffer_, buffer_);
-      return other.op_idx_ != op_idx_;
-    }
-    Iterator& operator++() {
-      if (!op_idx_++)
-        return *this;
-      PaintOp* op = **this;
-      uint32_t type = op->type;
-      CHECK_LE(type, static_cast<uint32_t>(PaintOpType::LastPaintOpType));
-      ptr_ += op->skip;
-      return *this;
-    }
-    operator bool() const { return op_idx_ < buffer_->approximateOpCount(); }
-
-    int op_idx() const { return op_idx_; }
-
-    // Return the next op without advancing the iterator, or nullptr if none.
-    PaintOp* peek1() const {
-      if (op_idx_ + 1 >= buffer_->approximateOpCount())
-        return nullptr;
-      if (!op_idx_)
-        return reinterpret_cast<PaintOp*>(ptr_);
-      return reinterpret_cast<PaintOp*>(ptr_ + (*this)->skip);
-    }
-
-    // Return the op two ops ahead without advancing the iterator, or nullptr if
-    // none.
-    PaintOp* peek2() const {
-      if (op_idx_ + 2 >= buffer_->approximateOpCount())
-        return nullptr;
-      char* next = ptr_ + reinterpret_cast<PaintOp*>(ptr_)->skip;
-      PaintOp* next_op = reinterpret_cast<PaintOp*>(next);
-      if (!op_idx_)
-        return next_op;
-      return reinterpret_cast<PaintOp*>(next + next_op->skip);
-    }
-
-   private:
-    Iterator(const PaintOpBuffer* buffer, char* ptr, int op_idx)
-        : buffer_(buffer), ptr_(ptr), op_idx_(op_idx) {}
-
-    const PaintOpBuffer* buffer_ = nullptr;
-    char* ptr_ = nullptr;
-    int op_idx_ = 0;
-  };
-
- private:
-  template <typename T, bool HasFlags>
-  struct CountSlowPathsFromFlags {
-    static int Count(const T* op) { return 0; }
-  };
-
-  template <typename T>
-  struct CountSlowPathsFromFlags<T, true> {
-    static int Count(const T* op) { return op->flags.getPathEffect() ? 1 : 0; }
-  };
-
-  template <typename T, typename... Args>
-  T* push_internal(size_t bytes, Args&&... args) {
-    size_t skip = SkAlignPtr(sizeof(T) + bytes);
-    DCHECK_LT(skip, static_cast<size_t>(1) << 24);
-    if (used_ + skip > reserved_ || !op_count_) {
-      if (!op_count_) {
-        if (bytes) {
-          // Internal first_op buffer doesn't have room for extra data.
-          // If the op wants extra bytes, then we'll just store a Noop
-          // in the first_op and proceed from there.  This seems unlikely
-          // to be a common case.
-          push<NoopOp>();
-        } else {
-          T* op = reinterpret_cast<T*>(&first_op_[0]);
-          new (op) T{std::forward<Args>(args)...};
-          op->type = static_cast<uint32_t>(T::kType);
-          op->skip = 0;
-          op_count_++;
-          return op;
-        }
-      }
-
-      // Start reserved_ at kInitialBufferSize and then double.
-      // ShrinkToFit can make this smaller afterwards.
-      while (used_ + skip > reserved_)
-        reserved_ = reserved_ ? reserved_ * 2 : kInitialBufferSize;
-      data_.realloc(reserved_);
-    }
-    DCHECK_LE(used_ + skip, reserved_);
-
-    T* op = reinterpret_cast<T*>(data_.get() + used_);
-    used_ += skip;
-    new (op) T(std::forward<Args>(args)...);
-    op->type = static_cast<uint32_t>(T::kType);
-    op->skip = skip;
-    op_count_++;
-
-    num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op);
-    num_slow_paths_ += op->CountSlowPaths();
-
-    subrecord_bytes_used_ += op->AdditionalBytesUsed();
-
-    return op;
-  }
-
-  // As a performance optimization because n=1 is an extremely common case just
-  // store the first op in the PaintOpBuffer itself to avoid an extra alloc.
-  char first_op_[sizeof(LargestPaintOp)];
-  SkAutoTMalloc<char> data_;
-  size_t used_ = 0;
-  size_t reserved_ = 0;
-  int op_count_ = 0;
-
-  // Record paths for veto-to-msaa for gpu raster.
-  int num_slow_paths_ = 0;
-  // Record additional bytes used by referenced sub-records and display lists.
-  size_t subrecord_bytes_used_ = 0;
-  SkRect cull_rect_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer);
-};
-
-}  // namespace cc
-
-#endif  // CC_PAINT_PAINT_OP_BUFFER_H_
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
deleted file mode 100644
index a962ab9..0000000
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/paint/paint_op_buffer.h"
-#include "cc/test/test_skcanvas.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-template <typename T>
-void CheckRefCnt(const T& obj, int32_t count) {
-// Skia doesn't define getRefCnt in all builds.
-#ifdef SK_DEBUG
-  EXPECT_EQ(obj->getRefCnt(), count);
-#endif
-}
-
-}  // namespace
-
-namespace cc {
-
-TEST(PaintOpBufferTest, Empty) {
-  PaintOpBuffer buffer;
-  EXPECT_EQ(buffer.approximateOpCount(), 0);
-  EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer));
-  EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
-
-  buffer.Reset();
-  EXPECT_EQ(buffer.approximateOpCount(), 0);
-  EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer));
-  EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
-}
-
-TEST(PaintOpBufferTest, SimpleAppend) {
-  SkRect rect = SkRect::MakeXYWH(2, 3, 4, 5);
-  PaintFlags flags;
-  flags.setColor(SK_ColorMAGENTA);
-  flags.setAlpha(100);
-  SkColor draw_color = SK_ColorRED;
-  SkBlendMode blend = SkBlendMode::kSrc;
-
-  PaintOpBuffer buffer;
-  buffer.push<SaveLayerOp>(&rect, &flags);
-  buffer.push<SaveOp>();
-  buffer.push<DrawColorOp>(draw_color, blend);
-  buffer.push<RestoreOp>();
-
-  EXPECT_EQ(buffer.approximateOpCount(), 4);
-
-  PaintOpBuffer::Iterator iter(&buffer);
-  ASSERT_EQ(iter->GetType(), PaintOpType::SaveLayer);
-  SaveLayerOp* save_op = static_cast<SaveLayerOp*>(*iter);
-  EXPECT_EQ(save_op->bounds, rect);
-  EXPECT_TRUE(save_op->flags == flags);
-  ++iter;
-
-  ASSERT_EQ(iter->GetType(), PaintOpType::Save);
-  ++iter;
-
-  ASSERT_EQ(iter->GetType(), PaintOpType::DrawColor);
-  DrawColorOp* op = static_cast<DrawColorOp*>(*iter);
-  EXPECT_EQ(op->color, draw_color);
-  EXPECT_EQ(op->mode, blend);
-  ++iter;
-
-  ASSERT_EQ(iter->GetType(), PaintOpType::Restore);
-  ++iter;
-
-  EXPECT_FALSE(iter);
-}
-
-// PaintOpBuffer has a special case for first ops stored locally, so
-// make sure that appending different kind of ops as a first op works
-// properly, as well as resetting and reusing the first local op.
-TEST(PaintOpBufferTest, FirstOpWithAndWithoutData) {
-  PaintOpBuffer buffer;
-  char text[] = "asdf";
-
-  // Use a color filter and its ref count to verify that the destructor
-  // is called on ops after reset.
-  PaintFlags flags;
-  sk_sp<SkColorFilter> filter =
-      SkColorFilter::MakeModeFilter(SK_ColorMAGENTA, SkBlendMode::kSrcOver);
-  flags.setColorFilter(filter);
-  CheckRefCnt(filter, 2);
-
-  buffer.push_with_data<DrawTextOp>(text, arraysize(text), 0.f, 0.f, flags);
-  CheckRefCnt(filter, 3);
-
-  // Verify that when the first op has data, which may not fit in the
-  // PaintRecord internal buffer, that it adds a noop as the first op
-  // and then appends the "op with data" into the heap buffer.
-  ASSERT_EQ(buffer.approximateOpCount(), 2);
-  EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::Noop);
-
-  // Verify iteration behavior and brief smoke test of op state.
-  {
-    PaintOpBuffer::Iterator iter(&buffer);
-    PaintOp* noop = *iter;
-    EXPECT_EQ(buffer.GetFirstOp(), noop);
-    ++iter;
-
-    PaintOp* op = *iter;
-    ASSERT_EQ(op->GetType(), PaintOpType::DrawText);
-    DrawTextOp* draw_text_op = static_cast<DrawTextOp*>(op);
-    EXPECT_EQ(draw_text_op->bytes, arraysize(text));
-
-    void* data = paint_op_data(draw_text_op);
-    EXPECT_EQ(memcmp(data, text, arraysize(text)), 0);
-
-    ++iter;
-    EXPECT_FALSE(iter);
-  }
-
-  // Reset, verify state, and append an op that will fit in the first slot.
-  buffer.Reset();
-  CheckRefCnt(filter, 2);
-
-  ASSERT_EQ(buffer.approximateOpCount(), 0);
-  EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false);
-
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, flags);
-  CheckRefCnt(filter, 3);
-
-  ASSERT_EQ(buffer.approximateOpCount(), 1);
-  EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::DrawRect);
-
-  PaintOpBuffer::Iterator iter(&buffer);
-  ASSERT_EQ(iter->GetType(), PaintOpType::DrawRect);
-  DrawRectOp* draw_rect_op = static_cast<DrawRectOp*>(*iter);
-  EXPECT_EQ(draw_rect_op->rect, rect);
-
-  ++iter;
-  EXPECT_FALSE(iter);
-
-  buffer.Reset();
-  ASSERT_EQ(buffer.approximateOpCount(), 0);
-  CheckRefCnt(filter, 2);
-}
-
-TEST(PaintOpBufferTest, Peek) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-  PaintFlags draw_flags;
-  buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), draw_flags);
-  buffer.push<RestoreOp>();
-  buffer.push<SaveOp>();
-  buffer.push<NoopOp>();
-  buffer.push<RestoreOp>();
-
-  PaintOpBuffer::Iterator init_iter(&buffer);
-  PaintOp* peek[2] = {*init_iter, init_iter.peek1()};
-
-  // Expect that while iterating that next = current.peek1() and that
-  // next.peek1() == current.peek2().
-  for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) {
-    EXPECT_EQ(*iter, peek[0]) << iter.op_idx();
-    EXPECT_EQ(iter.peek1(), peek[1]) << iter.op_idx();
-
-    peek[0] = iter.peek1();
-    peek[1] = iter.peek2();
-  }
-}
-
-TEST(PaintOpBufferTest, PeekEmpty) {
-  PaintOpBuffer empty;
-  PaintOpBuffer::Iterator empty_iter(&empty);
-  EXPECT_EQ(nullptr, empty_iter.peek1());
-  EXPECT_EQ(nullptr, empty_iter.peek2());
-}
-
-// Verify that a SaveLayerAlpha / Draw / Restore can be optimized to just
-// a draw with opacity.
-TEST(PaintOpBufferTest, SaveDrawRestore) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-
-  PaintFlags draw_flags;
-  draw_flags.setColor(SK_ColorMAGENTA);
-  draw_flags.setAlpha(50);
-  EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, draw_flags);
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(0, canvas.save_count_);
-  EXPECT_EQ(0, canvas.restore_count_);
-  EXPECT_EQ(rect, canvas.draw_rect_);
-
-  // Expect the alpha from the draw and the save layer to be folded together.
-  // Since alpha is stored in a uint8_t and gets rounded, so use tolerance.
-  float expected_alpha = alpha * 50 / 255.f;
-  EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f);
-}
-
-// The same as SaveDrawRestore, but test that the optimization doesn't apply
-// when the drawing op's flags are not compatible with being folded into the
-// save layer with opacity.
-TEST(PaintOpBufferTest, SaveDrawRestoreFail_BadFlags) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-
-  PaintFlags draw_flags;
-  draw_flags.setColor(SK_ColorMAGENTA);
-  draw_flags.setAlpha(50);
-  draw_flags.setBlendMode(SkBlendMode::kSrc);
-  EXPECT_FALSE(draw_flags.SupportsFoldingAlpha());
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, draw_flags);
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(rect, canvas.draw_rect_);
-  EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha());
-}
-
-// The same as SaveDrawRestore, but test that the optimization doesn't apply
-// when there are more than one ops between the save and restore.
-TEST(PaintOpBufferTest, SaveDrawRestoreFail_TooManyOps) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-
-  PaintFlags draw_flags;
-  draw_flags.setColor(SK_ColorMAGENTA);
-  draw_flags.setAlpha(50);
-  draw_flags.setBlendMode(SkBlendMode::kSrcOver);
-  EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  buffer.push<DrawRectOp>(rect, draw_flags);
-  buffer.push<NoopOp>();
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-  EXPECT_EQ(rect, canvas.draw_rect_);
-  EXPECT_EQ(draw_flags.getAlpha(), canvas.paint_.getAlpha());
-}
-
-// Verify that the save draw restore code works with a single op
-// that's not a draw op, and the optimization does not kick in.
-TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpNotADrawOp) {
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-
-  buffer.push<NoopOp>();
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-}
-
-// Test that the save/draw/restore optimization applies if the single op
-// is a DrawRecord that itself has a single draw op.
-TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleOp) {
-  sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>();
-
-  PaintFlags draw_flags;
-  draw_flags.setColor(SK_ColorMAGENTA);
-  draw_flags.setAlpha(50);
-  EXPECT_TRUE(draw_flags.SupportsFoldingAlpha());
-  SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4);
-  record->push<DrawRectOp>(rect, draw_flags);
-  EXPECT_EQ(record->approximateOpCount(), 1);
-
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-  buffer.push<DrawRecordOp>(std::move(record));
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(0, canvas.save_count_);
-  EXPECT_EQ(0, canvas.restore_count_);
-  EXPECT_EQ(rect, canvas.draw_rect_);
-
-  float expected_alpha = alpha * 50 / 255.f;
-  EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f);
-}
-
-// The same as the above SingleOpRecord test, but the single op is not
-// a draw op.  So, there's no way to fold in the save layer optimization.
-// Verify that the optimization doesn't apply and that this doesn't crash.
-// See: http://crbug.com/712093.
-TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleNonDrawOp) {
-  sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>();
-  record->push<NoopOp>();
-  EXPECT_EQ(record->approximateOpCount(), 1);
-  EXPECT_FALSE(record->GetFirstOp()->IsDrawOp());
-
-  PaintOpBuffer buffer;
-
-  uint8_t alpha = 100;
-  buffer.push<SaveLayerAlphaOp>(nullptr, alpha);
-  buffer.push<DrawRecordOp>(std::move(record));
-  buffer.push<RestoreOp>();
-
-  SaveCountingCanvas canvas;
-  buffer.playback(&canvas);
-
-  EXPECT_EQ(1, canvas.save_count_);
-  EXPECT_EQ(1, canvas.restore_count_);
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_record.cc b/cc/paint/paint_record.cc
deleted file mode 100644
index 52cb2524..0000000
--- a/cc/paint/paint_record.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/paint/paint_record.h"
-
-#include "cc/paint/paint_op_buffer.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
-
-namespace cc {
-
-sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) {
-  SkPictureRecorder recorder;
-  SkCanvas* canvas = recorder.beginRecording(record->cullRect());
-  record->playback(canvas);
-  return recorder.finishRecordingAsPicture();
-}
-
-sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record) {
-  SkPictureRecorder recorder;
-  SkCanvas* canvas = recorder.beginRecording(record->cullRect());
-  record->playback(canvas);
-  return recorder.finishRecordingAsPicture();
-}
-
-}  // namespace cc
diff --git a/cc/paint/paint_record.h b/cc/paint/paint_record.h
index daeee004..8506606b 100644
--- a/cc/paint/paint_record.h
+++ b/cc/paint/paint_record.h
@@ -5,22 +5,19 @@
 #ifndef CC_PAINT_PAINT_RECORD_H_
 #define CC_PAINT_PAINT_RECORD_H_
 
-#include "cc/paint/paint_export.h"
-#include "cc/paint/paint_op_buffer.h"
 #include "third_party/skia/include/core/SkPicture.h"
 
 namespace cc {
 
-// TODO(enne): Don't want to rename the world for this.  Using these as the
-// same types for now prevents an extra allocation.  Probably PaintRecord
-// will become an interface in the future.
-using PaintRecord = PaintOpBuffer;
+using PaintRecord = SkPicture;
 
-// TODO(enne): Remove these if possible, they are really expensive.
-CC_PAINT_EXPORT sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record);
+inline sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) {
+  return record;
+}
 
-CC_PAINT_EXPORT sk_sp<const SkPicture> ToSkPicture(
-    sk_sp<const PaintRecord> record);
+inline sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record) {
+  return record;
+}
 
 }  // namespace cc
 
diff --git a/cc/paint/paint_recorder.cc b/cc/paint/paint_recorder.cc
index c43f965..672f0712 100644
--- a/cc/paint/paint_recorder.cc
+++ b/cc/paint/paint_recorder.cc
@@ -4,36 +4,9 @@
 
 #include "cc/paint/paint_recorder.h"
 
-#include "cc/paint/paint_op_buffer.h"
-
 namespace cc {
 
 PaintRecorder::PaintRecorder() = default;
-
 PaintRecorder::~PaintRecorder() = default;
 
-PaintCanvas* PaintRecorder::beginRecording(const SkRect& bounds) {
-  buffer_.reset(new PaintOpBuffer(bounds));
-  canvas_.emplace(buffer_.get(), bounds);
-  return getRecordingCanvas();
-}
-
-sk_sp<PaintRecord> PaintRecorder::finishRecordingAsPicture() {
-  // SkPictureRecorder users expect that their saves are automatically
-  // closed for them.
-  //
-  // NOTE: Blink paint in general doesn't appear to need this, but the
-  // RecordingImageBufferSurface::fallBackToRasterCanvas finishing off the
-  // current frame depends on this.  Maybe we could remove this assumption and
-  // just have callers do it.
-  canvas_->restoreToCount(1);
-
-  // Some users (e.g. printing) use the existence of the recording canvas
-  // to know if recording is finished, so reset it here.
-  canvas_.reset();
-
-  buffer_->ShrinkToFit();
-  return std::move(buffer_);
-}
-
 }  // namespace cc
diff --git a/cc/paint/paint_recorder.h b/cc/paint/paint_recorder.h
index 7f582b85..2bbea83b 100644
--- a/cc/paint/paint_recorder.h
+++ b/cc/paint/paint_recorder.h
@@ -9,36 +9,47 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
+#include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_record.h"
-#include "cc/paint/record_paint_canvas.h"
+#include "cc/paint/skia_paint_canvas.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
 
 namespace cc {
 
-class PaintOpBuffer;
-
 class CC_PAINT_EXPORT PaintRecorder {
  public:
   PaintRecorder();
   ~PaintRecorder();
 
-  PaintCanvas* beginRecording(const SkRect& bounds);
+  ALWAYS_INLINE PaintCanvas* beginRecording(const SkRect& bounds) {
+    uint32_t record_flags = 0;
+    canvas_.emplace(recorder_.beginRecording(bounds, nullptr, record_flags));
+    return getRecordingCanvas();
+  }
 
-  // TODO(enne): should make everything go through the non-rect version.
-  // See comments in RecordPaintCanvas ctor for why.
-  PaintCanvas* beginRecording(SkScalar width, SkScalar height) {
-    return beginRecording(SkRect::MakeWH(width, height));
+  ALWAYS_INLINE PaintCanvas* beginRecording(SkScalar width, SkScalar height) {
+    uint32_t record_flags = 0;
+    canvas_.emplace(
+        recorder_.beginRecording(width, height, nullptr, record_flags));
+    return getRecordingCanvas();
   }
 
   // Only valid between between and finish recording.
-  ALWAYS_INLINE RecordPaintCanvas* getRecordingCanvas() {
+  ALWAYS_INLINE PaintCanvas* getRecordingCanvas() {
     return canvas_.has_value() ? &canvas_.value() : nullptr;
   }
 
-  sk_sp<PaintRecord> finishRecordingAsPicture();
+  ALWAYS_INLINE sk_sp<PaintRecord> finishRecordingAsPicture() {
+    sk_sp<SkPicture> picture = recorder_.finishRecordingAsPicture();
+    // Some users (e.g. printing) use the existence of the recording canvas
+    // to know if recording is finished, so reset it here.
+    canvas_.reset();
+    return sk_ref_sp(static_cast<PaintRecord*>(picture.get()));
+  }
 
  private:
-  sk_sp<PaintOpBuffer> buffer_;
-  base::Optional<RecordPaintCanvas> canvas_;
+  SkPictureRecorder recorder_;
+  base::Optional<SkiaPaintCanvas> canvas_;
 
   DISALLOW_COPY_AND_ASSIGN(PaintRecorder);
 };
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc
deleted file mode 100644
index 7f2ba61..0000000
--- a/cc/paint/record_paint_canvas.cc
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/paint/record_paint_canvas.h"
-
-#include "base/memory/ptr_util.h"
-#include "cc/paint/display_item_list.h"
-#include "cc/paint/paint_op_buffer.h"
-#include "cc/paint/paint_record.h"
-#include "cc/paint/paint_recorder.h"
-#include "third_party/skia/include/core/SkAnnotation.h"
-#include "third_party/skia/include/core/SkMetaData.h"
-#include "third_party/skia/include/utils/SkNWayCanvas.h"
-
-namespace cc {
-
-RecordPaintCanvas::RecordPaintCanvas(PaintOpBuffer* buffer,
-                                     const SkRect& cull_rect)
-    : buffer_(buffer),
-      canvas_(static_cast<int>(std::ceil(cull_rect.right())),
-              static_cast<int>(std::ceil(cull_rect.bottom()))) {
-  DCHECK(buffer_);
-
-  // This is part of the "recording canvases have a size, but why" dance.
-  // By creating a canvas of size (right x bottom) and then clipping it,
-  // It makes getDeviceClipBounds return the original cull rect, which code
-  // in GraphicsContextCanvas on Mac expects.  (Just creating an SkNoDrawCanvas
-  // with the cull_rect makes a canvas of size (width x height) instead
-  // which is incorrect.  SkRecorder cheats with private resetForNextCanvas.
-  canvas_.clipRect(SkRect::Make(cull_rect.roundOut()), SkClipOp::kIntersect,
-                   false);
-}
-
-RecordPaintCanvas::~RecordPaintCanvas() = default;
-
-SkMetaData& RecordPaintCanvas::getMetaData() {
-  // This could just be SkMetaData owned by RecordPaintCanvas, but since
-  // SkCanvas already has one, we might as well use it directly.
-  return canvas_.getMetaData();
-}
-
-SkImageInfo RecordPaintCanvas::imageInfo() const {
-  return canvas_.imageInfo();
-}
-
-void RecordPaintCanvas::flush() {
-  // This is a noop when recording.
-}
-
-SkISize RecordPaintCanvas::getBaseLayerSize() const {
-  return canvas_.getBaseLayerSize();
-}
-
-bool RecordPaintCanvas::writePixels(const SkImageInfo& info,
-                                    const void* pixels,
-                                    size_t row_bytes,
-                                    int x,
-                                    int y) {
-  NOTREACHED();
-  return false;
-}
-
-int RecordPaintCanvas::save() {
-  buffer_->push<SaveOp>();
-  return canvas_.save();
-}
-
-int RecordPaintCanvas::saveLayer(const SkRect* bounds,
-                                 const PaintFlags* flags) {
-  if (flags) {
-    if (flags->IsSimpleOpacity()) {
-      // TODO(enne): maybe more callers should know this and call
-      // saveLayerAlpha instead of needing to check here.
-      uint8_t alpha = SkColorGetA(flags->getColor());
-      return saveLayerAlpha(bounds, alpha);
-    }
-
-    // TODO(enne): it appears that image filters affect matrices and color
-    // matrices affect transparent flags on SkCanvas layers, but it's not clear
-    // whether those are actually needed and we could just skip ToSkPaint here.
-    buffer_->push<SaveLayerOp>(bounds, flags);
-    const SkPaint& paint = ToSkPaint(*flags);
-    return canvas_.saveLayer(bounds, &paint);
-  }
-  buffer_->push<SaveLayerOp>(bounds, flags);
-  return canvas_.saveLayer(bounds, nullptr);
-}
-
-int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
-  buffer_->push<SaveLayerAlphaOp>(bounds, alpha);
-  return canvas_.saveLayerAlpha(bounds, alpha);
-}
-
-void RecordPaintCanvas::restore() {
-  buffer_->push<RestoreOp>();
-  canvas_.restore();
-}
-
-int RecordPaintCanvas::getSaveCount() const {
-  return canvas_.getSaveCount();
-}
-
-void RecordPaintCanvas::restoreToCount(int save_count) {
-  DCHECK_GE(save_count, 1);
-  int diff = canvas_.getSaveCount() - save_count;
-  DCHECK_GE(diff, 0);
-  for (int i = 0; i < diff; ++i)
-    restore();
-}
-
-void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) {
-  buffer_->push<TranslateOp>(dx, dy);
-  canvas_.translate(dx, dy);
-}
-
-void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) {
-  buffer_->push<ScaleOp>(sx, sy);
-  canvas_.scale(sx, sy);
-}
-
-void RecordPaintCanvas::rotate(SkScalar degrees) {
-  buffer_->push<RotateOp>(degrees);
-  canvas_.rotate(degrees);
-}
-
-void RecordPaintCanvas::concat(const SkMatrix& matrix) {
-  buffer_->push<ConcatOp>(matrix);
-  canvas_.concat(matrix);
-}
-
-void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) {
-  buffer_->push<SetMatrixOp>(matrix);
-  canvas_.setMatrix(matrix);
-}
-
-void RecordPaintCanvas::clipRect(const SkRect& rect,
-                                 SkClipOp op,
-                                 bool antialias) {
-  buffer_->push<ClipRectOp>(rect, op, antialias);
-  canvas_.clipRect(rect, op, antialias);
-}
-
-void RecordPaintCanvas::clipRRect(const SkRRect& rrect,
-                                  SkClipOp op,
-                                  bool antialias) {
-  // TODO(enne): does this happen? Should the caller know this?
-  if (rrect.isRect()) {
-    clipRect(rrect.getBounds(), op, antialias);
-    return;
-  }
-  buffer_->push<ClipRRectOp>(rrect, op, antialias);
-  canvas_.clipRRect(rrect, op, antialias);
-}
-
-void RecordPaintCanvas::clipPath(const SkPath& path,
-                                 SkClipOp op,
-                                 bool antialias) {
-  if (!path.isInverseFillType() && canvas_.getTotalMatrix().rectStaysRect()) {
-    // TODO(enne): do these cases happen? should the caller know that this isn't
-    // a path?
-    SkRect rect;
-    if (path.isRect(&rect)) {
-      clipRect(rect, op, antialias);
-      return;
-    }
-    SkRRect rrect;
-    if (path.isOval(&rect)) {
-      rrect.setOval(rect);
-      clipRRect(rrect, op, antialias);
-      return;
-    }
-    if (path.isRRect(&rrect)) {
-      clipRRect(rrect, op, antialias);
-      return;
-    }
-  }
-
-  buffer_->push<ClipPathOp>(path, op, antialias);
-  canvas_.clipPath(path, op, antialias);
-  return;
-}
-
-bool RecordPaintCanvas::quickReject(const SkRect& rect) const {
-  return canvas_.quickReject(rect);
-}
-
-bool RecordPaintCanvas::quickReject(const SkPath& path) const {
-  return canvas_.quickReject(path);
-}
-
-SkRect RecordPaintCanvas::getLocalClipBounds() const {
-  return canvas_.getLocalClipBounds();
-}
-
-bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
-  return canvas_.getLocalClipBounds(bounds);
-}
-
-SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
-  return canvas_.getDeviceClipBounds();
-}
-
-bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
-  return canvas_.getDeviceClipBounds(bounds);
-}
-
-void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) {
-  buffer_->push<DrawColorOp>(color, mode);
-}
-
-void RecordPaintCanvas::clear(SkColor color) {
-  buffer_->push<DrawColorOp>(color, SkBlendMode::kSrc);
-}
-
-void RecordPaintCanvas::drawLine(SkScalar x0,
-                                 SkScalar y0,
-                                 SkScalar x1,
-                                 SkScalar y1,
-                                 const PaintFlags& flags) {
-  buffer_->push<DrawLineOp>(x0, y0, x1, y1, flags);
-}
-
-void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
-  buffer_->push<DrawRectOp>(rect, flags);
-}
-
-void RecordPaintCanvas::drawIRect(const SkIRect& rect,
-                                  const PaintFlags& flags) {
-  buffer_->push<DrawIRectOp>(rect, flags);
-}
-
-void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
-  buffer_->push<DrawOvalOp>(oval, flags);
-}
-
-void RecordPaintCanvas::drawRRect(const SkRRect& rrect,
-                                  const PaintFlags& flags) {
-  buffer_->push<DrawRRectOp>(rrect, flags);
-}
-
-void RecordPaintCanvas::drawDRRect(const SkRRect& outer,
-                                   const SkRRect& inner,
-                                   const PaintFlags& flags) {
-  if (outer.isEmpty())
-    return;
-  if (inner.isEmpty()) {
-    drawRRect(outer, flags);
-    return;
-  }
-  buffer_->push<DrawDRRectOp>(outer, inner, flags);
-}
-
-void RecordPaintCanvas::drawCircle(SkScalar cx,
-                                   SkScalar cy,
-                                   SkScalar radius,
-                                   const PaintFlags& flags) {
-  buffer_->push<DrawCircleOp>(cx, cy, radius, flags);
-}
-
-void RecordPaintCanvas::drawArc(const SkRect& oval,
-                                SkScalar start_angle,
-                                SkScalar sweep_angle,
-                                bool use_center,
-                                const PaintFlags& flags) {
-  buffer_->push<DrawArcOp>(oval, start_angle, sweep_angle, use_center, flags);
-}
-
-void RecordPaintCanvas::drawRoundRect(const SkRect& rect,
-                                      SkScalar rx,
-                                      SkScalar ry,
-                                      const PaintFlags& flags) {
-  // TODO(enne): move this into base class?
-  if (rx > 0 && ry > 0) {
-    SkRRect rrect;
-    rrect.setRectXY(rect, rx, ry);
-    drawRRect(rrect, flags);
-  } else {
-    drawRect(rect, flags);
-  }
-}
-
-void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
-  buffer_->push<DrawPathOp>(path, flags);
-}
-
-void RecordPaintCanvas::drawImage(const PaintImage& image,
-                                  SkScalar left,
-                                  SkScalar top,
-                                  const PaintFlags* flags) {
-  buffer_->push<DrawImageOp>(image, left, top, flags);
-}
-
-void RecordPaintCanvas::drawImageRect(const PaintImage& image,
-                                      const SkRect& src,
-                                      const SkRect& dst,
-                                      const PaintFlags* flags,
-                                      SrcRectConstraint constraint) {
-  buffer_->push<DrawImageRectOp>(image, src, dst, flags, constraint);
-}
-
-void RecordPaintCanvas::drawBitmap(const SkBitmap& bitmap,
-                                   SkScalar left,
-                                   SkScalar top,
-                                   const PaintFlags* flags) {
-  // TODO(enne): Move into base class?
-  if (bitmap.drawsNothing())
-    return;
-  drawImage(PaintImage(SkImage::MakeFromBitmap(bitmap),
-                       PaintImage::AnimationType::UNKNOWN,
-                       PaintImage::CompletionState::UNKNOWN),
-            left, top, flags);
-}
-
-void RecordPaintCanvas::drawText(const void* text,
-                                 size_t byte_length,
-                                 SkScalar x,
-                                 SkScalar y,
-                                 const PaintFlags& flags) {
-  buffer_->push_with_data<DrawTextOp>(text, byte_length, x, y, flags);
-}
-
-void RecordPaintCanvas::drawPosText(const void* text,
-                                    size_t byte_length,
-                                    const SkPoint pos[],
-                                    const PaintFlags& flags) {
-  size_t count = ToSkPaint(flags).countText(text, byte_length);
-  buffer_->push_with_data_array<DrawPosTextOp>(text, byte_length, pos, count,
-                                               flags);
-}
-
-void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
-                                     SkScalar x,
-                                     SkScalar y,
-                                     const PaintFlags& flags) {
-  buffer_->push<DrawTextBlobOp>(blob, x, y, flags);
-}
-
-void RecordPaintCanvas::drawDisplayItemList(
-    scoped_refptr<DisplayItemList> list) {
-  buffer_->push<DrawDisplayItemListOp>(list);
-}
-
-void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
-  // TODO(enne): If this is small, maybe flatten it?
-  buffer_->push<DrawRecordOp>(record);
-}
-
-bool RecordPaintCanvas::isClipEmpty() const {
-  return canvas_.isClipEmpty();
-}
-
-bool RecordPaintCanvas::isClipRect() const {
-  return canvas_.isClipRect();
-}
-
-const SkMatrix& RecordPaintCanvas::getTotalMatrix() const {
-  return canvas_.getTotalMatrix();
-}
-
-void RecordPaintCanvas::temporary_internal_describeTopLayer(
-    SkMatrix* matrix,
-    SkIRect* clip_bounds) {
-  return canvas_.temporary_internal_describeTopLayer(matrix, clip_bounds);
-}
-
-bool RecordPaintCanvas::ToPixmap(SkPixmap* output) {
-  // TODO(enne): It'd be nice to make this NOTREACHED() or remove this from
-  // RecordPaintCanvas, but this is used by GraphicsContextCanvas for knowing
-  // whether or not it can raster directly into pixels with Cg.
-  return false;
-}
-
-void RecordPaintCanvas::Annotate(AnnotationType type,
-                                 const SkRect& rect,
-                                 sk_sp<SkData> data) {
-  buffer_->push<AnnotateOp>(type, rect, data);
-}
-
-void RecordPaintCanvas::PlaybackPaintRecord(sk_sp<const PaintRecord> record) {
-  drawPicture(record);
-}
-
-}  // namespace cc
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h
deleted file mode 100644
index 15f0102..0000000
--- a/cc/paint/record_paint_canvas.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_PAINT_RECORD_PAINT_CANVAS_H_
-#define CC_PAINT_RECORD_PAINT_CANVAS_H_
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "cc/paint/paint_canvas.h"
-#include "cc/paint/paint_flags.h"
-#include "cc/paint/paint_record.h"
-#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
-
-namespace cc {
-
-class PaintOpBuffer;
-class PaintFlags;
-
-class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas {
- public:
-  explicit RecordPaintCanvas(PaintOpBuffer* buffer, const SkRect& cull_rect);
-  ~RecordPaintCanvas() override;
-
-  SkMetaData& getMetaData() override;
-  SkImageInfo imageInfo() const override;
-
-  void flush() override;
-
-  SkISize getBaseLayerSize() const override;
-  bool writePixels(const SkImageInfo& info,
-                   const void* pixels,
-                   size_t row_bytes,
-                   int x,
-                   int y) override;
-  int save() override;
-  int saveLayer(const SkRect* bounds, const PaintFlags* flags) override;
-  int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override;
-
-  void restore() override;
-  int getSaveCount() const override;
-  void restoreToCount(int save_count) override;
-  void translate(SkScalar dx, SkScalar dy) override;
-  void scale(SkScalar sx, SkScalar sy) override;
-  void rotate(SkScalar degrees) override;
-  void concat(const SkMatrix& matrix) override;
-  void setMatrix(const SkMatrix& matrix) override;
-
-  void clipRect(const SkRect& rect, SkClipOp op, bool antialias) override;
-  void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) override;
-  void clipPath(const SkPath& path, SkClipOp op, bool antialias) override;
-  bool quickReject(const SkRect& rect) const override;
-  bool quickReject(const SkPath& path) const override;
-  SkRect getLocalClipBounds() const override;
-  bool getLocalClipBounds(SkRect* bounds) const override;
-  SkIRect getDeviceClipBounds() const override;
-  bool getDeviceClipBounds(SkIRect* bounds) const override;
-  void drawColor(SkColor color, SkBlendMode mode) override;
-  void clear(SkColor color) override;
-
-  void drawLine(SkScalar x0,
-                SkScalar y0,
-                SkScalar x1,
-                SkScalar y1,
-                const PaintFlags& flags) override;
-  void drawRect(const SkRect& rect, const PaintFlags& flags) override;
-  void drawIRect(const SkIRect& rect, const PaintFlags& flags) override;
-  void drawOval(const SkRect& oval, const PaintFlags& flags) override;
-  void drawRRect(const SkRRect& rrect, const PaintFlags& flags) override;
-  void drawDRRect(const SkRRect& outer,
-                  const SkRRect& inner,
-                  const PaintFlags& flags) override;
-  void drawCircle(SkScalar cx,
-                  SkScalar cy,
-                  SkScalar radius,
-                  const PaintFlags& flags) override;
-  void drawArc(const SkRect& oval,
-               SkScalar start_angle,
-               SkScalar sweep_angle,
-               bool use_center,
-               const PaintFlags& flags) override;
-  void drawRoundRect(const SkRect& rect,
-                     SkScalar rx,
-                     SkScalar ry,
-                     const PaintFlags& flags) override;
-  void drawPath(const SkPath& path, const PaintFlags& flags) override;
-  void drawImage(const PaintImage& image,
-                 SkScalar left,
-                 SkScalar top,
-                 const PaintFlags* flags) override;
-  void drawImageRect(const PaintImage& image,
-                     const SkRect& src,
-                     const SkRect& dst,
-                     const PaintFlags* flags,
-                     SrcRectConstraint constraint) override;
-  void drawBitmap(const SkBitmap& bitmap,
-                  SkScalar left,
-                  SkScalar top,
-                  const PaintFlags* flags) override;
-
-  void drawText(const void* text,
-                size_t byte_length,
-                SkScalar x,
-                SkScalar y,
-                const PaintFlags& flags) override;
-  void drawPosText(const void* text,
-                   size_t byte_length,
-                   const SkPoint pos[],
-                   const PaintFlags& flags) override;
-  void drawTextBlob(sk_sp<SkTextBlob> blob,
-                    SkScalar x,
-                    SkScalar y,
-                    const PaintFlags& flags) override;
-
-  void drawDisplayItemList(
-      scoped_refptr<DisplayItemList> display_item_list) override;
-
-  void drawPicture(sk_sp<const PaintRecord> record) override;
-
-  bool isClipEmpty() const override;
-  bool isClipRect() const override;
-  const SkMatrix& getTotalMatrix() const override;
-
-  void temporary_internal_describeTopLayer(SkMatrix* matrix,
-                                           SkIRect* clip_bounds) override;
-
-  bool ToPixmap(SkPixmap* output) override;
-  void Annotate(AnnotationType type,
-                const SkRect& rect,
-                sk_sp<SkData> data) override;
-
-  void PlaybackPaintRecord(sk_sp<const PaintRecord> record) override;
-
-  // Don't shadow non-virtual helper functions.
-  using PaintCanvas::clipRect;
-  using PaintCanvas::clipRRect;
-  using PaintCanvas::clipPath;
-  using PaintCanvas::drawBitmap;
-  using PaintCanvas::drawColor;
-  using PaintCanvas::drawImage;
-  using PaintCanvas::drawPicture;
-
- private:
-  PaintOpBuffer* buffer_;
-
-  // TODO(enne): Although RecordPaintCanvas is mostly a write-only interface
-  // where paint commands are stored, occasionally users of PaintCanvas want
-  // to ask stateful questions mid-stream of clip and transform state.
-  // To avoid duplicating all this code (for now?), just forward to an SkCanvas
-  // that's not backed by anything but can answer these questions.
-  SkNoDrawCanvas canvas_;
-};
-
-}  // namespace cc
-
-#endif  // CC_PAINT_RECORD_PAINT_CANVAS_H_
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index 501ccdf..bfc38b6 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/paint/skia_paint_canvas.h"
+#include "cc/paint/paint_canvas.h"
 
 #include "base/memory/ptr_util.h"
 #include "cc/paint/display_item_list.h"
@@ -58,7 +58,7 @@
   return canvas_->saveLayer(bounds, ToSkPaint(flags));
 }
 
-int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
+int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
   return canvas_->saveLayerAlpha(bounds, alpha);
 }
 
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index 1bd23f0..47dba86 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -46,7 +46,7 @@
                    int y) override;
   int save() override;
   int saveLayer(const SkRect* bounds, const PaintFlags* flags) override;
-  int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override;
+  int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) override;
 
   void restore() override;
   int getSaveCount() const override;
diff --git a/cc/test/test_skcanvas.cc b/cc/test/test_skcanvas.cc
deleted file mode 100644
index e45f42de..0000000
--- a/cc/test/test_skcanvas.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/test/test_skcanvas.h"
-
-namespace cc {
-
-SaveCountingCanvas::SaveCountingCanvas() : SkNoDrawCanvas(100, 100) {}
-
-SkCanvas::SaveLayerStrategy SaveCountingCanvas::getSaveLayerStrategy(
-    const SaveLayerRec& rec) {
-  save_count_++;
-  return SkNoDrawCanvas::getSaveLayerStrategy(rec);
-}
-
-void SaveCountingCanvas::willRestore() {
-  restore_count_++;
-}
-
-void SaveCountingCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
-  draw_rect_ = rect;
-  paint_ = paint;
-}
-
-}  // namespace cc
diff --git a/cc/test/test_skcanvas.h b/cc/test/test_skcanvas.h
deleted file mode 100644
index 2b130a4..0000000
--- a/cc/test/test_skcanvas.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_TEST_TEST_SKCANVAS_H_
-#define CC_TEST_TEST_SKCANVAS_H_
-
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
-
-namespace cc {
-
-class SaveCountingCanvas : public SkNoDrawCanvas {
- public:
-  SaveCountingCanvas();
-
-  // Note: getSaveLayerStrategy is used as "willSave", as willSave
-  // is not always called.
-  SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override;
-  void willRestore() override;
-  void onDrawRect(const SkRect& rect, const SkPaint& paint) override;
-
-  int save_count_ = 0;
-  int restore_count_ = 0;
-  SkRect draw_rect_;
-  SkPaint paint_;
-};
-
-}  // namespace cc
-
-#endif  // CC_TEST_TEST_SKCANVAS_H_
diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc
index 48be0096..a3b88eb 100644
--- a/chrome/browser/io_thread_unittest.cc
+++ b/chrome/browser/io_thread_unittest.cc
@@ -271,7 +271,6 @@
 
   EXPECT_TRUE(params_.enable_http2);
   EXPECT_FALSE(params_.enable_quic);
-  EXPECT_TRUE(params_.enable_quic_alternative_service_with_different_host);
   EXPECT_EQ(1350u, params_.quic_max_packet_length);
   EXPECT_EQ(net::QuicTagVector(), params_.quic_connection_options);
   EXPECT_TRUE(params_.origins_to_force_quic_on.empty());
@@ -322,27 +321,6 @@
 }
 
 TEST_F(ConfigureParamsFromFieldTrialsAndCommandLineTest,
-       EnableAlternativeServicesFromCommandLineWithQuicDisabled) {
-  command_line_.AppendSwitch("enable-alternative-services");
-
-  ConfigureParamsFromFieldTrialsAndCommandLine();
-
-  EXPECT_FALSE(params_.enable_quic);
-  EXPECT_TRUE(params_.enable_quic_alternative_service_with_different_host);
-}
-
-TEST_F(ConfigureParamsFromFieldTrialsAndCommandLineTest,
-       EnableAlternativeServicesFromCommandLineWithQuicEnabled) {
-  command_line_.AppendSwitch("enable-quic");
-  command_line_.AppendSwitch("enable-alternative-services");
-
-  ConfigureParamsFromFieldTrialsAndCommandLine();
-
-  EXPECT_TRUE(params_.enable_quic);
-  EXPECT_TRUE(params_.enable_quic_alternative_service_with_different_host);
-}
-
-TEST_F(ConfigureParamsFromFieldTrialsAndCommandLineTest,
        QuicVersionFromCommandLine) {
   command_line_.AppendSwitch("enable-quic");
   std::string version =
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index e2cf293f..9900a90 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -1092,14 +1092,25 @@
   // The only thing we check here is that there is no use-after-free reported.
 }
 
-// Disabled on Windows due to flakiness: http://crbug.com/346297
-#if defined(OS_WIN)
-#define MAYBE_PasswordValueAccessible DISABLED_PasswordValueAccessible
-#else
-#define MAYBE_PasswordValueAccessible PasswordValueAccessible
-#endif
 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
-                       MAYBE_PasswordValueAccessible) {
+                       PasswordValueAccessible) {
+  // At first let us save a credential to the password store.
+  scoped_refptr<password_manager::TestPasswordStore> password_store =
+      static_cast<password_manager::TestPasswordStore*>(
+          PasswordStoreFactory::GetForProfile(
+              browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
+              .get());
+  autofill::PasswordForm signin_form;
+  signin_form.signon_realm = embedded_test_server()->base_url().spec();
+  signin_form.origin = embedded_test_server()->base_url();
+  signin_form.action = embedded_test_server()->base_url();
+  signin_form.username_value = base::ASCIIToUTF16("admin");
+  signin_form.password_value = base::ASCIIToUTF16("12345");
+  password_store->AddLogin(signin_form);
+
+  // Steps from https://crbug.com/337429#c37.
+  // Navigate to the page, click a link that opens a second tab, reload the
+  // first tab and observe that the password is accessible.
   NavigateToFile("/password/form_and_link.html");
 
   // Click on a link to open a new tab, then switch back to the first one.
@@ -1110,36 +1121,23 @@
   EXPECT_EQ(2, browser()->tab_strip_model()->count());
   browser()->tab_strip_model()->ActivateTabAt(0, false);
 
-  // Fill in the credentials, and make sure they are saved.
-  NavigationObserver form_submit_observer(WebContents());
-  std::unique_ptr<BubbleObserver> prompt_observer(
-      new BubbleObserver(WebContents()));
-  std::string fill_and_submit =
-      "document.getElementById('username_field').value = 'temp';"
-      "document.getElementById('password_field').value = 'random';"
-      "document.getElementById('input_submit_button').click();";
-  ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
-  form_submit_observer.Wait();
-  EXPECT_TRUE(prompt_observer->IsShowingSavePrompt());
-  prompt_observer->AcceptSavePrompt();
-
   // Reload the original page to have the saved credentials autofilled.
   NavigationObserver reload_observer(WebContents());
   NavigateToFile("/password/form_and_link.html");
   reload_observer.Wait();
 
   // Wait until the username is filled, to make sure autofill kicked in.
-  WaitForElementValue("username_field", "temp");
+  WaitForElementValue("username_field", "admin");
   // Now check that the password is not accessible yet.
   CheckElementValue("password_field", "");
   // Let the user interact with the page.
   content::SimulateMouseClickAt(
       WebContents(), 0, blink::WebMouseEvent::Button::kLeft, gfx::Point(1, 1));
   // Wait until that interaction causes the password value to be revealed.
-  WaitForElementValue("password_field", "random");
+  WaitForElementValue("password_field", "12345");
   // And check that after the side-effects of the interaction took place, the
   // username value stays the same.
-  CheckElementValue("username_field", "temp");
+  CheckElementValue("username_field", "admin");
 }
 
 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
diff --git a/components/favicon/ios/BUILD.gn b/components/favicon/ios/BUILD.gn
index 37ef0fbb7..5014a92e 100644
--- a/components/favicon/ios/BUILD.gn
+++ b/components/favicon/ios/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 source_set("ios") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "favicon_url_util.cc",
     "favicon_url_util.h",
diff --git a/components/favicon/ios/web_favicon_driver.mm b/components/favicon/ios/web_favicon_driver.mm
index 500a5f4..01f4ff8f 100644
--- a/components/favicon/ios/web_favicon_driver.mm
+++ b/components/favicon/ios/web_favicon_driver.mm
@@ -18,6 +18,10 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/image/image.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 DEFINE_WEB_STATE_USER_DATA_KEY(favicon::WebFaviconDriver);
 
 // Callback for the download of favicon.
diff --git a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadCallableTest.java b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadCallableTest.java
index e0fd90f9..52f2b3f 100644
--- a/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadCallableTest.java
+++ b/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/MinidumpUploadCallableTest.java
@@ -111,6 +111,28 @@
         }
     }
 
+    private static class ErrorCodeHttpUrlConnectionFactory implements HttpURLConnectionFactory {
+        private final int mErrorCode;
+
+        ErrorCodeHttpUrlConnectionFactory(int errorCode) {
+            mErrorCode = errorCode;
+        }
+
+        @Override
+        public HttpURLConnection createHttpURLConnection(String url) {
+            try {
+                return new TestHttpURLConnection(new URL(url)) {
+                    @Override
+                    public int getResponseCode() {
+                        return mErrorCode;
+                    }
+                };
+            } catch (IOException e) {
+                return null;
+            }
+        }
+    }
+
     private static class FailHttpURLConnectionFactory implements HttpURLConnectionFactory {
         @Override
         public HttpURLConnection createHttpURLConnection(String url) {
@@ -394,6 +416,33 @@
         }
     }
 
+    @SmallTest
+    @Feature({"Android-AppBase"})
+    public void testReceivingErrorCodes() throws Exception {
+        CrashReportingPermissionManager testPermManager =
+                new MockCrashReportingPermissionManager() {
+                    {
+                        mIsInSample = true;
+                        mIsUserPermitted = true;
+                        mIsNetworkAvailable = true;
+                        mIsEnabledForTests = false;
+                    }
+                };
+
+        final int[] errorCodes = {400, 401, 403, 404, 500};
+
+        for (int n = 0; n < errorCodes.length; n++) {
+            HttpURLConnectionFactory httpURLConnectionFactory =
+                    new ErrorCodeHttpUrlConnectionFactory(errorCodes[n]);
+            MinidumpUploadCallable minidumpUploadCallable =
+                    new MockMinidumpUploadCallable(httpURLConnectionFactory, testPermManager);
+            assertEquals(MinidumpUploadCallable.UPLOAD_FAILURE,
+                    minidumpUploadCallable.call().intValue());
+            // Note that mTestUpload is not renamed on failure - so we can try to upload that file
+            // several times during the same test.
+        }
+    }
+
     private void assertValidUploadLogEntry() throws IOException {
         File logfile = new File(mCrashDir, CrashFileManager.CRASH_DUMP_LOGFILE);
         BufferedReader input =  new BufferedReader(new FileReader(logfile));
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc
index 5822adf..e12cc1c 100644
--- a/components/network_session_configurator/network_session_configurator.cc
+++ b/components/network_session_configurator/network_session_configurator.cc
@@ -123,14 +123,6 @@
       "true");
 }
 
-bool ShouldQuicEnableAlternativeServicesForDifferentHost(
-    const VariationParameters& quic_trial_params) {
-  return !base::LowerCaseEqualsASCII(
-      GetVariationParam(quic_trial_params,
-                        "enable_alternative_service_with_different_host"),
-      "false");
-}
-
 net::QuicTagVector GetQuicConnectionOptions(
     const VariationParameters& quic_trial_params) {
   VariationParameters::const_iterator it =
@@ -306,8 +298,6 @@
 
   params->retry_without_alt_svc_on_quic_errors =
       ShouldRetryWithoutAltSvcOnQuicErrors(quic_trial_params);
-  params->enable_quic_alternative_service_with_different_host =
-      ShouldQuicEnableAlternativeServicesForDifferentHost(quic_trial_params);
 
   if (params->enable_quic) {
     params->quic_delay_tcp_race = ShouldQuicDelayTcpRace(quic_trial_params);
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc
index 8e5a7d2..f7b8048 100644
--- a/components/network_session_configurator/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -49,7 +49,6 @@
   EXPECT_TRUE(params_.enable_http2);
   EXPECT_TRUE(params_.http2_settings.empty());
   EXPECT_FALSE(params_.enable_tcp_fast_open_for_ssl);
-  EXPECT_TRUE(params_.enable_quic_alternative_service_with_different_host);
   EXPECT_FALSE(params_.enable_quic);
 }
 
@@ -76,7 +75,6 @@
   EXPECT_FALSE(params_.enable_server_push_cancellation);
   EXPECT_FALSE(params_.quic_enable_non_blocking_io);
   EXPECT_FALSE(params_.quic_disable_disk_cache);
-  EXPECT_TRUE(params_.enable_quic_alternative_service_with_different_host);
   EXPECT_TRUE(params_.quic_delay_tcp_race);
   EXPECT_FALSE(params_.quic_close_sessions_on_ip_change);
   EXPECT_EQ(net::kIdleConnectionTimeoutSeconds,
@@ -387,18 +385,6 @@
   EXPECT_TRUE(params_.quic_disable_disk_cache);
 }
 
-TEST_F(NetworkSessionConfiguratorTest,
-       QuicEnableAlternativeServicesFromFieldTrialParams) {
-  std::map<std::string, std::string> field_trial_params;
-  field_trial_params["enable_alternative_service_with_different_host"] = "true";
-  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
-  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
-
-  ParseFieldTrials();
-
-  EXPECT_TRUE(params_.enable_quic_alternative_service_with_different_host);
-}
-
 TEST_F(NetworkSessionConfiguratorTest, QuicDisableDelayTcpRace) {
   std::map<std::string, std::string> field_trial_params;
   field_trial_params["disable_delay_tcp_race"] = "true";
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index 716adc9..36978f6 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -532,7 +532,7 @@
   // the WebURLLoader are the ones created by CommitNavigation. Several browser
   // tests load HTML directly through a data url which will be handled by the
   // block above.
-  DCHECK(!IsBrowserSideNavigationEnabled() || stream_override_.get() ||
+  DCHECK(!IsBrowserSideNavigationEnabled() || stream_override_ ||
          request.GetFrameType() == WebURLRequest::kFrameTypeNone);
 
   GURL referrer_url(
@@ -603,7 +603,7 @@
   // contains the body of the response. The network request has already been
   // made by the browser.
   mojo::ScopedDataPipeConsumerHandle consumer_handle;
-  if (stream_override_.get()) {
+  if (stream_override_) {
     CHECK(IsBrowserSideNavigationEnabled());
     DCHECK(!sync_load_response);
     DCHECK_NE(WebURLRequest::kFrameTypeNone, request.GetFrameType());
@@ -716,7 +716,7 @@
 
   // PlzNavigate: during navigations, the ResourceResponse has already been
   // received on the browser side, and has been passed down to the renderer.
-  if (stream_override_.get()) {
+  if (stream_override_) {
     CHECK(IsBrowserSideNavigationEnabled());
     // Compute the delta between the response sizes so that the accurate
     // transfer size can be reported at the end of the request.
@@ -785,19 +785,20 @@
     client_->DidReceiveResponse(response, std::move(read_handle));
     // TODO(yhirano): Support ftp listening and multipart
     return;
-  } else {
-    client_->DidReceiveResponse(response);
   }
 
-  // We may have been cancelled after didReceiveResponse, which would leave us
-  // without a client and therefore without much need to do further handling.
+  client_->DidReceiveResponse(response);
+
+  // DidReceiveResponse() may have triggered a cancel, causing the |client_| to
+  // go away.
   if (!client_)
     return;
 
-  DCHECK(!ftp_listing_delegate_.get());
+  DCHECK(!ftp_listing_delegate_);
   if (info.mime_type == "text/vnd.chromium.ftp-dir" && !show_raw_listing) {
-    ftp_listing_delegate_.reset(
-        new FtpDirectoryListingResponseDelegate(client_, loader_, response));
+    ftp_listing_delegate_ =
+        base::MakeUnique<FtpDirectoryListingResponseDelegate>(client_, loader_,
+                                                              response);
   }
 }
 
@@ -829,16 +830,17 @@
     // The FTP listing delegate will make the appropriate calls to
     // client_->didReceiveData and client_->didReceiveResponse.
     ftp_listing_delegate_->OnReceivedData(payload, data_length);
-  } else {
-    // We dispatch the data even when |useStreamOnResponse()| is set, in order
-    // to make Devtools work.
-    client_->DidReceiveData(payload, data_length);
+    return;
+  }
 
-    if (request_.UseStreamOnResponse()) {
-      // We don't support ftp_listening_delegate_ for now.
-      // TODO(yhirano): Support ftp listening.
-      body_stream_writer_->AddData(std::move(data));
-    }
+  // We dispatch the data even when |useStreamOnResponse()| is set, in order
+  // to make Devtools work.
+  client_->DidReceiveData(payload, data_length);
+
+  if (request_.UseStreamOnResponse()) {
+    // We don't support |ftp_listing_delegate_| for now.
+    // TODO(yhirano): Support ftp listening.
+    body_stream_writer_->AddData(std::move(data));
   }
 }
 
@@ -889,7 +891,7 @@
                        total_transfer_size, encoded_body_size);
     } else {
       // PlzNavigate: compute the accurate transfer size for navigations.
-      if (stream_override_.get()) {
+      if (stream_override_) {
         DCHECK(IsBrowserSideNavigationEnabled());
         total_transfer_size += stream_override_->total_transfer_size_delta;
       }
diff --git a/jingle/glue/proxy_resolving_client_socket.cc b/jingle/glue/proxy_resolving_client_socket.cc
index 4b9547c2..4417590 100644
--- a/jingle/glue/proxy_resolving_client_socket.cc
+++ b/jingle/glue/proxy_resolving_client_socket.cc
@@ -91,8 +91,6 @@
     session_params.enable_http2 = reference_params->enable_http2;
     session_params.enable_http2_alternative_service =
         reference_params->enable_http2_alternative_service;
-    session_params.enable_quic_alternative_service_with_different_host =
-        reference_params->enable_quic_alternative_service_with_different_host;
   }
 
   network_session_.reset(new net::HttpNetworkSession(session_params));
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 2bf81e63..5c208946 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -120,7 +120,6 @@
       spdy_session_max_recv_window_size(kSpdySessionMaxRecvWindowSize),
       time_func(&base::TimeTicks::Now),
       enable_http2_alternative_service(false),
-      enable_quic_alternative_service_with_different_host(true),
       enable_quic(false),
       mark_quic_broken_when_network_blackholes(false),
       retry_without_alt_svc_on_quic_errors(false),
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index b0061da..7765245 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -113,9 +113,6 @@
     SpdySessionPool::TimeFunc time_func;
     // Whether to enable HTTP/2 Alt-Svc entries.
     bool enable_http2_alternative_service;
-    // Whether to enable QUIC Alt-Svc entries with hostname different than that
-    // of the origin.
-    bool enable_quic_alternative_service_with_different_host;
 
     // Enables QUIC support.
     bool enable_quic;
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc
index fc6d3e14..b4a6bd46 100644
--- a/net/http/http_stream_factory_impl_job_controller.cc
+++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -994,12 +994,6 @@
     }
 
     DCHECK_EQ(kProtoQUIC, alternative_service.protocol);
-    if (origin.host() != alternative_service.host &&
-        !session_->params()
-             .enable_quic_alternative_service_with_different_host) {
-      continue;
-    }
-
     quic_all_broken = false;
     if (!session_->IsQuicEnabled())
       continue;
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index 77eddbdb..7feab3fb 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -3015,7 +3015,6 @@
   // There is no need to set up main job, because no attempt will be made to
   // speak to the proxy over TCP.
   request_.url = GURL("http://mail.example.org/");
-  params_.enable_quic_alternative_service_with_different_host = false;
   TestProxyDelegate test_proxy_delegate;
   const HostPortPair host_port_pair("mail.example.org", 443);
 
diff --git a/printing/pdf_metafile_skia.cc b/printing/pdf_metafile_skia.cc
index aec4d3f..b2e914b3 100644
--- a/printing/pdf_metafile_skia.cc
+++ b/printing/pdf_metafile_skia.cc
@@ -12,9 +12,9 @@
 #include "base/files/file.h"
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
+#include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_record.h"
 #include "cc/paint/paint_recorder.h"
-#include "cc/paint/skia_paint_canvas.h"
 #include "printing/print_settings.h"
 #include "third_party/skia/include/core/SkDocument.h"
 #include "third_party/skia/include/core/SkStream.h"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-createEvent-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-createEvent-expected.txt
index 727ee6ad..72e81162 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-createEvent-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-createEvent-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 331 tests; 306 PASS, 25 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 331 tests; 307 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS AnimationEvent should be an alias for AnimationEvent. 
 PASS createEvent('AnimationEvent') should be initialized correctly. 
 PASS animationevent should be an alias for AnimationEvent. 
@@ -333,9 +333,7 @@
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TimeEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitAnimationEvent" 
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitAnimationEvents" 
-FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitTransitionEvent" assert_throws: function "function () {
-        var evt = document.createEvent(eventInterface);
-      }" did not throw
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitTransitionEvent" 
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitTransitionEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "XULCommandEvent" 
 PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "XULCommandEvents" 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document-expected.txt
index 6e91db4a..1f6252f 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document-expected.txt
@@ -4,7 +4,7 @@
 
 
 PASS testFrameUnloaded is true
-PASS cachedDocument.defaultView is undefined.
+PASS cachedDocument.defaultView is null
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document.html b/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document.html
index b5095d2d..0a14301 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/defaultView-on-detached-document.html
@@ -40,7 +40,7 @@
 function finishTest()
 {
     shouldBeTrue("testFrameUnloaded");
-    shouldBeUndefined("cachedDocument.defaultView");
+    shouldBeNull("cachedDocument.defaultView");
     finishJSTest();
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt b/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt
index 8792b3c99..7a41397 100644
--- a/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt
@@ -91,9 +91,6 @@
 PASS document.createEvent('TransitionEvent') instanceof window.TransitionEvent is true
 PASS document.createEvent('TransitionEvent') instanceof window.Event is true
 PASS document.createEvent('TransitionEvent').constructor === window.TransitionEvent is true
-PASS document.createEvent('WebKitTransitionEvent') instanceof window.WebKitTransitionEvent is true
-PASS document.createEvent('WebKitTransitionEvent') instanceof window.Event is true
-PASS document.createEvent('WebKitTransitionEvent').constructor === window.WebKitTransitionEvent is true
 PASS document.createEvent('WheelEvent') instanceof window.WheelEvent is true
 PASS document.createEvent('WheelEvent') instanceof window.MouseEvent is true
 PASS document.createEvent('WheelEvent') instanceof window.UIEvent is true
diff --git a/third_party/WebKit/LayoutTests/fast/events/event-creation.html b/third_party/WebKit/LayoutTests/fast/events/event-creation.html
index 0e2db8b..07d7a697 100644
--- a/third_party/WebKit/LayoutTests/fast/events/event-creation.html
+++ b/third_party/WebKit/LayoutTests/fast/events/event-creation.html
@@ -135,11 +135,6 @@
     shouldBeTrue("document.createEvent('TransitionEvent') instanceof window.Event");
     shouldBeTrue("document.createEvent('TransitionEvent').constructor === window.TransitionEvent");
 
-    // WebKitTransitionEvent
-    shouldBeTrue("document.createEvent('WebKitTransitionEvent') instanceof window.WebKitTransitionEvent");
-    shouldBeTrue("document.createEvent('WebKitTransitionEvent') instanceof window.Event");
-    shouldBeTrue("document.createEvent('WebKitTransitionEvent').constructor === window.WebKitTransitionEvent");
-
     // WheelEvent
     shouldBeTrue("document.createEvent('WheelEvent') instanceof window.WheelEvent");
     shouldBeTrue("document.createEvent('WheelEvent') instanceof window.MouseEvent");
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html
new file mode 100644
index 0000000..97d5761f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<style>
+    .multicol {
+        width: 300px;
+        height: 100px;
+        line-height: 20px;
+        border: 5px solid maroon;
+    }
+    .column {
+        width: 100px;
+        float: left;
+    }
+    .multicol[dir="rtl"] > .column {
+        float: right;
+    }
+    .block {
+        display: inline-block;
+        width: 1em;
+        height: 10px;
+        background-color: green;
+    }
+    .opacity {
+        opacity: 0.5;
+        color: green;
+    }
+    .relative {
+        position: relative;
+        top: -4px;
+        color: green;
+    }
+</style>
+<p>
+    Test layers which are fully contained within a single column.
+</p>
+LTR:
+<div class="multicol">
+    <div class="column">
+        line1<br>
+        line2<br>
+        line3<br>
+        line4<br>
+        line5<br>
+    </div>
+    <div class="column">
+        line6<br>
+        <div class="block"></div> line7<br>
+        line8<br>
+        <span class="relative">relative9</span><br>
+        line10<br>
+    </div>
+    <div class="column">
+        line11<br>
+        line12<br>
+        <!-- The extra inner span below forces the creation of a transparency layer in Skia to work
+             around optimizations that would cause blending differences between the test and the
+             expectation. -->
+        <span class="opacity">opacity<span>13</span></span><br>
+        line14
+    </div>
+</div>
+
+RTL:
+<div class="multicol" dir="rtl">
+    <div class="column">
+        line1<br>
+        line2<br>
+        line3<br>
+        line4<br>
+        line5<br>
+    </div>
+    <div class="column">
+        line6<br>
+        <div class="block"></div> line7<br>
+        line8<br>
+        <span class="relative">relative9</span><br>
+        line10<br>
+    </div>
+    <div class="column">
+        line11<br>
+        line12<br>
+        <!-- The extra inner span below forces the creation of a transparency layer in Skia to work
+             around optimizations that would cause blending differences between the test and the
+             expectation. -->
+        <span class="opacity">opacity<span>13</span></span><br>
+        line14
+    </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html
new file mode 100644
index 0000000..8bbd920
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<style>
+    .container {
+        margin-right: 4px;
+        position: absolute;
+    }
+    .multicol {
+        width: 110px;
+        height: 150px;
+        border: 5px solid black;
+    }
+    .multicol > div {
+        float: left;
+        width: 50px;
+        height: 50px;
+    }
+
+    .row1_left { background-color: black; }
+    .row1_right { background-color: #0000b0; }
+    .row2_left { background-color: #0000f0; }
+    .row2_right { background-color: #000090; }
+    .row3_left { background-color: #0000d0; }
+    .row3_right { background-color: black; }
+
+    .row1_right,
+    .row2_right,
+    .row3_right {
+        margin-left: 10px;
+    }
+
+    #opacity .row1_right,
+    #opacity .row2_left,
+    #opacity .row2_right,
+    #opacity .row3_left {
+        opacity: 0.99;
+    }
+
+    .pos1 { left: 10px; top: 10px; }
+    .pos2 { left: 150px; top: 10px; }
+    .pos3 { left: 10px; top: 200px; }
+    .pos4 { left: 150px; top: 200px; }
+
+</style>
+<div class="container pos1">
+    Overflow:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <div class="row1_right"></div>
+        <div class="row2_left"></div>
+        <div class="row2_right"></div>
+        <div class="row3_left"></div>
+        <div class="row3_right"></div>
+    </div>
+</div>
+<div class="container pos2">
+    Transforms:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <div class="row1_right"></div>
+        <div class="row2_left"></div>
+        <div class="row2_right"></div>
+        <div class="row3_left"></div>
+        <div class="row3_right"></div>
+    </div>
+</div>
+<div class="container pos3">
+    Relative Pos.:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <div class="row1_right"></div>
+        <div class="row2_left"></div>
+        <div class="row2_right"></div>
+        <div class="row3_left"></div>
+        <div class="row3_right"></div>
+    </div>
+</div>
+<div class="container pos4" id="opacity">
+    Opacity:
+    <div class="multicol">
+        <div class="row1_left"></div>
+        <!-- The extra &nbsp;s below force the creation of transparency layers in Skia to work
+             around optimizations that would cause blending differences between the test and the
+             expectation. -->
+        <div class="row1_right">&nbsp;</div>
+        <div class="row2_left">&nbsp;</div>
+        <div class="row2_right">&nbsp;</div>
+        <div class="row3_left">&nbsp;</div>
+        <div class="row3_right"></div>
+    </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html
new file mode 100644
index 0000000..0b67873
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html
@@ -0,0 +1,6 @@
+<div style="position:relative; width:420px;border:2px solid black; height:200px">
+<!-- The extra &nbsp; below forces the creation of a transparency layer in Skia to work around
+     optimizations that would cause blending differences between the test and the expectation. -->
+<div style="opacity:0.5; position:absolute;width:200px;height:100px;background-color:green;right:0;top:0">&nbsp;</div>
+</div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png
deleted file mode 100644
index 1ebb6e8..0000000
--- a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/nfc/push.html b/third_party/WebKit/LayoutTests/nfc/push.html
index 205f52d..44301ee 100644
--- a/third_party/WebKit/LayoutTests/nfc/push.html
+++ b/third_party/WebKit/LayoutTests/nfc/push.html
@@ -133,14 +133,8 @@
 }, 'Check that provided NFCPushOptions values are correctly converted.');
 
 nfc_test(nfc => {
-  return navigator.nfc.push(test_buffer_data).then(() => {
-    nfc.assertNFCMessagesEqual(test_buffer_data, nfc.mockNFC.pushedMessage());
-  });
-}, 'Push ArrayBuffer with default NFCPushOptions.');
-
-nfc_test(nfc => {
   return navigator.nfc.push(test_text_data)
-      .then(() => { navigator.nfc.cancelPush });
+      .then(() => { return navigator.nfc.cancelPush(); });
 }, 'nfc.cancelPush should succeed if there is pending push operation.');
 
 nfc_test(nfc => {
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png
index c6cabcbb..a92e6a8 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png
deleted file mode 100644
index 44fc4a4..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png
deleted file mode 100644
index 27fbf58..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 5e1fff8..b024e71 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
index 6f98684..8d5f6fd3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 5e1fff8..b024e71 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
index 0acea10..3a881330 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 991aaf7a..07e019c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png
index 84b89da..11b5d71 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png
index 1693941..f409f9e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/transforms/transformed-focused-text-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 991aaf7a..07e019c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png
deleted file mode 100644
index 9243efa..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png
deleted file mode 100644
index 86cf379..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index af00c64c0..56d7e380c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
index 31dd704..ab426ac 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
index 98ce8c5..7e1243a1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index 556507c..8938c8b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
index 70f55312..497919fc 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png
index c57f417b..38e6870 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-focused-text-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index af00c64c0..56d7e380c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png
deleted file mode 100644
index 62b98ea..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png
deleted file mode 100644
index 608b610..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 6eb1bf6..8829276ef 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
index 5b597ed..6837fed 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 6eb1bf6..8829276ef 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 27dad6f..bbb8278 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png
index 855bfdf8..7e9778db 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
index 27dad6f..bbb8278 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/disable-spinvalidation/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/transitions/transition-end-event-create-expected.txt b/third_party/WebKit/LayoutTests/transitions/transition-end-event-create-expected.txt
deleted file mode 100644
index 2fb53bf..0000000
--- a/third_party/WebKit/LayoutTests/transitions/transition-end-event-create-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Test dynamic creation of WebKitTransitionEnd event.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS document.createEvent exists
-
-Test creation of WebKitTransitionEvent
-PASS typeof(ev) is 'object'
-PASS ev.propertyName is ''
-PASS ev.elapsedTime is 0.0
-
-Create a MouseEvent and make sure it doesn't have the WebKitTransitionEnd event properties
-PASS typeof(ev) is 'object'
-PASS ev.propertyName is undefined
-PASS ev.elapsedTime is undefined
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/transitions/transition-end-event-create.html b/third_party/WebKit/LayoutTests/transitions/transition-end-event-create.html
deleted file mode 100644
index b2a51ce7..0000000
--- a/third_party/WebKit/LayoutTests/transitions/transition-end-event-create.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<html>
-<head>
-<script src="../resources/js-test.js"></script>
-</head>
-<body>
-<p id="description"></p>
-<div id="console"></div>
-<script>
-
-description("Test dynamic creation of WebKitTransitionEnd event.");
-
-if (document.createEvent)
-    testPassed("document.createEvent exists");
-else
-    testFailed("document.createEvent missing");
-
-debug("");
-debug("Test creation of WebKitTransitionEvent");
-
-var ev = document.createEvent("WebKitTransitionEvent");
-
-shouldBe("typeof(ev)", "'object'");
-shouldBe("ev.propertyName", "''");
-shouldBe("ev.elapsedTime", "0.0");
-
-debug("");
-debug("Create a MouseEvent and make sure it doesn't have the WebKitTransitionEnd event properties");
-
-ev = document.createEvent("MouseEvent");
-
-shouldBe("typeof(ev)", "'object'");
-shouldBe("ev.propertyName", "undefined");
-shouldBe("ev.elapsedTime", "undefined");
-
-debug("");
-
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/PerformanceTests/Bindings/sequence-conversion-array.html b/third_party/WebKit/PerformanceTests/Bindings/sequence-conversion-array.html
new file mode 100644
index 0000000..d0aa16c
--- /dev/null
+++ b/third_party/WebKit/PerformanceTests/Bindings/sequence-conversion-array.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../resources/runner.js"></script>
+<script>
+let dataArray = [];
+for (let i = 0; i < 100000; i++) {
+  // We are interested in the conversion of JS arrays to C++ sequences, not in
+  // the JS string to C++ string conversion, so just push empty strings into
+  // the array.
+  dataArray.push('');
+}
+
+PerfTestRunner.measureRunsPerSecond({
+  description: "This benchmark measures the overhead of converting JavaScript objects into WebIDL sequences (fast path for arrays)",
+  run: function() {
+    new Blob(dataArray);
+  }});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni
index e4137fd..6a5c991 100644
--- a/third_party/WebKit/Source/bindings/bindings.gni
+++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -137,7 +137,6 @@
                     "core/v8/Transferables.h",
                     "core/v8/ToV8.h",
                     "core/v8/ToV8ForCore.h",
-                    "core/v8/ToV8ForCore.cpp",
                     "core/v8/UseCounterCallback.cpp",
                     "core/v8/UseCounterCallback.h",
                     "core/v8/V8AbstractEventListener.cpp",
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h b/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h
index da4e201..a1a32f1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMDataStore.h
@@ -136,6 +136,12 @@
     wrapper_map_->MarkWrapper(script_wrappable);
   }
 
+  // Dissociates a wrapper, if any, from |script_wrappable|.
+  void UnsetWrapperIfAny(ScriptWrappable* script_wrappable) {
+    DCHECK(!is_main_world_);
+    wrapper_map_->RemoveIfAny(script_wrappable);
+  }
+
   bool SetReturnValueFrom(v8::ReturnValue<v8::Value> return_value,
                           ScriptWrappable* object) {
     if (is_main_world_)
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h
index 976baea..a413b2e8 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperMap.h
@@ -80,6 +80,11 @@
     return true;
   }
 
+  void RemoveIfAny(KeyType* key) {
+    if (ContainsKey(key))
+      map_.Remove(key);
+  }
+
   void Clear() { map_.Clear(); }
 
   void RemoveAndDispose(KeyType* key) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
index 21331ec..b6c72dbb 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp
@@ -31,15 +31,9 @@
 #include "bindings/core/v8/DOMWrapperWorld.h"
 
 #include <memory>
+
 #include "bindings/core/v8/DOMDataStore.h"
-#include "bindings/core/v8/ScriptController.h"
-#include "bindings/core/v8/V8Binding.h"
-#include "bindings/core/v8/V8DOMActivityLogger.h"
-#include "bindings/core/v8/V8DOMWrapper.h"
-#include "bindings/core/v8/V8Window.h"
-#include "bindings/core/v8/WindowProxy.h"
-#include "bindings/core/v8/WrapperTypeInfo.h"
-#include "core/dom/ExecutionContext.h"
+#include "bindings/core/v8/ScriptFunction.h"
 #include "platform/wtf/HashTraits.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/StdLibExtras.h"
@@ -337,4 +331,15 @@
   return kInvalidWorldId;
 }
 
+void DOMWrapperWorld::DissociateDOMWindowWrappersInAllWorlds(
+    ScriptWrappable* script_wrappable) {
+  DCHECK(script_wrappable);
+  DCHECK(IsMainThread());
+
+  script_wrappable->UnsetWrapperIfAny();
+
+  for (auto& world : GetWorldMap().Values())
+    world->DomDataStore().UnsetWrapperIfAny(script_wrappable);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h
index cfc5b05..08c2601 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h
@@ -133,7 +133,6 @@
   int GetWorldId() const { return world_id_; }
   DOMDataStore& DomDataStore() const { return *dom_data_store_; }
 
- public:
   template <typename T>
   void RegisterDOMObjectHolder(v8::Isolate*, T*, v8::Local<v8::Value>);
 
@@ -152,6 +151,30 @@
   // out of DOMWrapperWorld.
   static int GenerateWorldIdForType(WorldType);
 
+  // Dissociates all wrappers in all worlds associated with |script_wrappable|.
+  //
+  // Do not use this function except for DOMWindow.  Only DOMWindow needs to
+  // dissociate wrappers from the ScriptWrappable because of the following two
+  // reasons.
+  //
+  // Reason 1) Case of the main world
+  // A DOMWindow may be collected by Blink GC *before* V8 GC collects the
+  // wrapper because the wrapper object associated with a DOMWindow is a global
+  // proxy, which remains after navigations.  We don't want V8 GC to reset the
+  // weak persistent handle to a wrapper within the DOMWindow
+  // (ScriptWrappable::main_world_wrapper_) *after* Blink GC collects the
+  // DOMWindow because it's use-after-free.  Thus, we need to dissociate the
+  // wrapper in advance.
+  //
+  // Reason 2) Case of isolated worlds
+  // As same, a DOMWindow may be collected before the wrapper gets collected.
+  // A DOMWrapperMap supports mapping from ScriptWrappable* to v8::Global<T>,
+  // and we don't want to leave an entry of an already-dead DOMWindow* to the
+  // persistent handle for the global proxy object, especially considering that
+  // the address to the already-dead DOMWindow* may be re-used.
+  friend class DOMWindow;
+  static void DissociateDOMWindowWrappersInAllWorlds(ScriptWrappable*);
+
   const WorldType world_type_;
   const int world_id_;
   std::unique_ptr<DOMDataStore> dom_data_store_;
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
index 4147067..7a76273 100644
--- a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -221,8 +221,9 @@
   // The global proxy object.  Note this is not the global object.
   v8::Local<v8::Object> global_proxy = context->Global();
   CHECK(global_proxy_ == global_proxy);
-  V8DOMWrapper::SetNativeInfo(GetIsolate(), global_proxy, wrapper_type_info,
-                              window);
+  v8::Local<v8::Object> associated_wrapper =
+      AssociateWithWrapper(window, wrapper_type_info, global_proxy);
+  DCHECK(associated_wrapper == global_proxy);
   // Mark the handle to be traced by Oilpan, since the global proxy has a
   // reference to the DOMWindow.
   global_proxy_.Get().SetWrapperClassId(wrapper_type_info->wrapper_class_id);
@@ -230,9 +231,8 @@
   // The global object, aka window wrapper object.
   v8::Local<v8::Object> window_wrapper =
       global_proxy->GetPrototype().As<v8::Object>();
-  v8::Local<v8::Object> associated_wrapper =
-      AssociateWithWrapper(window, wrapper_type_info, window_wrapper);
-  DCHECK(associated_wrapper == window_wrapper);
+  V8DOMWrapper::SetNativeInfo(GetIsolate(), window_wrapper, wrapper_type_info,
+                              window);
 
   // The prototype object of Window interface.
   v8::Local<v8::Object> window_prototype =
diff --git a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
index 1c90600..3625ce5d 100644
--- a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
@@ -125,9 +125,9 @@
 
   // The global proxy object.  Note this is not the global object.
   v8::Local<v8::Object> global_proxy = global_proxy_.NewLocal(GetIsolate());
-  CHECK(global_proxy_ == global_proxy);
-  V8DOMWrapper::SetNativeInfo(GetIsolate(), global_proxy, wrapper_type_info,
-                              window);
+  v8::Local<v8::Object> associated_wrapper =
+      AssociateWithWrapper(window, wrapper_type_info, global_proxy);
+  DCHECK(associated_wrapper == global_proxy);
   // Mark the handle to be traced by Oilpan, since the global proxy has a
   // reference to the DOMWindow.
   global_proxy_.Get().SetWrapperClassId(wrapper_type_info->wrapper_class_id);
@@ -135,9 +135,8 @@
   // The global object, aka window wrapper object.
   v8::Local<v8::Object> window_wrapper =
       global_proxy->GetPrototype().As<v8::Object>();
-  v8::Local<v8::Object> associated_wrapper =
-      AssociateWithWrapper(window, wrapper_type_info, window_wrapper);
-  DCHECK(associated_wrapper == window_wrapper);
+  V8DOMWrapper::SetNativeInfo(GetIsolate(), window_wrapper, wrapper_type_info,
+                              window);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h
index e6f3e2d..66e7dea 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappable.h
@@ -130,6 +130,14 @@
     return true;
   }
 
+  // Dissociates the wrapper, if any, from this instance.
+  void UnsetWrapperIfAny() {
+    if (ContainsWrapper()) {
+      main_world_wrapper_.Reset();
+      WrapperTypeInfo::WrapperDestroyed();
+    }
+  }
+
   bool IsEqualTo(const v8::Local<v8::Object>& other) const {
     return main_world_wrapper_ == other;
   }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ToV8ForCore.cpp b/third_party/WebKit/Source/bindings/core/v8/ToV8ForCore.cpp
deleted file mode 100644
index 71e07c22..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/ToV8ForCore.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "bindings/core/v8/ToV8ForCore.h"
-
-#include "bindings/core/v8/WindowProxy.h"
-#include "core/events/EventTarget.h"
-#include "core/frame/DOMWindow.h"
-#include "core/frame/Frame.h"
-
-namespace blink {
-
-v8::Local<v8::Value> ToV8(DOMWindow* window,
-                          v8::Local<v8::Object> creation_context,
-                          v8::Isolate* isolate) {
-  // Notice that we explicitly ignore creationContext because the DOMWindow
-  // has its own creationContext.
-
-  if (UNLIKELY(!window))
-    return v8::Null(isolate);
-
-  return window->GlobalProxy(DOMWrapperWorld::Current(isolate));
-}
-
-v8::Local<v8::Value> ToV8(EventTarget* impl,
-                          v8::Local<v8::Object> creation_context,
-                          v8::Isolate* isolate) {
-  if (UNLIKELY(!impl))
-    return v8::Null(isolate);
-
-  if (impl->InterfaceName() == EventTargetNames::DOMWindow)
-    return ToV8(static_cast<DOMWindow*>(impl), creation_context, isolate);
-  return ToV8(static_cast<ScriptWrappable*>(impl), creation_context, isolate);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ToV8ForCore.h b/third_party/WebKit/Source/bindings/core/v8/ToV8ForCore.h
index a41ba2c..cb3fed42 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ToV8ForCore.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ToV8ForCore.h
@@ -8,35 +8,13 @@
 // ToV8() provides C++ -> V8 conversion. Note that ToV8() can return an empty
 // handle. Call sites must check IsEmpty() before using return value.
 
-#include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
-#include "core/CoreExport.h"
 #include "core/dom/NotShared.h"
 #include "v8/include/v8.h"
 
 namespace blink {
 
-class DOMWindow;
 class Dictionary;
-class EventTarget;
-class Node;
-
-inline v8::Local<v8::Value> ToV8(Node* impl,
-                                 v8::Local<v8::Object> creation_context,
-                                 v8::Isolate* isolate) {
-  return ToV8(ScriptWrappable::FromNode(impl), creation_context, isolate);
-}
-
-// Special versions for DOMWindow and EventTarget
-
-CORE_EXPORT v8::Local<v8::Value> ToV8(DOMWindow*,
-                                      v8::Local<v8::Object> creation_context,
-                                      v8::Isolate*);
-CORE_EXPORT v8::Local<v8::Value> ToV8(EventTarget*,
-                                      v8::Local<v8::Object> creation_context,
-                                      v8::Isolate*);
-
-// Dictionary
 
 inline v8::Local<v8::Value> ToV8(const Dictionary& value,
                                  v8::Local<v8::Object> creation_context,
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
index b641638..f783f6a 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
@@ -57,7 +57,6 @@
 
 class DOMWindow;
 class EventListener;
-class EventTarget;
 class ExceptionState;
 class ExecutionContext;
 class FlexibleArrayBufferView;
@@ -195,22 +194,6 @@
   V8SetReturnValue(callback_info, ScriptWrappable::FromNode(impl));
 }
 
-// Special versions for DOMWindow and EventTarget
-
-template <typename CallbackInfo>
-inline void V8SetReturnValue(const CallbackInfo& callback_info,
-                             DOMWindow* impl) {
-  V8SetReturnValue(callback_info, ToV8(impl, callback_info.Holder(),
-                                       callback_info.GetIsolate()));
-}
-
-template <typename CallbackInfo>
-inline void V8SetReturnValue(const CallbackInfo& callback_info,
-                             EventTarget* impl) {
-  V8SetReturnValue(callback_info, ToV8(impl, callback_info.Holder(),
-                                       callback_info.GetIsolate()));
-}
-
 template <typename CallbackInfo, typename T>
 inline void V8SetReturnValue(const CallbackInfo& callback_info,
                              PassRefPtr<T> impl) {
@@ -239,46 +222,6 @@
   V8SetReturnValue(callback_info, wrapper);
 }
 
-template <typename CallbackInfo>
-inline void V8SetReturnValueForMainWorld(const CallbackInfo& callback_info,
-                                         Node* impl) {
-  // Since EventTarget has a special version of ToV8 and V8EventTarget.h
-  // defines its own v8SetReturnValue family, which are slow, we need to
-  // override them with optimized versions for Node and its subclasses.
-  // Without this overload, v8SetReturnValueForMainWorld for Node would be
-  // very slow.
-  //
-  // class hierarchy:
-  //     ScriptWrappable <-- EventTarget <--+-- Node <-- ...
-  //                                        +-- Window
-  // overloads:
-  //     v8SetReturnValueForMainWorld(ScriptWrappable*)
-  //         Optimized and very fast.
-  //     v8SetReturnValueForMainWorld(EventTarget*)
-  //         Uses custom toV8 function and slow.
-  //     v8SetReturnValueForMainWorld(Node*)
-  //         Optimized and very fast.
-  //     v8SetReturnValueForMainWorld(Window*)
-  //         Uses custom toV8 function and slow.
-  V8SetReturnValueForMainWorld(callback_info, ScriptWrappable::FromNode(impl));
-}
-
-// Special versions for DOMWindow and EventTarget
-
-template <typename CallbackInfo>
-inline void V8SetReturnValueForMainWorld(const CallbackInfo& callback_info,
-                                         DOMWindow* impl) {
-  V8SetReturnValue(callback_info, ToV8(impl, callback_info.Holder(),
-                                       callback_info.GetIsolate()));
-}
-
-template <typename CallbackInfo>
-inline void V8SetReturnValueForMainWorld(const CallbackInfo& callback_info,
-                                         EventTarget* impl) {
-  V8SetReturnValue(callback_info, ToV8(impl, callback_info.Holder(),
-                                       callback_info.GetIsolate()));
-}
-
 template <typename CallbackInfo, typename T>
 inline void V8SetReturnValueForMainWorld(const CallbackInfo& callback_info,
                                          PassRefPtr<T> impl) {
@@ -309,24 +252,6 @@
                        wrappable);
 }
 
-// Special versions for DOMWindow and EventTarget
-
-template <typename CallbackInfo>
-inline void V8SetReturnValueFast(const CallbackInfo& callback_info,
-                                 DOMWindow* impl,
-                                 const ScriptWrappable*) {
-  V8SetReturnValue(callback_info, ToV8(impl, callback_info.Holder(),
-                                       callback_info.GetIsolate()));
-}
-
-template <typename CallbackInfo>
-inline void V8SetReturnValueFast(const CallbackInfo& callback_info,
-                                 EventTarget* impl,
-                                 const ScriptWrappable*) {
-  V8SetReturnValue(callback_info, ToV8(impl, callback_info.Holder(),
-                                       callback_info.GetIsolate()));
-}
-
 template <typename CallbackInfo, typename T, typename Wrappable>
 inline void V8SetReturnValueFast(const CallbackInfo& callback_info,
                                  PassRefPtr<T> impl,
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
index c5327db..c997530 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -472,7 +472,9 @@
 
 class DOMWrapperTracer : public v8::PersistentHandleVisitor {
  public:
-  explicit DOMWrapperTracer(Visitor* visitor) : visitor_(visitor) {}
+  explicit DOMWrapperTracer(Visitor* visitor) : visitor_(visitor) {
+    DCHECK(visitor_);
+  }
 
   void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
                              uint16_t class_id) override {
@@ -483,8 +485,8 @@
     const v8::Persistent<v8::Object>& wrapper =
         v8::Persistent<v8::Object>::Cast(*value);
 
-    if (visitor_)
-      ToWrapperTypeInfo(wrapper)->Trace(visitor_, ToScriptWrappable(wrapper));
+    if (ScriptWrappable* script_wrappable = ToScriptWrappable(wrapper))
+      ToWrapperTypeInfo(wrapper)->Trace(visitor_, script_wrappable);
   }
 
  private:
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
index 79bcbb5..60b6ebf1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
@@ -76,7 +76,7 @@
 // security checks for same-origin/cross-origin access to the Window interface.
 // When the check passes (i.e. the access is same-origin), the access is
 // forwarded to the inner global object of the active Document in this
-// WindowProxy's Frame).
+// WindowProxy's Frame.
 //
 // When the security check fails, the access is delegated to the outer global
 // proxy's cross-origin interceptors. The cross-origin interceptors may choose
diff --git a/third_party/WebKit/Source/bindings/core/v8/WrapperTypeInfo.h b/third_party/WebKit/Source/bindings/core/v8/WrapperTypeInfo.h
index 7fd0ba86..cc6597c 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WrapperTypeInfo.h
+++ b/third_party/WebKit/Source/bindings/core/v8/WrapperTypeInfo.h
@@ -180,8 +180,8 @@
   const WrapperTypeInfo* parent_class;
   const unsigned wrapper_type_prototype : 1;  // WrapperTypePrototype
   const unsigned wrapper_class_id : 2;        // WrapperClassId
-  const unsigned
-      active_script_wrappable_inheritance : 1;  // ActiveScriptWrappableInheritance
+  const unsigned  // ActiveScriptWrappableInheritance
+      active_script_wrappable_inheritance : 1;
   const unsigned lifetime : 1;                // Lifetime
 };
 
@@ -199,6 +199,8 @@
       wrapper->GetAlignedPointerFromInternalField(offset));
 }
 
+// The return value can be null if |wrapper| is a global proxy, which points to
+// nothing while a navigation.
 inline ScriptWrappable* ToScriptWrappable(
     const v8::PersistentBase<v8::Object>& wrapper) {
   return GetInternalField<ScriptWrappable, kV8DOMWrapperObjectIndex>(wrapper);
diff --git a/third_party/WebKit/Source/build/scripts/make_event_factory.py b/third_party/WebKit/Source/build/scripts/make_event_factory.py
index edef99a..5e7e933 100755
--- a/third_party/WebKit/Source/build/scripts/make_event_factory.py
+++ b/third_party/WebKit/Source/build/scripts/make_event_factory.py
@@ -92,7 +92,6 @@
             or name == 'TrackEvent'
             or name == 'TransitionEvent'
             or name == 'WebGLContextEvent'
-            or name == 'WebKitTransitionEvent'
             or name == 'WheelEvent')
 
 
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 9e6b7c3..3b0b38b 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -5314,6 +5314,13 @@
                                                         name);
 }
 
+LocalDOMWindow* Document::defaultView() const {
+  // The HTML spec requires to return null if the document is detached from the
+  // DOM.  However, |dom_window_| is not cleared on the detachment.  So, we need
+  // to check |frame_| to tell whether the document is attached or not.
+  return frame_ ? dom_window_ : nullptr;
+}
+
 void Document::FinishedParsing() {
   DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing());
   DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading);
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 5478be0..a81650c 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -408,6 +408,9 @@
   HTMLCollection* WindowNamedItems(const AtomicString& name);
   DocumentNameCollection* DocumentNamedItems(const AtomicString& name);
 
+  // "defaultView" attribute defined in HTML spec.
+  LocalDOMWindow* defaultView() const;
+
   bool IsHTMLDocument() const { return document_classes_ & kHTMLDocumentClass; }
   bool IsXHTMLDocument() const {
     return document_classes_ & kXHTMLDocumentClass;
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl
index 41e4115..136ae2c 100644
--- a/third_party/WebKit/Source/core/dom/Document.idl
+++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -119,7 +119,7 @@
     [CallWith=EnteredWindow, CEReactions, CustomElementCallbacks, RaisesException] void writeln(DOMString... text);
 
     // user interaction
-    [ImplementedAs=domWindow] readonly attribute Window? defaultView;
+    readonly attribute Window? defaultView;
     boolean hasFocus();
     [CEReactions, CustomElementCallbacks, MeasureAs=DocumentDesignMode] attribute DOMString designMode;
     [CEReactions, CustomElementCallbacks, RaisesException] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
index c3b0748..dadbe0f 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -39,23 +39,31 @@
 DOMWindow::~DOMWindow() {
   // The frame must be disconnected before finalization.
   DCHECK(!frame_);
+
+  // Because the wrapper object of a DOMWindow is the global proxy, which may
+  // live much longer than the DOMWindow, we need to dissociate all wrappers
+  // for this instance.
+  DOMWrapperWorld::DissociateDOMWindowWrappersInAllWorlds(this);
 }
 
-v8::Local<v8::Object> DOMWindow::Wrap(v8::Isolate*,
+v8::Local<v8::Object> DOMWindow::Wrap(v8::Isolate* isolate,
                                       v8::Local<v8::Object> creation_context) {
-  LOG(FATAL) << "DOMWindow must never be wrapped with wrap method.  The "
-                "wrappers must be created at WindowProxy::createContext() and "
-                "setupWindowPrototypeChain().";
-  return v8::Local<v8::Object>();
+  // Notice that we explicitly ignore |creation_context| because the DOMWindow
+  // has its own creation context.
+
+  // TODO(yukishiino): Make this function always return the non-empty handle
+  // even if the frame is detached because the global proxy must always exist
+  // per spec.
+  return window_proxy_manager_
+      ->GetWindowProxy(DOMWrapperWorld::Current(isolate))
+      ->GlobalProxyIfNotDetached();
 }
 
 v8::Local<v8::Object> DOMWindow::AssociateWithWrapper(
     v8::Isolate*,
     const WrapperTypeInfo*,
     v8::Local<v8::Object> wrapper) {
-  LOG(FATAL) << "DOMWindow must never be wrapped with wrap method.  The "
-                "wrappers must be created at WindowProxy::createContext() and "
-                "setupWindowPrototypeChain().";
+  NOTREACHED();
   return v8::Local<v8::Object>();
 }
 
@@ -437,14 +445,6 @@
                                                true /* notifyEmbedder */);
 }
 
-v8::Local<v8::Object> DOMWindow::GlobalProxy(DOMWrapperWorld& world) {
-  // TODO(yukishiino): Make this function always return the non-empty handle
-  // even if the frame is detached because the global proxy must always exist
-  // per spec.
-  return window_proxy_manager_->GetWindowProxy(world)
-      ->GlobalProxyIfNotDetached();
-}
-
 InputDeviceCapabilitiesConstants* DOMWindow::GetInputDeviceCapabilities() {
   if (!input_capabilities_)
     input_capabilities_ = new InputDeviceCapabilitiesConstants;
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.h b/third_party/WebKit/Source/core/frame/DOMWindow.h
index 445850e..54bda63 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.h
@@ -109,8 +109,6 @@
 
   bool isSecureContext() const;
 
-  v8::Local<v8::Object> GlobalProxy(DOMWrapperWorld&);
-
   InputDeviceCapabilitiesConstants* GetInputDeviceCapabilities();
 
  protected:
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index 279c1738..5247e37c9 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -385,13 +385,6 @@
       return replacedBy("VREyeParameters.offset",
                         "view matrices provided by VRFrameData");
 
-    case UseCounter::
-        kServiceWorkerRespondToNavigationRequestWithRedirectedResponse:
-      return String::Format(
-          "The service worker responded to the navigation request with a "
-          "redirected response. This will result in an error in %s.",
-          milestoneString(M59));
-
     case UseCounter::kCSSSelectorInternalMediaControlsOverlayCastButton:
       return willBeRemoved(
           "-internal-media-controls-overlay-cast-button selector", M59,
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index a444cbd..c40c8d03 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -901,7 +901,6 @@
     kDocumentCreateEventTrackEvent = 1186,
     kDocumentCreateEventMutationEvents = 1188,
     kDocumentCreateEventSVGEvents = 1190,
-    kDocumentCreateEventWebKitTransitionEvent = 1191,
     kDocumentCreateEventDeviceMotionEvent = 1195,
     kDocumentCreateEventDeviceOrientationEvent = 1196,
     kDocumentCreateEventIDBVersionChangeEvent = 1201,
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index c16060d..32b5099 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -360,6 +360,10 @@
     context_->RestoreCanvasMatrixClipStack(canvas);
 }
 
+void HTMLCanvasElement::SetNeedsCompositingUpdate() {
+  Element::SetNeedsCompositingUpdate();
+}
+
 void HTMLCanvasElement::DoDeferredPaintInvalidation() {
   DCHECK(!dirty_rect_.IsEmpty());
   if (Is2d()) {
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
index 0ca28af7..4aa2a41c 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -204,6 +204,7 @@
   void NotifySurfaceInvalid() override;
   void DidDisableAcceleration() override;
   void RestoreCanvasMatrixClipStack(PaintCanvas*) const override;
+  void SetNeedsCompositingUpdate() override;
 
   // ImageBitmapSource implementation
   IntSize BitmapSourceSize() const override;
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h
index 2cd3ff21..07093ad8 100644
--- a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h
@@ -23,6 +23,7 @@
 
 #include "core/CoreExport.h"
 #include "core/dom/Document.h"
+#include "core/frame/DOMWindow.h"
 #include "core/frame/FrameOwner.h"
 #include "core/html/HTMLElement.h"
 #include "platform/heap/Handle.h"
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index 6bfe79f..63a756b 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -458,19 +458,6 @@
   application_cache_host_->FinishedLoadingMainResource();
   EndWriting();
   ClearMainResourceHandle();
-
-  // Shows the deprecation message and measures the impact of the new security
-  // restriction which disallows responding to navigation requests with
-  // redirected responses in the service worker.
-  // TODO(horo): Remove this when we actually introduce the restriction in
-  // RespondWithObserver.
-  if (response_.WasFetchedViaServiceWorker() &&
-      response_.UrlListViaServiceWorker().size() > 1) {
-    Deprecation::CountDeprecation(
-        frame_,
-        UseCounter::
-            kServiceWorkerRespondToNavigationRequestWithRedirectedResponse);
-  }
 }
 
 bool DocumentLoader::RedirectReceived(
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index a57d2f7c..c72135b 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -365,7 +365,7 @@
   FloatRect float_bounds(FloatPoint(), size);
   const SkRect bounds(float_bounds);
 
-  flags.setShader(MakePaintShaderRecord(
+  flags.setShader(SkShader::MakePictureShader(
       PaintRecordForCurrentFrame(float_bounds, url), SkShader::kRepeat_TileMode,
       SkShader::kRepeat_TileMode, &local_matrix, &bounds));
 
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index 32d3a1a..0df9635 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -10,10 +10,13 @@
 #include "core/dom/Document.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/ImageBitmap.h"
+#include "core/frame/Settings.h"
 #include "core/html/HTMLCanvasElement.h"
 #include "core/html/ImageData.h"
 #include "core/imagebitmap/ImageBitmapOptions.h"
+#include "core/layout/LayoutBoxModelObject.h"
 #include "core/loader/EmptyClients.h"
+#include "core/paint/PaintLayer.h"
 #include "core/testing/DummyPageHolder.h"
 #include "modules/canvas2d/CanvasGradient.h"
 #include "modules/canvas2d/CanvasPattern.h"
@@ -26,7 +29,9 @@
 #include "platform/graphics/test/FakeGLES2Interface.h"
 #include "platform/graphics/test/FakeWebGraphicsContext3DProvider.h"
 #include "platform/loader/fetch/MemoryCache.h"
+#include "platform/testing/TestingPlatformSupport.h"
 #include "platform/wtf/PtrUtil.h"
+#include "public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColorSpaceXform.h"
@@ -166,6 +171,9 @@
   FakeImageSource opaque_bitmap_;
   FakeImageSource alpha_bitmap_;
 
+  // Set this to override frame settings.
+  FrameSettingOverrideFunction override_settings_function_ = nullptr;
+
   StringOrCanvasGradientOrCanvasPattern& OpaqueGradient() {
     return wrap_gradients_->opaque_gradient_;
   }
@@ -200,7 +208,8 @@
   Page::PageClients page_clients;
   FillWithEmptyClients(page_clients);
   dummy_page_holder_ =
-      DummyPageHolder::Create(IntSize(800, 600), &page_clients);
+      DummyPageHolder::Create(IntSize(800, 600), &page_clients, nullptr,
+                              override_settings_function_, nullptr);
   document_ = &dummy_page_holder_->GetDocument();
   document_->documentElement()->setInnerHTML(
       "<body><canvas id='c'></canvas></body>");
@@ -1385,4 +1394,70 @@
       color_correct_rendering_default_mode_runtime_flag);
 }
 
+void OverrideScriptEnabled(Settings& settings) {
+  // Simulate that we allow scripts, so that HTMLCanvasElement uses
+  // LayoutHTMLCanvas.
+  settings.SetScriptEnabled(true);
+}
+
+class CanvasRenderingContext2DTestWithTestingPlatform
+    : public CanvasRenderingContext2DTest {
+ protected:
+  void SetUp() override {
+    override_settings_function_ = &OverrideScriptEnabled;
+    platform_->AdvanceClockSeconds(1.);  // For non-zero DocumentParserTimings.
+    CanvasRenderingContext2DTest::SetUp();
+    GetDocument().View()->UpdateLayout();
+  }
+
+  void RunUntilIdle() { platform_->RunUntilIdle(); }
+
+  ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
+      platform_;
+};
+
+// https://crbug.com/708445: When the Canvas2DLayerBridge hibernates or wakes up
+// from hibernation, the compositing reasons for the canvas element may change.
+// In these cases, the element should request a compositing update.
+TEST_F(CanvasRenderingContext2DTestWithTestingPlatform,
+       ElementRequestsCompositingUpdateOnHibernateAndWakeUp) {
+  CreateContext(kNonOpaque);
+  FakeGLES2Interface gl;
+  std::unique_ptr<FakeWebGraphicsContext3DProvider> context_provider(
+      new FakeWebGraphicsContext3DProvider(&gl));
+  IntSize size(300, 300);
+  RefPtr<Canvas2DLayerBridge> bridge =
+      MakeBridge(std::move(context_provider), size,
+                 Canvas2DLayerBridge::kEnableAcceleration);
+  // Force hibernatation to occur in an immediate task.
+  bridge->DontUseIdleSchedulingForTesting();
+  std::unique_ptr<Canvas2DImageBufferSurface> surface(
+      new Canvas2DImageBufferSurface(bridge, size));
+  CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
+
+  EXPECT_TRUE(CanvasElement().Buffer()->IsAccelerated());
+
+  EXPECT_TRUE(CanvasElement().GetLayoutBoxModelObject());
+  PaintLayer* layer = CanvasElement().GetLayoutBoxModelObject()->Layer();
+  EXPECT_TRUE(layer);
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // Hide element to trigger hibernation (if enabled).
+  GetDocument().GetPage()->SetVisibilityState(kPageVisibilityStateHidden,
+                                              false);
+  RunUntilIdle();  // Run hibernation task.
+  // If enabled, hibernation should cause compositing update.
+  EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED,
+            layer->NeedsCompositingInputsUpdate());
+
+  GetDocument().View()->UpdateAllLifecyclePhases();
+  EXPECT_FALSE(layer->NeedsCompositingInputsUpdate());
+
+  // Wake up again, which should request a compositing update synchronously.
+  GetDocument().GetPage()->SetVisibilityState(kPageVisibilityStateVisible,
+                                              false);
+  EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED,
+            layer->NeedsCompositingInputsUpdate());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index 1cef1ac..d29e539 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -528,6 +528,9 @@
 #if USE_IOSURFACE_FOR_2D_CANVAS
   ClearCHROMIUMImageCache();
 #endif  // USE_IOSURFACE_FOR_2D_CANVAS
+  // shouldBeDirectComposited() may have changed.
+  if (image_buffer_)
+    image_buffer_->SetNeedsCompositingUpdate();
   logger_->DidStartHibernating();
 }
 
@@ -607,11 +610,15 @@
                                      &copy_paint);
     hibernation_image_.reset();
 
-    if (image_buffer_)
+    if (image_buffer_) {
       image_buffer_->UpdateGPUMemoryUsage();
 
-    if (image_buffer_ && !is_deferral_enabled_)
-      image_buffer_->ResetCanvas(surface_paint_canvas_.get());
+      if (!is_deferral_enabled_)
+        image_buffer_->ResetCanvas(surface_paint_canvas_.get());
+
+      // shouldBeDirectComposited() may have changed.
+      image_buffer_->SetNeedsCompositingUpdate();
+    }
   }
 
   return surface_.get();
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index b3677e5..ee46ab4 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -599,6 +599,11 @@
   UpdateGPUMemoryUsage();
 }
 
+void ImageBuffer::SetNeedsCompositingUpdate() {
+  if (client_)
+    client_->SetNeedsCompositingUpdate();
+}
+
 bool ImageDataBuffer::EncodeImage(const String& mime_type,
                                   const double& quality,
                                   Vector<unsigned char>* encoded_image) const {
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
index 4f358ba..0d18f76 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
@@ -176,6 +176,8 @@
   void DisableAcceleration();
   void SetSurface(std::unique_ptr<ImageBufferSurface>);
 
+  void SetNeedsCompositingUpdate();
+
   WeakPtrFactory<ImageBuffer> weak_ptr_factory_;
 
  protected:
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBufferClient.h b/third_party/WebKit/Source/platform/graphics/ImageBufferClient.h
index b23b59f..55b567b 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBufferClient.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageBufferClient.h
@@ -42,6 +42,7 @@
   virtual void NotifySurfaceInvalid() = 0;
   virtual void DidDisableAcceleration() = 0;
   virtual void RestoreCanvasMatrixClipStack(PaintCanvas*) const = 0;
+  virtual void SetNeedsCompositingUpdate() = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
index a215a535..75f9fdd2 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
@@ -23,12 +23,11 @@
   list->AppendClipPathItem(clip_path_, true);
 }
 
-int BeginClipPathDisplayItem::NumberOfSlowPaths() const {
+void BeginClipPathDisplayItem::AnalyzeForGpuRasterization(
+    SkPictureGpuAnalyzer& analyzer) const {
   // Temporarily disabled (pref regressions due to GPU veto stickiness:
   // http://crbug.com/603969).
   // analyzer.analyzeClipPath(m_clipPath, SkRegion::kIntersect_Op, true);
-  // TODO(enne): fixup this code to return an int.
-  return 0;
 }
 
 void EndClipPathDisplayItem::Replay(GraphicsContext& context) const {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
index 3952c87..42434ae 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.h
@@ -24,7 +24,7 @@
   void AppendToWebDisplayItemList(const IntRect&,
                                   WebDisplayItemList*) const override;
 
-  int NumberOfSlowPaths() const override;
+  void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override;
 
  private:
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
index 7eac3491..cdcd8fd 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
@@ -29,8 +29,58 @@
 CompositingRecorder::~CompositingRecorder() {
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
     return;
-  graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>(
-      client_);
+  // If the end of the current display list is of the form
+  // [BeginCompositingDisplayItem] [DrawingDisplayItem], then fold the
+  // BeginCompositingDisplayItem into a new DrawingDisplayItem that replaces
+  // them both. This allows Skia to optimize for the case when the
+  // BeginCompositingDisplayItem represents a simple opacity/color that can be
+  // merged into the opacity/color of the drawing. See crbug.com/628831 for more
+  // details.
+  PaintController& paint_controller = graphics_context_.GetPaintController();
+  const DisplayItem* last_display_item = paint_controller.LastDisplayItem(0);
+  const DisplayItem* second_to_last_display_item =
+      paint_controller.LastDisplayItem(1);
+  // TODO(chrishtr): remove the call to LastDisplayItemIsSubsequenceEnd when
+  // https://codereview.chromium.org/2768143002 lands.
+  if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() && last_display_item &&
+      second_to_last_display_item && last_display_item->DrawsContent() &&
+      second_to_last_display_item->GetType() ==
+          DisplayItem::kBeginCompositing &&
+      !paint_controller.LastDisplayItemIsSubsequenceEnd()) {
+    FloatRect cull_rect(
+        ((DrawingDisplayItem*)last_display_item)->GetPaintRecord()->cullRect());
+    const DisplayItemClient& display_item_client = last_display_item->Client();
+    DisplayItem::Type display_item_type = last_display_item->GetType();
+
+    // Re-record the last two DisplayItems into a new drawing. The new item
+    // cannot be cached, because it is a mutation of the DisplayItem the client
+    // thought it was painting.
+    paint_controller.BeginSkippingCache();
+    {
+#if DCHECK_IS_ON()
+      // In the recorder's scope we remove the last two display items which
+      // are combined into a new drawing.
+      DisableListModificationCheck disabler;
+#endif
+      DrawingRecorder new_recorder(graphics_context_, display_item_client,
+                                   display_item_type, cull_rect);
+      DCHECK(!DrawingRecorder::UseCachedDrawingIfPossible(
+          graphics_context_, display_item_client, display_item_type));
+
+      second_to_last_display_item->Replay(graphics_context_);
+      last_display_item->Replay(graphics_context_);
+      EndCompositingDisplayItem(client_).Replay(graphics_context_);
+
+      // Remove the DrawingDisplayItem.
+      paint_controller.RemoveLastDisplayItem();
+      // Remove the BeginCompositingDisplayItem.
+      paint_controller.RemoveLastDisplayItem();
+    }
+    paint_controller.EndSkippingCache();
+  } else {
+    graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>(
+        client_);
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
index d5f344e6..a9afcd1 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -17,6 +17,8 @@
 #include "platform/wtf/text/WTFString.h"
 #endif
 
+class SkPictureGpuAnalyzer;
+
 namespace blink {
 
 class GraphicsContext;
@@ -335,7 +337,7 @@
   virtual bool DrawsContent() const { return false; }
 
   // Override to implement specific analysis strategies.
-  virtual int NumberOfSlowPaths() const { return 0; }
+  virtual void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const {}
 
 #ifndef NDEBUG
   static WTF::String TypeAsDebugString(DisplayItem::Type);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
index 4fe7853..474a7d12 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -7,6 +7,7 @@
 #include "platform/graphics/LoggingCanvas.h"
 #include "platform/graphics/paint/DrawingDisplayItem.h"
 #include "platform/graphics/paint/PaintChunk.h"
+#include "third_party/skia/include/core/SkPictureAnalyzer.h"
 
 #ifndef NDEBUG
 #include "platform/wtf/text/WTFString.h"
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
index 7c14717..2a17f3d 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
@@ -10,6 +10,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkPictureAnalyzer.h"
 
 namespace blink {
 
@@ -29,8 +30,14 @@
   return record_.get();
 }
 
-int DrawingDisplayItem::NumberOfSlowPaths() const {
-  return record_ ? record_->numSlowPaths() : 0;
+void DrawingDisplayItem::AnalyzeForGpuRasterization(
+    SkPictureGpuAnalyzer& analyzer) const {
+  // TODO(enne): Need an SkPictureGpuAnalyzer on PictureRecord.
+  // This is a bit overkill to ToSkPicture a record just to get
+  // numSlowPaths.
+  if (!record_)
+    return;
+  analyzer.analyzePicture(ToSkPicture(record_).get());
 }
 
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
index 3dedbcbd..e5f989f8 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.h
@@ -41,7 +41,7 @@
     return known_to_be_opaque_;
   }
 
-  int NumberOfSlowPaths() const override;
+  void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override;
 
  private:
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
index d3b7553..e26681df 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -16,8 +16,6 @@
 #include <stdio.h>
 #endif
 
-static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5;
-
 namespace blink {
 
 void PaintController::SetTracksRasterInvalidations(bool value) {
@@ -537,7 +535,7 @@
       !new_display_item_list_.IsEmpty())
     GenerateChunkRasterInvalidationRects(new_paint_chunks_.LastChunk());
 
-  int num_slow_paths = 0;
+  SkPictureGpuAnalyzer gpu_analyzer;
 
   current_cache_generation_ =
       DisplayItemClient::CacheGenerationOrInvalidationReason::Next();
@@ -556,8 +554,8 @@
   Vector<const DisplayItemClient*> skipped_cache_clients;
   for (const auto& item : new_display_item_list_) {
     // No reason to continue the analysis once we have a veto.
-    if (num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto)
-      num_slow_paths += item.NumberOfSlowPaths();
+    if (gpu_analyzer.suitableForGpuRasterization())
+      item.AnalyzeForGpuRasterization(gpu_analyzer);
 
     // TODO(wkorman): Only compute and append visual rect for drawings.
     new_display_item_list_.AppendVisualRect(
@@ -595,7 +593,7 @@
   new_display_item_list_.ShrinkToFit();
   current_paint_artifact_ = PaintArtifact(
       std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(),
-      num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto);
+      gpu_analyzer.suitableForGpuRasterization());
   ResetCurrentListIndices();
   out_of_order_item_indices_.Clear();
   out_of_order_chunk_indices_.Clear();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index 5a09e2d8..f4e0aae 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -2273,6 +2273,40 @@
     DisplayItemClient::EndShouldKeepAliveAllClients();
 #endif
   }
+
+  void TestFoldCompositingDrawingInSubsequence() {
+    FakeDisplayItemClient container("container");
+    FakeDisplayItemClient content("content");
+    GraphicsContext context(GetPaintController());
+
+    {
+      SubsequenceRecorder subsequence(context, container);
+      CompositingRecorder compositing(context, content, SkBlendMode::kSrc, 0.5);
+      DrawRect(context, content, kBackgroundDrawingType,
+               FloatRect(100, 100, 300, 300));
+    }
+    GetPaintController().CommitNewDisplayItems();
+    EXPECT_EQ(
+        1u,
+        GetPaintController().GetPaintArtifact().GetDisplayItemList().size());
+
+    {
+      EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
+          context, container));
+      SubsequenceRecorder subsequence(context, container);
+      CompositingRecorder compositing(context, content, SkBlendMode::kSrc, 0.5);
+      DrawRect(context, content, kBackgroundDrawingType,
+               FloatRect(100, 100, 300, 300));
+    }
+    GetPaintController().CommitNewDisplayItems();
+    EXPECT_EQ(
+        1u,
+        GetPaintController().GetPaintArtifact().GetDisplayItemList().size());
+
+#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
+    DisplayItemClient::EndShouldKeepAliveAllClients();
+#endif
+  }
 };
 
 TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawing) {
@@ -2322,6 +2356,11 @@
   TestInvalidationInSubsequence();
 }
 
+TEST_F(PaintControllerUnderInvalidationTest,
+       FoldCompositingDrawingInSubsequence) {
+  TestFoldCompositingDrawingInSubsequence();
+}
+
 #endif  // defined(GTEST_HAS_DEATH_TEST) && !OS(ANDROID)
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
index e3eada5..6379d6a 100644
--- a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
+++ b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
@@ -24,7 +24,6 @@
 #include "platform/graphics/paint/PaintCanvas.h"
 #include "platform/mac/ThemeMac.h"
 #include "platform_canvas.h"
-#include "third_party/skia/include/core/SkRegion.h"
 
 namespace blink {
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c731d207..62ad949 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -94950,7 +94950,7 @@
   <int value="1188" label="DocumentCreateEventMutationEvents"/>
   <int value="1189" label="DocumentCreateEventOrientationEvent"/>
   <int value="1190" label="DocumentCreateEventSVGEvents"/>
-  <int value="1191" label="DocumentCreateEventWebKitTransitionEvent"/>
+  <int value="1191" label="OBSOLETE_DocumentCreateEventWebKitTransitionEvent"/>
   <int value="1192" label="DocumentCreateEventBeforeInstallPromptEvent"/>
   <int value="1193" label="DocumentCreateEventSyncEvent"/>
   <int value="1194" label="DocumentCreateEventDeviceLightEvent"/>
diff --git a/tools/perf/page_sets/system_health/searching_stories.py b/tools/perf/page_sets/system_health/searching_stories.py
index a4cc8d3..ac1666af 100644
--- a/tools/perf/page_sets/system_health/searching_stories.py
+++ b/tools/perf/page_sets/system_health/searching_stories.py
@@ -6,6 +6,8 @@
 from page_sets.system_health import story_tags
 from page_sets.system_health import system_health_story
 
+from telemetry import decorators
+
 from devil.android.sdk import keyevent # pylint: disable=import-error
 
 
@@ -67,6 +69,7 @@
     action_runner.ScrollPage(use_touch=True, distance=500)
 
 
+@decorators.Disabled('android')  # crbug.com/712590
 class MobileNewTabPageStory(system_health_story.SystemHealthStory):
   """Story that loads new tab page and performs searches.
 
diff --git a/ui/file_manager/externs/compiled_resources2.gyp b/ui/file_manager/externs/compiled_resources2.gyp
index a205351..e1a3cc9b 100644
--- a/ui/file_manager/externs/compiled_resources2.gyp
+++ b/ui/file_manager/externs/compiled_resources2.gyp
@@ -104,6 +104,10 @@
       'includes': ['../../../third_party/closure_compiler/include_js.gypi'],
     },
     {
+      'target_name': 'menu_item_update_event',
+      'includes': ['../../../third_party/closure_compiler/include_js.gypi'],
+    },
+    {
       'target_name': 'metadata_parser_interface',
       'includes': ['../../../third_party/closure_compiler/include_js.gypi'],
     },
diff --git a/ui/file_manager/externs/menu_item_update_event.js b/ui/file_manager/externs/menu_item_update_event.js
new file mode 100644
index 0000000..0666a9a
--- /dev/null
+++ b/ui/file_manager/externs/menu_item_update_event.js
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ * @extends {Event}
+ */
+var MenuItemUpdateEvent = function() {};
+
+/**
+ * @type {!cr.ui.MenuButton}
+ */
+MenuItemUpdateEvent.prototype.menuButton;
diff --git a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
index 04b44c6..21750966 100644
--- a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
+++ b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
@@ -188,6 +188,7 @@
           '../../../externs/file_operation_progress_event.js',
           '../../../externs/html_menu_item_element.js',
           '../../../externs/launcher_search_provider.js',
+          '../../../externs/menu_item_update_event.js',
           '../../../externs/paper_elements.js',
           '../../../externs/platform.js',
           '../../../externs/volume_info.js',
diff --git a/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp b/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
index 6629da8..8e8d4ae 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
+++ b/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
@@ -11,10 +11,21 @@
 #      ],
 #      'includes': ['../../../../compile_js2.gypi'],
 #    },
-#    {
-#      'target_name': 'banners',
-#      'includes': ['../../../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'banners',
+      'dependencies': [
+        '../../../../externs/compiled_resources2.gyp:chrome_echo_private',
+        '../../../common/js/compiled_resources2.gyp:util',
+        '../../../common/js/compiled_resources2.gyp:volume_manager_common',
+        '../compiled_resources2.gyp:directory_model',
+        '../compiled_resources2.gyp:volume_manager_wrapper',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+        '<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:event_target',
+        '<(EXTERNS_GYP):chrome_extensions',
+        '<(EXTERNS_GYP):file_manager_private',
+      ],
+      'includes': ['../../../../compile_js2.gypi'],
+    },
     {
       'target_name': 'combobutton',
       'dependencies': [
@@ -53,10 +64,24 @@
       ],
       'includes': ['../../../../compile_js2.gypi'],
     },
-#    {
-#      'target_name': 'directory_tree',
-#      'includes': ['../../../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'directory_tree',
+      'dependencies': [
+        '../../../../externs/compiled_resources2.gyp:menu_item_update_event',
+        '../../../background/js/compiled_resources2.gyp:file_operation_manager',
+        '../../../common/js/compiled_resources2.gyp:util',
+        '../../../common/js/compiled_resources2.gyp:volume_manager_common',
+        '../compiled_resources2.gyp:directory_model',
+        '../compiled_resources2.gyp:navigation_list_model',
+        '../compiled_resources2.gyp:volume_manager_wrapper',
+        '../metadata/compiled_resources2.gyp:metadata_model',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:context_menu_button',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:context_menu_handler',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:menu',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:tree',
+      ],
+      'includes': ['../../../../compile_js2.gypi'],
+    },
     {
       'target_name': 'drag_selector',
       'dependencies': [
@@ -221,10 +246,18 @@
       ],
       'includes': ['../../../../compile_js2.gypi'],
     },
-#    {
-#      'target_name': 'providers_menu',
-#      'includes': ['../../../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'providers_menu',
+      'dependencies': [
+        '../../../../externs/compiled_resources2.gyp:menu_item_update_event',
+        '../compiled_resources2.gyp:providers_model',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:menu',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:position_util',
+        'directory_tree',
+        'files_menu',
+      ],
+      'includes': ['../../../../compile_js2.gypi'],
+    },
 #    {
 #      'target_name': 'search_box',
 #      'includes': ['../../../../compile_js2.gypi'],
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
index 489ee96..d407e8f 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -988,7 +988,7 @@
  */
 MenuItem.prototype.activate = function() {
   // Dispatch an event to update the menu (if updatable).
-  var updateEvent = new Event('update');
+  var updateEvent = /** @type {MenuItemUpdateEvent} */ (new Event('update'));
   updateEvent.menuButton = this.menuButton_;
   this.menuButton_.menu.dispatchEvent(updateEvent);
 
@@ -1368,14 +1368,14 @@
 
 /**
  * Invoked when a directory is changed.
- * @param {!Event} event Event.
+ * @param {!FileWatchEvent} event Event.
  * @private
  */
 DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) {
   if (event.eventType !== 'changed' || !event.entry)
     return;
 
-  this.updateTreeByEntry_(event.entry);
+  this.updateTreeByEntry_(/** @type{!Entry} */ (event.entry));
 };
 
 /**
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index ce75522..c77bdf4 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -5,7 +5,6 @@
 #import "ui/views/controls/scrollbar/cocoa_scroll_bar.h"
 
 #import "base/mac/sdk_forward_declarations.h"
-#include "cc/paint/paint_shader.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 #include "ui/compositor/layer.h"
diff --git a/ui/webui/resources/js/cr/ui/compiled_resources2.gyp b/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
index 6f0eb1d..dd8aeed5 100644
--- a/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
+++ b/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
@@ -28,6 +28,25 @@
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
+      'target_name': 'context_menu_button',
+      'dependencies': [
+        'menu_button',
+      ],
+      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
+      'target_name': 'context_menu_handler',
+      'dependencies': [
+         '../../compiled_resources2.gyp:cr',
+         '../compiled_resources2.gyp:event_target',
+         '../compiled_resources2.gyp:ui',
+         'menu',
+         'menu_button',
+         'position_util',
+      ],
+      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'dialogs',
       'dependencies': [
         '../../compiled_resources2.gyp:cr',
@@ -187,5 +206,14 @@
       ],
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
+    {
+      'target_name': 'tree',
+      'dependencies': [
+        '../../compiled_resources2.gyp:cr',
+        '../../compiled_resources2.gyp:util',
+        '../compiled_resources2.gyp:ui',
+      ],
+      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
   ],
 }