diff --git a/DEPS b/DEPS
index e3abd6e..1c592e8d 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': '9f6be2e9e4279586cf484b669d1fc701c31a7fe2',
+  'v8_revision': '83d9ade42120db9133e0c94d4d193386d69456f8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '012ae898a069bda7afbfdad4eb4c8ba042b68dc7',
+  'pdfium_revision': '2bbb55162f0c9490a2085ed6eaa38038a7605609',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -232,7 +232,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '9cdb5386506ddbff3cbb096e9d2292c632ad915c', # commit position 17863
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'ce4e632d4dd043996afe4402d4edf27186b33032', # commit position 17884
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 02f2a6a..c7619a9 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -743,10 +743,15 @@
     ProcessId pid = kv.first;  // kNullProcessId for the current process.
     ProcessMemoryDump* process_memory_dump = kv.second.get();
 
-    bool added_to_trace = tracing_observer_->AddDumpToTraceIfEnabled(
-        &pmd_async_state->req_args, pid, process_memory_dump);
+    // SUMMARY_ONLY dumps are just return the summarized result in the
+    // ProcessMemoryDumpCallback. These shouldn't be added to the trace to
+    // avoid confusing trace consumers.
+    if (pmd_async_state->req_args.dump_type != MemoryDumpType::SUMMARY_ONLY) {
+      bool added_to_trace = tracing_observer_->AddDumpToTraceIfEnabled(
+          &pmd_async_state->req_args, pid, process_memory_dump);
 
-    dump_successful = dump_successful && added_to_trace;
+      dump_successful = dump_successful && added_to_trace;
+    }
 
     // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203
     // Don't try to fill the struct in detailed mode since it is hard to avoid
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 732b5c8..946b5b64 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -221,6 +221,23 @@
   unsigned num_of_post_tasks_;
 };
 
+std::unique_ptr<trace_analyzer::TraceAnalyzer> GetDeserializedTrace() {
+  // Flush the trace into JSON.
+  trace_event::TraceResultBuffer buffer;
+  TraceResultBuffer::SimpleOutput trace_output;
+  buffer.SetOutputCallback(trace_output.GetCallback());
+  RunLoop run_loop;
+  buffer.Start();
+  trace_event::TraceLog::GetInstance()->Flush(
+      Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
+  run_loop.Run();
+  buffer.Finish();
+
+  // Analyze the JSON.
+  return WrapUnique(
+      trace_analyzer::TraceAnalyzer::Create(trace_output.json_output));
+}
+
 }  // namespace
 
 class MemoryDumpManagerTest : public testing::Test {
@@ -1080,20 +1097,8 @@
                            MemoryDumpLevelOfDetail::DETAILED);
   DisableTracing();
 
-  // Flush the trace into JSON.
-  trace_event::TraceResultBuffer buffer;
-  TraceResultBuffer::SimpleOutput trace_output;
-  buffer.SetOutputCallback(trace_output.GetCallback());
-  RunLoop run_loop;
-  buffer.Start();
-  trace_event::TraceLog::GetInstance()->Flush(
-      Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
-  run_loop.Run();
-  buffer.Finish();
-
-  // Analyze the JSON.
-  std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer = WrapUnique(
-      trace_analyzer::TraceAnalyzer::Create(trace_output.json_output));
+  std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer =
+      GetDeserializedTrace();
   trace_analyzer::TraceEventVector events;
   analyzer->FindEvents(Query::EventPhaseIs(TRACE_EVENT_PHASE_MEMORY_DUMP),
                        &events);
@@ -1107,6 +1112,37 @@
   ASSERT_EQ(events[0]->id, events[2]->id);
 }
 
+TEST_F(MemoryDumpManagerTest, SummaryOnlyDumpsArentAddedToTrace) {
+  using trace_analyzer::Query;
+
+  InitializeMemoryDumpManager(false /* is_coordinator */);
+  SetDumpProviderWhitelistForTesting(kTestMDPWhitelist);
+
+  // Standard provider with default options (create dump for current process).
+  MockMemoryDumpProvider mdp;
+  RegisterDumpProvider(&mdp, nullptr, kDefaultOptions, kWhitelistedMDPName);
+
+  EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
+  EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)).Times(2);
+  EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(2).WillRepeatedly(Return(true));
+  RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
+                           MemoryDumpLevelOfDetail::BACKGROUND);
+  RequestGlobalDumpAndWait(MemoryDumpType::SUMMARY_ONLY,
+                           MemoryDumpLevelOfDetail::BACKGROUND);
+  DisableTracing();
+
+  std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer =
+      GetDeserializedTrace();
+  trace_analyzer::TraceEventVector events;
+  analyzer->FindEvents(Query::EventPhaseIs(TRACE_EVENT_PHASE_MEMORY_DUMP),
+                       &events);
+
+  ASSERT_EQ(1u, events.size());
+  ASSERT_TRUE(trace_analyzer::CountMatches(
+      events, Query::EventNameIs(MemoryDumpTypeToString(
+                  MemoryDumpType::EXPLICITLY_TRIGGERED))));
+}
+
 // Tests the basics of the UnregisterAndDeleteDumpProviderSoon(): the
 // unregistration should actually delete the providers and not leak them.
 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoon) {
diff --git a/base/trace_event/memory_dump_request_args.cc b/base/trace_event/memory_dump_request_args.cc
index 0b525d4..633b535 100644
--- a/base/trace_event/memory_dump_request_args.cc
+++ b/base/trace_event/memory_dump_request_args.cc
@@ -18,6 +18,8 @@
       return "explicitly_triggered";
     case MemoryDumpType::PEAK_MEMORY_USAGE:
       return "peak_memory_usage";
+    case MemoryDumpType::SUMMARY_ONLY:
+      return "summary_only";
   }
   NOTREACHED();
   return "unknown";
@@ -30,6 +32,8 @@
     return MemoryDumpType::EXPLICITLY_TRIGGERED;
   if (str == "peak_memory_usage")
     return MemoryDumpType::PEAK_MEMORY_USAGE;
+  if (str == "summary_only")
+    return MemoryDumpType::SUMMARY_ONLY;
   NOTREACHED();
   return MemoryDumpType::LAST;
 }
diff --git a/base/trace_event/memory_dump_request_args.h b/base/trace_event/memory_dump_request_args.h
index 0f42a1853..bc5cc38e 100644
--- a/base/trace_event/memory_dump_request_args.h
+++ b/base/trace_event/memory_dump_request_args.h
@@ -28,7 +28,8 @@
   PERIODIC_INTERVAL,     // Dumping memory at periodic intervals.
   EXPLICITLY_TRIGGERED,  // Non maskable dump request.
   PEAK_MEMORY_USAGE,     // Dumping memory at detected peak total memory usage.
-  LAST = PEAK_MEMORY_USAGE  // For IPC macros.
+  SUMMARY_ONLY,          // Calculate just the summary & don't add to the trace.
+  LAST = SUMMARY_ONLY
 };
 
 // Tells the MemoryDumpProvider(s) how much detailed their dumps should be.
diff --git a/base/trace_event/memory_tracing_observer.cc b/base/trace_event/memory_tracing_observer.cc
index 3130b20..a5b60e4 100644
--- a/base/trace_event/memory_tracing_observer.cc
+++ b/base/trace_event/memory_tracing_observer.cc
@@ -72,6 +72,8 @@
   if (!IsMemoryInfraTracingEnabled())
     return false;
 
+  CHECK_NE(MemoryDumpType::SUMMARY_ONLY, req_args->dump_type);
+
   const uint64_t dump_guid = req_args->dump_guid;
 
   std::unique_ptr<TracedValue> traced_value(new TracedValue);
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 6b7472f4..fa0bd60 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -652,6 +652,8 @@
     "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",
@@ -769,6 +771,7 @@
     "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",
@@ -939,6 +942,7 @@
     "//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 3af5dee..11f9fdac 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -32,13 +32,19 @@
     "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 8359948..c1b069548 100644
--- a/cc/paint/display_item_list.cc
+++ b/cc/paint/display_item_list.cc
@@ -100,9 +100,13 @@
       if (canvas->quickReject(item.picture->cullRect()))
         break;
 
-      // SkPicture always does a wrapping save/restore on the canvas, so it is
-      // not necessary here.
+      // 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();
       item.picture->playback(canvas, callback);
+      canvas->restore();
       break;
     }
     case DisplayItem::FLOAT_CLIP: {
@@ -176,6 +180,33 @@
   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;
@@ -184,14 +215,33 @@
 
   std::vector<size_t> indices;
   rtree_.Search(canvas_playback_rect, &indices);
-  for (size_t index : indices) {
-    RasterItem(items_[index], canvas, callback);
-
+  for (size_t i = 0; i < indices.size(); ++i) {
     // 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 f1b9e75..b166229c6 100644
--- a/cc/paint/display_item_list_unittest.cc
+++ b/cc/paint/display_item_list_unittest.cc
@@ -17,16 +17,17 @@
 #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"
@@ -80,6 +81,19 @@
   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);
@@ -704,4 +718,110 @@
   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 86348f0..e1fa9d0 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -11,19 +11,25 @@
 #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:
+  PaintCanvas() {}
   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
@@ -36,7 +42,7 @@
 
   virtual int save() = 0;
   virtual int saveLayer(const SkRect* bounds, const PaintFlags* flags) = 0;
-  virtual int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) = 0;
+  virtual int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) = 0;
 
   virtual void restore() = 0;
   virtual int getSaveCount() const = 0;
@@ -87,6 +93,8 @@
   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,
@@ -180,6 +188,9 @@
  protected:
   friend class PaintSurface;
   friend class PaintRecorder;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PaintCanvas);
 };
 
 class CC_PAINT_EXPORT PaintCanvasAutoRestore {
diff --git a/cc/paint/paint_flags.cc b/cc/paint/paint_flags.cc
new file mode 100644
index 0000000..e16a8bb
--- /dev/null
+++ b/cc/paint/paint_flags.cc
@@ -0,0 +1,42 @@
+// 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 b7e96c6..37b460d6 100644
--- a/cc/paint/paint_flags.h
+++ b/cc/paint/paint_flags.h
@@ -7,7 +7,6 @@
 
 #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"
@@ -19,6 +18,8 @@
 
 namespace cc {
 
+using PaintShader = SkShader;
+
 class CC_PAINT_EXPORT PaintFlags {
  public:
   enum Style {
@@ -198,6 +199,14 @@
     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 70644ed..d34d05d 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -12,6 +12,9 @@
     : 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 0ed1edd..c772316 100644
--- a/cc/paint/paint_image.h
+++ b/cc/paint/paint_image.h
@@ -23,6 +23,7 @@
   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
new file mode 100644
index 0000000..fa62a41
--- /dev/null
+++ b/cc/paint/paint_op_buffer.cc
@@ -0,0 +1,566 @@
+// 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
new file mode 100644
index 0000000..c874590
--- /dev/null
+++ b/cc/paint/paint_op_buffer.h
@@ -0,0 +1,799 @@
+// 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 "base/memory/aligned_memory.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 const_cast<PaintOp*>(first_op_.data_as<PaintOp>());
+  }
+
+  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 {
+          // |first_op_| is aligned to LargestPaintOp. If T needs a smaller
+          // alignment, this is okay because it will be a factor of the actual
+          // alignment being used (as they are always a power of 2). If T needs
+          // a larger alignment, that is bad and we should use T to choose the
+          // alignment of |first_op_| instead.
+          static_assert(ALIGNOF(T) <= ALIGNOF(LargestPaintOp), "");
+          auto* op = reinterpret_cast<T*>(first_op_.data_as<T>());
+          new (op) T{std::forward<Args>(args)...};
+          op->type = static_cast<uint32_t>(T::kType);
+          op->skip = 0;
+          AnalyzeAddedOp(op);
+          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;
+    AnalyzeAddedOp(op);
+    op_count_++;
+    return op;
+  }
+
+  template <typename T>
+  void AnalyzeAddedOp(const T* op) {
+    num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op);
+    num_slow_paths_ += op->CountSlowPaths();
+
+    subrecord_bytes_used_ += op->AdditionalBytesUsed();
+  }
+
+  // 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.
+  base::AlignedMemory<sizeof(LargestPaintOp), ALIGNOF(LargestPaintOp)>
+      first_op_;
+  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
new file mode 100644
index 0000000..a962ab9
--- /dev/null
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -0,0 +1,332 @@
+// 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
new file mode 100644
index 0000000..52cb2524
--- /dev/null
+++ b/cc/paint/paint_record.cc
@@ -0,0 +1,26 @@
+// 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 8506606b..daeee004 100644
--- a/cc/paint/paint_record.h
+++ b/cc/paint/paint_record.h
@@ -5,19 +5,22 @@
 #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 {
 
-using PaintRecord = SkPicture;
+// 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;
 
-inline sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record) {
-  return record;
-}
+// TODO(enne): Remove these if possible, they are really expensive.
+CC_PAINT_EXPORT sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record);
 
-inline sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record) {
-  return record;
-}
+CC_PAINT_EXPORT sk_sp<const SkPicture> ToSkPicture(
+    sk_sp<const PaintRecord> record);
 
 }  // namespace cc
 
diff --git a/cc/paint/paint_recorder.cc b/cc/paint/paint_recorder.cc
index 672f0712..2ed17c74 100644
--- a/cc/paint/paint_recorder.cc
+++ b/cc/paint/paint_recorder.cc
@@ -4,9 +4,36 @@
 
 #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());
+  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 2bbea83b..7f582b85 100644
--- a/cc/paint/paint_recorder.h
+++ b/cc/paint/paint_recorder.h
@@ -9,47 +9,36 @@
 #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/skia_paint_canvas.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "cc/paint/record_paint_canvas.h"
 
 namespace cc {
 
+class PaintOpBuffer;
+
 class CC_PAINT_EXPORT PaintRecorder {
  public:
   PaintRecorder();
   ~PaintRecorder();
 
-  ALWAYS_INLINE PaintCanvas* beginRecording(const SkRect& bounds) {
-    uint32_t record_flags = 0;
-    canvas_.emplace(recorder_.beginRecording(bounds, nullptr, record_flags));
-    return getRecordingCanvas();
-  }
+  PaintCanvas* beginRecording(const SkRect& bounds);
 
-  ALWAYS_INLINE PaintCanvas* beginRecording(SkScalar width, SkScalar height) {
-    uint32_t record_flags = 0;
-    canvas_.emplace(
-        recorder_.beginRecording(width, height, 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));
   }
 
   // Only valid between between and finish recording.
-  ALWAYS_INLINE PaintCanvas* getRecordingCanvas() {
+  ALWAYS_INLINE RecordPaintCanvas* getRecordingCanvas() {
     return canvas_.has_value() ? &canvas_.value() : nullptr;
   }
 
-  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()));
-  }
+  sk_sp<PaintRecord> finishRecordingAsPicture();
 
  private:
-  SkPictureRecorder recorder_;
-  base::Optional<SkiaPaintCanvas> canvas_;
+  sk_sp<PaintOpBuffer> buffer_;
+  base::Optional<RecordPaintCanvas> canvas_;
 
   DISALLOW_COPY_AND_ASSIGN(PaintRecorder);
 };
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc
new file mode 100644
index 0000000..935452a3
--- /dev/null
+++ b/cc/paint/record_paint_canvas.cc
@@ -0,0 +1,372 @@
+// 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) : buffer_(buffer) {
+  DCHECK(buffer_);
+}
+
+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 GetCanvas()->getMetaData();
+}
+
+SkImageInfo RecordPaintCanvas::imageInfo() const {
+  return GetCanvas()->imageInfo();
+}
+
+void RecordPaintCanvas::flush() {
+  // This is a noop when recording.
+}
+
+int RecordPaintCanvas::save() {
+  buffer_->push<SaveOp>();
+  return GetCanvas()->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 GetCanvas()->saveLayer(bounds, &paint);
+  }
+  buffer_->push<SaveLayerOp>(bounds, flags);
+  return GetCanvas()->saveLayer(bounds, nullptr);
+}
+
+int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
+  buffer_->push<SaveLayerAlphaOp>(bounds, alpha);
+  return GetCanvas()->saveLayerAlpha(bounds, alpha);
+}
+
+void RecordPaintCanvas::restore() {
+  buffer_->push<RestoreOp>();
+  GetCanvas()->restore();
+}
+
+int RecordPaintCanvas::getSaveCount() const {
+  return GetCanvas()->getSaveCount();
+}
+
+void RecordPaintCanvas::restoreToCount(int save_count) {
+  if (!canvas_) {
+    DCHECK_EQ(save_count, 1);
+    return;
+  }
+
+  DCHECK_GE(save_count, 1);
+  int diff = GetCanvas()->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);
+  GetCanvas()->translate(dx, dy);
+}
+
+void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) {
+  buffer_->push<ScaleOp>(sx, sy);
+  GetCanvas()->scale(sx, sy);
+}
+
+void RecordPaintCanvas::rotate(SkScalar degrees) {
+  buffer_->push<RotateOp>(degrees);
+  GetCanvas()->rotate(degrees);
+}
+
+void RecordPaintCanvas::concat(const SkMatrix& matrix) {
+  buffer_->push<ConcatOp>(matrix);
+  GetCanvas()->concat(matrix);
+}
+
+void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) {
+  buffer_->push<SetMatrixOp>(matrix);
+  GetCanvas()->setMatrix(matrix);
+}
+
+void RecordPaintCanvas::clipRect(const SkRect& rect,
+                                 SkClipOp op,
+                                 bool antialias) {
+  buffer_->push<ClipRectOp>(rect, op, antialias);
+  GetCanvas()->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);
+  GetCanvas()->clipRRect(rrect, op, antialias);
+}
+
+void RecordPaintCanvas::clipPath(const SkPath& path,
+                                 SkClipOp op,
+                                 bool antialias) {
+  if (!path.isInverseFillType() &&
+      GetCanvas()->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);
+  GetCanvas()->clipPath(path, op, antialias);
+  return;
+}
+
+bool RecordPaintCanvas::quickReject(const SkRect& rect) const {
+  return GetCanvas()->quickReject(rect);
+}
+
+bool RecordPaintCanvas::quickReject(const SkPath& path) const {
+  return GetCanvas()->quickReject(path);
+}
+
+SkRect RecordPaintCanvas::getLocalClipBounds() const {
+  return GetCanvas()->getLocalClipBounds();
+}
+
+bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
+  return GetCanvas()->getLocalClipBounds(bounds);
+}
+
+SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
+  return GetCanvas()->getDeviceClipBounds();
+}
+
+bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
+  return GetCanvas()->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 GetCanvas()->isClipEmpty();
+}
+
+bool RecordPaintCanvas::isClipRect() const {
+  return GetCanvas()->isClipRect();
+}
+
+const SkMatrix& RecordPaintCanvas::getTotalMatrix() const {
+  return GetCanvas()->getTotalMatrix();
+}
+
+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);
+}
+
+const SkNoDrawCanvas* RecordPaintCanvas::GetCanvas() const {
+  return const_cast<RecordPaintCanvas*>(this)->GetCanvas();
+}
+
+SkNoDrawCanvas* RecordPaintCanvas::GetCanvas() {
+  if (canvas_)
+    return &*canvas_;
+
+  SkIRect rect = buffer_->cullRect().roundOut();
+  canvas_.emplace(rect.right(), rect.bottom());
+
+  // 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(rect), SkClipOp::kIntersect, false);
+  return &*canvas_;
+}
+
+}  // namespace cc
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h
new file mode 100644
index 0000000..4677512
--- /dev/null
+++ b/cc/paint/record_paint_canvas.h
@@ -0,0 +1,159 @@
+// 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 "base/optional.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);
+  ~RecordPaintCanvas() override;
+
+  SkMetaData& getMetaData() override;
+  SkImageInfo imageInfo() const override;
+
+  void flush() 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 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:
+  const SkNoDrawCanvas* GetCanvas() const;
+  SkNoDrawCanvas* GetCanvas();
+
+  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.
+  //
+  // This is mutable so that const functions (e.g. quickReject) that may
+  // lazy initialize the canvas can still be const.
+  mutable base::Optional<SkNoDrawCanvas> canvas_;
+
+  DISALLOW_COPY_AND_ASSIGN(RecordPaintCanvas);
+};
+
+}  // 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 9c1a20a..47953bd 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -22,7 +22,6 @@
                                  const SkSurfaceProps& props)
     : canvas_(new SkCanvas(bitmap, props)), owned_(canvas_) {}
 
-SkiaPaintCanvas::SkiaPaintCanvas(SkiaPaintCanvas&& other) = default;
 SkiaPaintCanvas::~SkiaPaintCanvas() = default;
 
 SkMetaData& SkiaPaintCanvas::getMetaData() {
@@ -45,7 +44,7 @@
   return canvas_->saveLayer(bounds, ToSkPaint(flags));
 }
 
-int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
+int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
   return canvas_->saveLayerAlpha(bounds, alpha);
 }
 
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index 8e016f0..720104df 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -28,11 +28,8 @@
   explicit SkiaPaintCanvas(SkCanvas* canvas);
   explicit SkiaPaintCanvas(const SkBitmap& bitmap);
   explicit SkiaPaintCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
-  explicit SkiaPaintCanvas(SkiaPaintCanvas&& other);
   ~SkiaPaintCanvas() override;
 
-  SkiaPaintCanvas& operator=(SkiaPaintCanvas&& other) = default;
-
   SkMetaData& getMetaData() override;
   SkImageInfo imageInfo() const override;
 
@@ -40,7 +37,7 @@
 
   int save() override;
   int saveLayer(const SkRect* bounds, const PaintFlags* flags) override;
-  int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) override;
+  int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override;
 
   void restore() override;
   int getSaveCount() const override;
diff --git a/cc/test/test_skcanvas.cc b/cc/test/test_skcanvas.cc
new file mode 100644
index 0000000..e45f42de
--- /dev/null
+++ b/cc/test/test_skcanvas.cc
@@ -0,0 +1,26 @@
+// 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
new file mode 100644
index 0000000..2b130a4
--- /dev/null
+++ b/cc/test/test_skcanvas.h
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef 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/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 700ebd2..850a28f 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -6658,8 +6658,27 @@
   FakeContentLayerClient client_;
 };
 
+class LayerTreeTestSingleTextureMaskLayerForSurfaceWithContentRectNotAtOrigin
+    : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = false;
+  }
+};
+
 SINGLE_AND_MULTI_THREAD_TEST_F(
-    LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin);
+    LayerTreeTestSingleTextureMaskLayerForSurfaceWithContentRectNotAtOrigin);
+
+class LayerTreeTestMultiTextureMaskLayerForSurfaceWithContentRectNotAtOrigin
+    : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = true;
+  }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+    LayerTreeTestMultiTextureMaskLayerForSurfaceWithContentRectNotAtOrigin);
 
 class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest {
  protected:
@@ -6771,15 +6790,30 @@
   FakeContentLayerClient client_;
 };
 
+class LayerTreeTestSingleTextureMaskLayerForSurfaceWithClippedLayer
+    : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = false;
+  }
+};
+
 SINGLE_AND_MULTI_THREAD_TEST_F(
-    LayerTreeTestMaskLayerForSurfaceWithClippedLayer);
+    LayerTreeTestSingleTextureMaskLayerForSurfaceWithClippedLayer);
+
+class LayerTreeTestMultiTextureMaskLayerForSurfaceWithClippedLayer
+    : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = true;
+  }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+    LayerTreeTestMultiTextureMaskLayerForSurfaceWithClippedLayer);
 
 class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest {
  protected:
-  void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->layer_transforms_should_scale_layer_contents = true;
-  }
-
   void SetupTree() override {
     // Root
     //  |
@@ -6895,7 +6929,27 @@
   FakeContentLayerClient client_;
 };
 
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling);
+class LayerTreeTestSingleTextureMaskLayerWithScaling
+    : public LayerTreeTestMaskLayerWithScaling {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = false;
+    settings->layer_transforms_should_scale_layer_contents = true;
+  }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestSingleTextureMaskLayerWithScaling);
+
+class LayerTreeTestMultiTextureMaskLayerWithScaling
+    : public LayerTreeTestMaskLayerWithScaling {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = true;
+    settings->layer_transforms_should_scale_layer_contents = true;
+  }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMultiTextureMaskLayerWithScaling);
 
 class LayerTreeTestMaskLayerWithDifferentBounds : public LayerTreeTest {
  protected:
@@ -7000,7 +7054,27 @@
   FakeContentLayerClient client_;
 };
 
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithDifferentBounds);
+class LayerTreeTestSingleTextureMaskLayerWithDifferentBounds
+    : public LayerTreeTestMaskLayerWithDifferentBounds {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = false;
+  }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+    LayerTreeTestSingleTextureMaskLayerWithDifferentBounds);
+
+class LayerTreeTestMultiTextureMaskLayerWithDifferentBounds
+    : public LayerTreeTestMaskLayerWithDifferentBounds {
+ public:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->enable_mask_tiling = true;
+  }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+    LayerTreeTestMultiTextureMaskLayerWithDifferentBounds);
 
 class LayerTreeTestPageScaleFlags : public LayerTreeTest {
  protected:
diff --git a/chrome/android/java/res/layout-sw360dp/preference_spinner_single_line.xml b/chrome/android/java/res/layout-sw360dp/preference_spinner_single_line.xml
index 3793a52..815da682 100644
--- a/chrome/android/java/res/layout-sw360dp/preference_spinner_single_line.xml
+++ b/chrome/android/java/res/layout-sw360dp/preference_spinner_single_line.xml
@@ -21,7 +21,9 @@
         android:textAlignment="viewStart"
         android:layout_height="wrap_content"
         android:layout_width="0dp"
-        android:layout_weight="1" />
+        android:layout_weight="1"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"/>
 
     <Spinner
         android:id="@+id/spinner"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index d769f08..c37db14 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -550,6 +550,8 @@
         getImageControl().hideCustomImage(true);
         getSearchBarControl().setSearchTerm(searchTerm);
         mPanelMetrics.onSearchRequestStarted();
+        // Make sure the new Search Term draws.
+        requestUpdate();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
index 4fdbc1e..752e673 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
@@ -16,6 +16,8 @@
 import android.view.View.MeasureSpec;
 import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
 import android.widget.PopupWindow;
 import android.widget.PopupWindow.OnDismissListener;
 import android.widget.TextView;
@@ -302,9 +304,15 @@
 
     private void createContentView() {
         if (mPopupWindow.getContentView() != null) return;
+
         View view = LayoutInflater.from(mContext).inflate(R.layout.textbubble_text, null);
         ((TextView) view).setText(mStringId);
         mPopupWindow.setContentView(view);
+
+        // On some versions of Android, the LayoutParams aren't set until after the popup window
+        // is shown. Explicitly set the LayoutParams to avoid crashing. See crbug.com/713759.
+        view.setLayoutParams(
+                new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
     }
 
     // OnTouchListener implementation.
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS b/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS
index 325f7c3..56eef3e 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS
@@ -1 +1,2 @@
 emaxx@chromium.org
+drcrash@chromium.org
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS b/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS
index d7df737..19c0042 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS
@@ -1,3 +1,5 @@
-dkrahn@chromium.org
-mnissler@chromium.org
+emaxx@chromium.org
+drcrash@chromium.org
 bartfab@chromium.org
+mnissler@chromium.org
+dkrahn@chromium.org
diff --git a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
index 822e9ff..9d19714 100644
--- a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
+++ b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
@@ -39,6 +39,7 @@
 #include "net/log/net_log_entry.h"
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
 #include "chrome/browser/chromeos/system_logs/debug_log_writer.h"
 #endif
 
@@ -111,7 +112,15 @@
 // will be stored - /home/chronos/<user_profile_dir>/Downloads/log_dumps
 base::FilePath GetLogDumpDirectory(content::BrowserContext* context) {
   const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(context);
-  return prefs->DownloadPath().Append(kLogDumpsSubdir);
+  base::FilePath path = prefs->DownloadPath();
+
+#if defined(OS_CHROMEOS)
+  Profile* profile = Profile::FromBrowserContext(context);
+  if (file_manager::util::IsUnderNonNativeLocalPath(profile, path))
+    path = prefs->GetDefaultDownloadDirectoryForProfile();
+#endif
+
+  return path.Append(kLogDumpsSubdir);
 }
 
 // Removes direcotry content of |logs_dumps| and |app_logs_dir| (only for the
diff --git a/chrome/browser/net/dns_probe_browsertest.cc b/chrome/browser/net/dns_probe_browsertest.cc
index 94b24b55a..6235a9c 100644
--- a/chrome/browser/net/dns_probe_browsertest.cc
+++ b/chrome/browser/net/dns_probe_browsertest.cc
@@ -9,7 +9,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/io_thread.h"
@@ -185,8 +185,12 @@
             request,
             network_delegate,
             file_path,
-            BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
-                base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
+            base::CreateTaskRunnerWithTraits(
+                base::TaskTraits()
+                    .MayBlock()
+                    .WithPriority(base::TaskPriority::BACKGROUND)
+                    .WithShutdownBehavior(
+                        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN))),
         should_delay_(should_delay),
         start_delayed_(false),
         destruction_callback_(destruction_callback) {}
diff --git a/chrome/browser/net/load_timing_browsertest.cc b/chrome/browser/net/load_timing_browsertest.cc
index e6f53d9c..18af0e56 100644
--- a/chrome/browser/net/load_timing_browsertest.cc
+++ b/chrome/browser/net/load_timing_browsertest.cc
@@ -14,7 +14,7 @@
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -123,10 +123,15 @@
                               const base::FilePath& path,
                               const TimingDeltas& load_timing_deltas)
       : net::URLRequestFileJob(
-            request, network_delegate, path,
-            content::BrowserThread::GetBlockingPool()->
-                GetTaskRunnerWithShutdownBehavior(
-                    base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
+            request,
+            network_delegate,
+            path,
+            base::CreateTaskRunnerWithTraits(
+                base::TaskTraits()
+                    .MayBlock()
+                    .WithPriority(base::TaskPriority::BACKGROUND)
+                    .WithShutdownBehavior(
+                        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN))),
         load_timing_deltas_(load_timing_deltas),
         weak_factory_(this) {}
 
diff --git a/chrome/browser/notifications/notification_common.cc b/chrome/browser/notifications/notification_common.cc
index 92f44b4..3320f6a 100644
--- a/chrome/browser/notifications/notification_common.cc
+++ b/chrome/browser/notifications/notification_common.cc
@@ -14,6 +14,7 @@
 void NotificationCommon::OpenNotificationSettings(
     content::BrowserContext* browser_context) {
 #if defined(OS_ANDROID)
+  // Android settings are opened directly from Java
   NOTIMPLEMENTED();
 #else
   Profile* profile = Profile::FromBrowserContext(browser_context);
diff --git a/chrome/browser/notifications/notification_display_service_factory.cc b/chrome/browser/notifications/notification_display_service_factory.cc
index 3e7c4f1..da0e659 100644
--- a/chrome/browser/notifications/notification_display_service_factory.cc
+++ b/chrome/browser/notifications/notification_display_service_factory.cc
@@ -39,25 +39,28 @@
 
 // Selection of the implementation works as follows:
 //   - Android always uses the NativeNotificationDisplayService.
-//   - Mac uses the MessageCenterDisplayService by default, but can use the
-//     NativeNotificationDisplayService by using the chrome://flags or via
-//     the --enable-features=NativeNotifications command line flag.
+//   - Mac uses the NativeNotificationDisplayService by default but
+//     can revert to MessageCenterDisplayService via
+//     chrome://flags#enable-native-notifications or Finch
+//   - Linux uses MessageCenterDisplayService by default but can switch
+//     to NativeNotificationDisplayService via
+//     chrome://flags#enable-native-notifications
 //   - All other platforms always use the MessageCenterDisplayService.
 KeyedService* NotificationDisplayServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
 #if BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
 #if defined(OS_ANDROID)
+  DCHECK(base::FeatureList::IsEnabled(features::kNativeNotifications));
   return new NativeNotificationDisplayService(
       Profile::FromBrowserContext(context),
       g_browser_process->notification_platform_bridge());
-#else   // defined(OS_ANDROID)
+#endif
   if (base::FeatureList::IsEnabled(features::kNativeNotifications) &&
       g_browser_process->notification_platform_bridge()) {
     return new NativeNotificationDisplayService(
         Profile::FromBrowserContext(context),
         g_browser_process->notification_platform_bridge());
   }
-#endif  // defined(OS_ANDROID)
 #endif  // BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
   return new MessageCenterDisplayService(
       Profile::FromBrowserContext(context),
diff --git a/chrome/browser/notifications/platform_notification_service_unittest.cc b/chrome/browser/notifications/platform_notification_service_unittest.cc
index a7ed019..808fdd2 100644
--- a/chrome/browser/notifications/platform_notification_service_unittest.cc
+++ b/chrome/browser/notifications/platform_notification_service_unittest.cc
@@ -165,11 +165,7 @@
   }
 
   Notification GetDisplayedNotification() {
-#if defined(OS_ANDROID)
-    return static_cast<StubNotificationPlatformBridge*>(
-               g_browser_process->notification_platform_bridge())
-        ->GetNotificationAt(profile_->GetPath().BaseName().value(), 0);
-#elif BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
+#if BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
     if (base::FeatureList::IsEnabled(features::kNativeNotifications)) {
       return static_cast<StubNotificationPlatformBridge*>(
                  g_browser_process->notification_platform_bridge())
diff --git a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
index c77fc39..a6355bb 100644
--- a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
@@ -28,12 +28,9 @@
 PaymentRequestSheetController::~PaymentRequestSheetController() {}
 
 std::unique_ptr<views::View> PaymentRequestSheetController::CreateView() {
-  // This is owned by its parent.
-  content_view_ = new views::View;
-
-  FillContentView(content_view_);
-
-  return CreatePaymentView();
+  std::unique_ptr<views::View> view = CreatePaymentView();
+  UpdateContentView();
+  return view;
 }
 
 void PaymentRequestSheetController::UpdateContentView() {
@@ -117,6 +114,8 @@
       0, views::GridLayout::SizeType::FIXED, kDialogWidth, kDialogWidth);
   pane_->SetLayoutManager(pane_layout);
   pane_layout->StartRow(0, 0);
+  // This is owned by its parent. It's the container passed to FillContentView.
+  content_view_ = new views::View;
   pane_layout->AddView(content_view_);
   pane_->SizeToPreferredSize();
 
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 9935918..901375a 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -16,6 +16,7 @@
 #include "build/build_config.h"
 #include "cc/paint/paint_flags.h"
 #include "cc/paint/paint_recorder.h"
+#include "cc/paint/paint_shader.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 6e36f8bd4..dc19f25 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -224,7 +224,7 @@
 // Enables the use of native notification centers instead of using the Message
 // Center for displaying the toasts.
 #if BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
 const base::Feature kNativeNotifications{"NativeNotifications",
                                          base::FEATURE_ENABLED_BY_DEFAULT};
 #else
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker.cc b/chrome/test/chromedriver/chrome/navigation_tracker.cc
index 0fdceb63..3980478 100644
--- a/chrome/test/chromedriver/chrome/navigation_tracker.cc
+++ b/chrome/test/chromedriver/chrome/navigation_tracker.cc
@@ -117,15 +117,26 @@
   if (loading_state_ == kUnknown) {
     // In the case that a http request is sent to server to fetch the page
     // content and the server hasn't responded at all, a dummy page is created
-    // for the new window. In such case, the baseURL will be empty.
+    // for the new window. In such case, the baseURL will be empty for <=M59 ;
+    // whereas the baseURL will be 'about:blank' for >=M60. See crbug/711562.
+    // TODO(gmanikpure):Remove condition for <3076 when we stop supporting M59.
     base::DictionaryValue empty_params;
     std::unique_ptr<base::DictionaryValue> result;
     Status status = client_->SendCommandAndGetResultWithTimeout(
         "DOM.getDocument", empty_params, timeout, &result);
     std::string base_url;
-    if (status.IsError() || !result->GetString("root.baseURL", &base_url))
+    std::string doc_url;
+    if (status.IsError() || !result->GetString("root.baseURL", &base_url) ||
+        !result->GetString("root.documentURL", &doc_url))
       return MakeNavigationCheckFailedStatus(status);
-    if (base_url.empty()) {
+
+    bool condition;
+    if (browser_info_->build_no >= 3076)
+      condition = doc_url != "about:blank" && base_url == "about:blank";
+    else
+      condition = base_url.empty();
+
+    if (condition) {
       *is_pending = true;
       loading_state_ = kLoading;
       return Status(kOk);
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc b/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc
index 91ff255..a66e6175 100644
--- a/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc
+++ b/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc
@@ -46,10 +46,13 @@
       std::unique_ptr<base::DictionaryValue>* result) override {
     if (method == "DOM.getDocument") {
       base::DictionaryValue result_dict;
-      if (has_empty_base_url_)
-        result_dict.SetString("root.baseURL", std::string());
-      else
+      if (has_empty_base_url_) {
+        result_dict.SetString("root.baseURL", "about:blank");
+        result_dict.SetString("root.documentURL", "http://test");
+      } else {
         result_dict.SetString("root.baseURL", "http://test");
+        result_dict.SetString("root.documentURL", "http://test");
+      }
       result->reset(result_dict.DeepCopy());
       return Status(kOk);
     } else if (method == "Runtime.evaluate") {
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index ce5a8453..41eb401 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -73,8 +73,6 @@
 
 _VERSION_SPECIFIC_FILTER = {}
 _VERSION_SPECIFIC_FILTER['HEAD'] = [
-    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1775
-    'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
 ]
 _VERSION_SPECIFIC_FILTER['58'] = [
     # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1673
diff --git a/content/browser/renderer_host/clipboard_message_filter.cc b/content/browser/renderer_host/clipboard_message_filter.cc
index 39b8714..8b930c1 100644
--- a/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/content/browser/renderer_host/clipboard_message_filter.cc
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/pickle.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
@@ -180,12 +180,14 @@
                                          IPC::Message* reply_msg) {
   SkBitmap bitmap = GetClipboard()->ReadImage(type);
 
-  BrowserThread::GetBlockingPool()
-      ->GetTaskRunnerWithShutdownBehavior(
-          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)
-      ->PostTask(FROM_HERE,
-                 base::Bind(&ClipboardMessageFilter::ReadAndEncodeImage, this,
-                            bitmap, reply_msg));
+  base::PostTaskWithTraits(
+      FROM_HERE,
+      base::TaskTraits()
+          .MayBlock()
+          .WithPriority(base::TaskPriority::BACKGROUND)
+          .WithShutdownBehavior(base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
+      base::BindOnce(&ClipboardMessageFilter::ReadAndEncodeImage, this, bitmap,
+                     reply_msg));
 }
 
 void ClipboardMessageFilter::ReadAndEncodeImage(const SkBitmap& bitmap,
diff --git a/device/bluetooth/bluetooth_adapter_factory.cc b/device/bluetooth/bluetooth_adapter_factory.cc
index 8cf0128..21a1216 100644
--- a/device/bluetooth/bluetooth_adapter_factory.cc
+++ b/device/bluetooth/bluetooth_adapter_factory.cc
@@ -19,6 +19,9 @@
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
 #endif
+#if defined(ANDROID)
+#include "base/android/build_info.h"
+#endif
 
 namespace device {
 
@@ -77,8 +80,9 @@
   if (default_adapter.Get())
     return true;
 
-#if defined(OS_ANDROID) && __ANDROID_API__ >= 23
-  return true;
+#if defined(OS_ANDROID)
+  return base::android::BuildInfo::GetInstance()->sdk_int() >=
+         base::android::SDK_VERSION_MARSHMALLOW;
 #elif defined(OS_WIN)
   // Windows 8 supports Low Energy GATT operations but it does not support
   // scanning, initiating connections and GATT Server. To keep the API
diff --git a/extensions/renderer/resources/guest_view/extension_view/extension_view_api_methods.js b/extensions/renderer/resources/guest_view/extension_view/extension_view_api_methods.js
index b7ce28c0..bebe55e 100644
--- a/extensions/renderer/resources/guest_view/extension_view/extension_view_api_methods.js
+++ b/extensions/renderer/resources/guest_view/extension_view/extension_view_api_methods.js
@@ -25,7 +25,7 @@
 
 ExtensionViewImpl.prototype.load = function(src) {
   return new Promise($Function.bind(function(resolve, reject) {
-    this.loadQueue.push({src: src, resolve: resolve, reject: reject});
+    $Array.push(this.loadQueue, {src: src, resolve: resolve, reject: reject});
     this.loadNextSrc();
   }, this))
   .then($Function.bind(function onLoadResolved() {
diff --git a/extensions/renderer/resources/guest_view/guest_view.js b/extensions/renderer/resources/guest_view/guest_view.js
index c8ce3b9..c228dca0 100644
--- a/extensions/renderer/resources/guest_view/guest_view.js
+++ b/extensions/renderer/resources/guest_view/guest_view.js
@@ -310,7 +310,7 @@
 GuestView.prototype.attach = function(
     internalInstanceId, viewInstanceId, attachParams, callback) {
   var internal = privates(this).internal;
-  internal.actionQueue.push($Function.bind(internal.attachImpl$,
+  $Array.push(internal.actionQueue, $Function.bind(internal.attachImpl$,
       internal, internalInstanceId, viewInstanceId, attachParams, callback));
   internal.performNextAction();
 };
@@ -318,7 +318,7 @@
 // Creates the guestview.
 GuestView.prototype.create = function(createParams, callback) {
   var internal = privates(this).internal;
-  internal.actionQueue.push($Function.bind(internal.createImpl$,
+  $Array.push(internal.actionQueue, $Function.bind(internal.createImpl$,
       internal, createParams, callback));
   internal.performNextAction();
 };
@@ -327,7 +327,7 @@
 // been destroyed.
 GuestView.prototype.destroy = function(callback) {
   var internal = privates(this).internal;
-  internal.actionQueue.push(
+  $Array.push(internal.actionQueue,
       $Function.bind(internal.destroyImpl, internal, callback));
   internal.performNextAction();
 };
@@ -336,7 +336,7 @@
 // Note: This is not currently used.
 GuestView.prototype.detach = function(callback) {
   var internal = privates(this).internal;
-  internal.actionQueue.push(
+  $Array.push(internal.actionQueue,
       $Function.bind(internal.detachImpl, internal, callback));
   internal.performNextAction();
 };
@@ -344,7 +344,7 @@
 // Adjusts the guestview's sizing parameters.
 GuestView.prototype.setSize = function(sizeParams, callback) {
   var internal = privates(this).internal;
-  internal.actionQueue.push(
+  $Array.push(internal.actionQueue,
       $Function.bind(internal.setSizeImpl, internal, sizeParams, callback));
   internal.performNextAction();
 };
diff --git a/extensions/renderer/resources/guest_view/guest_view_events.js b/extensions/renderer/resources/guest_view/guest_view_events.js
index acb3781e..4a0a7bd 100644
--- a/extensions/renderer/resources/guest_view/guest_view_events.js
+++ b/extensions/renderer/resources/guest_view/guest_view_events.js
@@ -69,7 +69,7 @@
 // to be removed once this GuestViewEvents object is garbage collected.
 GuestViewEvents.prototype.addScopedListener = function(
     evt, listener, listenerOpts) {
-  this.listenersToBeRemoved.push({ 'evt': evt, 'listener': listener });
+  $Array.push(this.listenersToBeRemoved, { 'evt': evt, 'listener': listener });
   evt.addListener(listener, listenerOpts);
 };
 
diff --git a/gpu/skia_bindings/grcontext_for_gles2_interface.cc b/gpu/skia_bindings/grcontext_for_gles2_interface.cc
index 1f16141..ee7516b 100644
--- a/gpu/skia_bindings/grcontext_for_gles2_interface.cc
+++ b/gpu/skia_bindings/grcontext_for_gles2_interface.cc
@@ -10,6 +10,7 @@
 
 #include "base/lazy_instance.h"
 #include "base/macros.h"
+#include "base/sys_info.h"
 #include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
@@ -32,10 +33,22 @@
     static const int kMaxGaneshResourceCacheCount = 16384;
     // The limit of the bytes allocated toward GPU resources in the GrContext's
     // GPU cache.
+    static const size_t kMaxLowEndGaneshResourceCacheBytes = 48 * 1024 * 1024;
     static const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
+    static const size_t kMaxHighEndGaneshResourceCacheBytes = 256 * 1024 * 1024;
+    static const int64_t kHighEndMemoryThreshold = (int64_t)4096 * 1024 * 1024;
+    static const int64_t kLowEndMemoryThreshold = (int64_t)512 * 1024 * 1024;
+
+    size_t max_ganesh_resource_cache_bytes = kMaxGaneshResourceCacheBytes;
+    if (base::SysInfo::AmountOfPhysicalMemory() <= kLowEndMemoryThreshold) {
+      max_ganesh_resource_cache_bytes = kMaxLowEndGaneshResourceCacheBytes;
+    } else if (base::SysInfo::AmountOfPhysicalMemory() >=
+               kHighEndMemoryThreshold) {
+      max_ganesh_resource_cache_bytes = kMaxHighEndGaneshResourceCacheBytes;
+    }
 
     gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
-                                        kMaxGaneshResourceCacheBytes);
+                                        max_ganesh_resource_cache_bytes);
   }
 }
 
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 3922634..454717d 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -224,6 +224,8 @@
               "lib/browser/headless_devtools_manager_delegate.cc",
               "lib/browser/headless_devtools_manager_delegate.h",
               "lib/browser/headless_macros.h",
+              "lib/browser/headless_net_log.cc",
+              "lib/browser/headless_net_log.h",
               "lib/browser/headless_network_delegate.cc",
               "lib/browser/headless_network_delegate.h",
               "lib/browser/headless_permission_manager.cc",
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc
index b691760..7e6879b 100644
--- a/headless/lib/browser/headless_browser_context_impl.cc
+++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -18,6 +18,8 @@
 #include "headless/grit/headless_lib_resources.h"
 #include "headless/lib/browser/headless_browser_context_options.h"
 #include "headless/lib/browser/headless_browser_impl.h"
+#include "headless/lib/browser/headless_browser_main_parts.h"
+#include "headless/lib/browser/headless_net_log.h"
 #include "headless/lib/browser/headless_permission_manager.h"
 #include "headless/lib/browser/headless_url_request_context_getter.h"
 #include "headless/public/util/black_hole_protocol_handler.h"
@@ -223,7 +225,8 @@
           content::BrowserThread::GetTaskRunnerForThread(
               content::BrowserThread::FILE),
           protocol_handlers, context_options_->TakeProtocolHandlers(),
-          std::move(request_interceptors), context_options_.get()));
+          std::move(request_interceptors), context_options_.get(),
+          browser_->browser_main_parts()->net_log()));
   resource_context_->set_url_request_context_getter(url_request_context_getter);
   return url_request_context_getter.get();
 }
diff --git a/headless/lib/browser/headless_browser_main_parts.cc b/headless/lib/browser/headless_browser_main_parts.cc
index 2ae52c3..6423a44 100644
--- a/headless/lib/browser/headless_browser_main_parts.cc
+++ b/headless/lib/browser/headless_browser_main_parts.cc
@@ -4,9 +4,12 @@
 
 #include "headless/lib/browser/headless_browser_main_parts.h"
 
+#include "base/command_line.h"
+#include "content/public/common/content_switches.h"
 #include "headless/lib/browser/headless_browser_context_impl.h"
 #include "headless/lib/browser/headless_browser_impl.h"
 #include "headless/lib/browser/headless_devtools.h"
+#include "headless/lib/browser/headless_net_log.h"
 #include "headless/lib/browser/headless_screen.h"
 
 namespace headless {
@@ -18,6 +21,14 @@
 HeadlessBrowserMainParts::~HeadlessBrowserMainParts() {}
 
 void HeadlessBrowserMainParts::PreMainMessageLoopRun() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kLogNetLog)) {
+    base::FilePath log_path =
+        command_line->GetSwitchValuePath(switches::kLogNetLog);
+    net_log_.reset(new HeadlessNetLog(log_path));
+  }
+
   if (browser_->options()->devtools_endpoint.address().IsValid()) {
     StartLocalDevToolsHttpHandler(browser_->options());
     devtools_http_handler_started_ = true;
diff --git a/headless/lib/browser/headless_browser_main_parts.h b/headless/lib/browser/headless_browser_main_parts.h
index 0bf44ee..0b8d81f 100644
--- a/headless/lib/browser/headless_browser_main_parts.h
+++ b/headless/lib/browser/headless_browser_main_parts.h
@@ -7,11 +7,13 @@
 
 #include <memory>
 
+#include "base/files/file_path.h"
 #include "content/public/browser/browser_main_parts.h"
 #include "headless/public/headless_browser.h"
 
 namespace headless {
 
+class HeadlessNetLog;
 class HeadlessBrowserImpl;
 
 class HeadlessBrowserMainParts : public content::BrowserMainParts {
@@ -26,10 +28,13 @@
   void PreMainMessageLoopStart() override;
 #endif
 
+  HeadlessNetLog* net_log() const { return net_log_.get(); }
+
  private:
   HeadlessBrowserImpl* browser_;  // Not owned.
 
   bool devtools_http_handler_started_;
+  std::unique_ptr<HeadlessNetLog> net_log_;
 
   DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserMainParts);
 };
diff --git a/headless/lib/browser/headless_net_log.cc b/headless/lib/browser/headless_net_log.cc
new file mode 100644
index 0000000..a64f37ea
--- /dev/null
+++ b/headless/lib/browser/headless_net_log.cc
@@ -0,0 +1,75 @@
+// 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 "headless/lib/browser/headless_net_log.h"
+
+#include <stdio.h>
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "content/public/common/content_switches.h"
+#include "net/log/net_log_util.h"
+#include "net/log/write_to_file_net_log_observer.h"
+
+namespace headless {
+namespace {
+
+std::unique_ptr<base::Value> GetHeadlessConstants() {
+  std::unique_ptr<base::DictionaryValue> constants_dict =
+      net::GetNetConstants();
+
+  // Add a dictionary with client information
+  base::DictionaryValue* dict = new base::DictionaryValue();
+
+  dict->SetString("name", "headless");
+  dict->SetString(
+      "command_line",
+      base::CommandLine::ForCurrentProcess()->GetCommandLineString());
+
+  constants_dict->Set("clientInfo", dict);
+
+  return std::move(constants_dict);
+}
+
+}  // namespace
+
+HeadlessNetLog::HeadlessNetLog(const base::FilePath& log_path) {
+  // TODO(mmenke):  Other than a different set of constants, this code is
+  //     identical to code in ChromeNetLog.  Consider merging the code.
+
+  // Much like logging.h, bypass threading restrictions by using fopen
+  // directly.  Have to write on a thread that's shutdown to handle events on
+  // shutdown properly, and posting events to another thread as they occur
+  // would result in an unbounded buffer size, so not much can be gained by
+  // doing this on another thread.  It's only used when debugging, so
+  // performance is not a big concern.
+  base::ScopedFILE file;
+#if defined(OS_WIN)
+  file.reset(_wfopen(log_path.value().c_str(), L"w"));
+#elif defined(OS_POSIX)
+  file.reset(fopen(log_path.value().c_str(), "w"));
+#endif
+
+  if (!file) {
+    LOG(ERROR) << "Could not open file " << log_path.value()
+               << " for net logging";
+  } else {
+    std::unique_ptr<base::Value> constants(GetHeadlessConstants());
+    write_to_file_observer_.reset(new net::WriteToFileNetLogObserver());
+    write_to_file_observer_->StartObserving(this, std::move(file),
+                                            constants.get(), nullptr);
+  }
+}
+
+HeadlessNetLog::~HeadlessNetLog() {
+  // Remove the observer we own before we're destroyed.
+  if (write_to_file_observer_)
+    write_to_file_observer_->StopObserving(nullptr);
+}
+
+}  // namespace headless
diff --git a/headless/lib/browser/headless_net_log.h b/headless/lib/browser/headless_net_log.h
new file mode 100644
index 0000000..ac33ee5
--- /dev/null
+++ b/headless/lib/browser/headless_net_log.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEADLESS_LIB_BROWSER_HEADLESS_NET_LOG_H_
+#define HEADLESS_LIB_BROWSER_HEADLESS_NET_LOG_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "net/log/write_to_file_net_log_observer.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace headless {
+
+class HeadlessNetLog : public net::NetLog {
+ public:
+  explicit HeadlessNetLog(const base::FilePath& log_path);
+  ~HeadlessNetLog() override;
+
+ private:
+  std::unique_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_;
+
+  DISALLOW_COPY_AND_ASSIGN(HeadlessNetLog);
+};
+
+}  // namespace headless
+
+#endif  // HEADLESS_LIB_BROWSER_HEADLESS_NET_LOG_H_
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc
index 1d26484d..1a0f4327 100644
--- a/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -26,13 +26,15 @@
     content::ProtocolHandlerMap* protocol_handlers,
     ProtocolHandlerMap context_protocol_handlers,
     content::URLRequestInterceptorScopedVector request_interceptors,
-    HeadlessBrowserContextOptions* options)
+    HeadlessBrowserContextOptions* options,
+    net::NetLog* net_log)
     : io_task_runner_(std::move(io_task_runner)),
       file_task_runner_(std::move(file_task_runner)),
       user_agent_(options->user_agent()),
       host_resolver_rules_(options->host_resolver_rules()),
       proxy_server_(options->proxy_server()),
-      request_interceptors_(std::move(request_interceptors)) {
+      request_interceptors_(std::move(request_interceptors)),
+      net_log_(net_log) {
   // Must first be created on the UI thread.
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
@@ -78,7 +80,7 @@
 
     if (!host_resolver_rules_.empty()) {
       std::unique_ptr<net::HostResolver> host_resolver(
-          net::HostResolver::CreateDefaultResolver(nullptr /* net_log */));
+          net::HostResolver::CreateDefaultResolver(net_log_));
       std::unique_ptr<net::MappedHostResolver> mapped_host_resolver(
           new net::MappedHostResolver(std::move(host_resolver)));
       mapped_host_resolver->SetRulesFromString(host_resolver_rules_);
@@ -93,6 +95,7 @@
     builder.SetInterceptors(std::move(request_interceptors_));
 
     url_request_context_ = builder.Build();
+    url_request_context_->set_net_log(net_log_);
   }
 
   return url_request_context_.get();
diff --git a/headless/lib/browser/headless_url_request_context_getter.h b/headless/lib/browser/headless_url_request_context_getter.h
index e1bee1ea..c5ef277 100644
--- a/headless/lib/browser/headless_url_request_context_getter.h
+++ b/headless/lib/browser/headless_url_request_context_getter.h
@@ -35,7 +35,8 @@
       content::ProtocolHandlerMap* protocol_handlers,
       ProtocolHandlerMap context_protocol_handlers,
       content::URLRequestInterceptorScopedVector request_interceptors,
-      HeadlessBrowserContextOptions* options);
+      HeadlessBrowserContextOptions* options,
+      net::NetLog* net_log);
 
   // net::URLRequestContextGetter implementation:
   net::URLRequestContext* GetURLRequestContext() override;
@@ -62,6 +63,7 @@
   std::unique_ptr<net::URLRequestContext> url_request_context_;
   content::ProtocolHandlerMap protocol_handlers_;
   content::URLRequestInterceptorScopedVector request_interceptors_;
+  net::NetLog* net_log_;  // Not owned.
 
   DISALLOW_COPY_AND_ASSIGN(HeadlessURLRequestContextGetter);
 };
diff --git a/headless/lib/headless_browser_browsertest.cc b/headless/lib/headless_browser_browsertest.cc
index 8b6e20c7..2c85ae0 100644
--- a/headless/lib/headless_browser_browsertest.cc
+++ b/headless/lib/headless_browser_browsertest.cc
@@ -789,4 +789,44 @@
                 content::PermissionType::NOTIFICATIONS, url, url));
 }
 
+class HeadlessBrowserTestWithNetLog : public HeadlessBrowserTest {
+ public:
+  HeadlessBrowserTestWithNetLog() {}
+
+  void SetUp() override {
+    base::ThreadRestrictions::SetIOAllowed(true);
+    EXPECT_TRUE(base::CreateTemporaryFile(&net_log_));
+    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII("--log-net-log",
+                                                              net_log_.value());
+    HeadlessBrowserTest::SetUp();
+  }
+
+  void TearDown() override {
+    HeadlessBrowserTest::TearDown();
+    base::DeleteFile(net_log_, false);
+  }
+
+ protected:
+  base::FilePath net_log_;
+};
+
+IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestWithNetLog, WriteNetLog) {
+  EXPECT_TRUE(embedded_test_server()->Start());
+
+  HeadlessBrowserContext* browser_context =
+      browser()->CreateBrowserContextBuilder().Build();
+
+  HeadlessWebContents* web_contents =
+      browser_context->CreateWebContentsBuilder()
+          .SetInitialURL(embedded_test_server()->GetURL("/hello.html"))
+          .Build();
+  EXPECT_TRUE(WaitForLoad(web_contents));
+  browser()->Shutdown();
+
+  base::ThreadRestrictions::SetIOAllowed(true);
+  std::string net_log_data;
+  EXPECT_TRUE(base::ReadFileToString(net_log_, &net_log_data));
+  EXPECT_GE(net_log_data.find("hello.html"), 0u);
+}
+
 }  // namespace headless
diff --git a/net/log/net_log_util.cc b/net/log/net_log_util.cc
index 2d1b2dc..85b5460 100644
--- a/net/log/net_log_util.cc
+++ b/net/log/net_log_util.cc
@@ -515,7 +515,7 @@
     DCHECK(context->CalledOnValidThread());
     // Contexts should all be using the same NetLog.
     DCHECK_EQ((*contexts.begin())->net_log(), context->net_log());
-    for (auto* request : *context->url_requests()) {
+    for (auto* request : context->url_requests()) {
       requests.push_back(request);
     }
   }
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index ec9d001..bcddd10 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -186,8 +186,7 @@
   // on UserData associated with |this| and poke at it during teardown.
   job_.reset();
 
-  DCHECK_EQ(1u, context_->url_requests()->count(this));
-  context_->url_requests()->erase(this);
+  context_->RemoveURLRequest(this);
 
   int net_error = OK;
   // Log error only on failure, not cancellation, as even successful requests
@@ -585,7 +584,7 @@
   // Sanity check out environment.
   DCHECK(base::ThreadTaskRunnerHandle::IsSet());
 
-  context->url_requests()->insert(this);
+  context->InsertURLRequest(this);
   net_log_.BeginEvent(
       NetLogEventType::REQUEST_ALIVE,
       base::Bind(&NetLogURLRequestConstructorCallback, &url, priority_));
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 0ec1db6..c7e4477 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/debug/alias.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -48,10 +49,10 @@
       sdch_manager_(nullptr),
       network_quality_estimator_(nullptr),
       reporting_service_(nullptr),
-      url_requests_(new std::set<const URLRequest*>),
       enable_brotli_(false),
       check_cleartext_permitted_(false),
-      name_(nullptr) {
+      name_(nullptr),
+      largest_outstanding_requests_count_seen_(0) {
   base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
       this, "URLRequestContext", base::ThreadTaskRunnerHandle::Get());
 }
@@ -122,13 +123,27 @@
   cookie_store_ = cookie_store;
 }
 
+void URLRequestContext::InsertURLRequest(const URLRequest* request) const {
+  url_requests_.insert(request);
+  if (url_requests_.size() > largest_outstanding_requests_count_seen_) {
+    largest_outstanding_requests_count_seen_ = url_requests_.size();
+    UMA_HISTOGRAM_COUNTS_1M("Net.URLRequestContext.OutstandingRequests",
+                            largest_outstanding_requests_count_seen_);
+  }
+}
+
+void URLRequestContext::RemoveURLRequest(const URLRequest* request) const {
+  DCHECK_EQ(1u, url_requests_.count(request));
+  url_requests_.erase(request);
+}
+
 void URLRequestContext::AssertNoURLRequests() const {
-  int num_requests = url_requests_->size();
+  int num_requests = url_requests_.size();
   if (num_requests != 0) {
     // We're leaking URLRequests :( Dump the URL of the first one and record how
     // many we leaked so we have an idea of how bad it is.
     char url_buf[128];
-    const URLRequest* request = *url_requests_->begin();
+    const URLRequest* request = *url_requests_.begin();
     base::strlcpy(url_buf, request->url().spec().c_str(), arraysize(url_buf));
     int load_flags = request->load_flags();
     base::debug::Alias(url_buf);
@@ -154,7 +169,7 @@
       pmd->CreateAllocatorDump(dump_name);
   dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
                   base::trace_event::MemoryAllocatorDump::kUnitsObjects,
-                  url_requests_->size());
+                  url_requests_.size());
   HttpTransactionFactory* transaction_factory = http_transaction_factory();
   if (transaction_factory) {
     HttpNetworkSession* network_session = transaction_factory->GetSession();
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index d34c2fd..206b0105 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -221,10 +221,14 @@
 
   // Gets the URLRequest objects that hold a reference to this
   // URLRequestContext.
-  std::set<const URLRequest*>* url_requests() const {
-    return url_requests_.get();
+  const std::set<const URLRequest*>& url_requests() const {
+    return url_requests_;
   }
 
+  void InsertURLRequest(const URLRequest* request) const;
+
+  void RemoveURLRequest(const URLRequest* request) const;
+
   // CHECKs that no URLRequests using this context remain. Subclasses should
   // additionally call AssertNoURLRequests() within their own destructor,
   // prior to implicit destruction of subclass-owned state.
@@ -312,7 +316,7 @@
   // be added to CopyFrom.
   // ---------------------------------------------------------------------------
 
-  std::unique_ptr<std::set<const URLRequest*>> url_requests_;
+  mutable std::set<const URLRequest*> url_requests_;
 
   // Enables Brotli Content-Encoding support.
   bool enable_brotli_;
@@ -325,6 +329,10 @@
   // to be unique.
   const char* name_;
 
+  // The largest number of outstanding URLRequests that have been created by
+  // |this| and are not yet destroyed. This doesn't need to be in CopyFrom.
+  mutable size_t largest_outstanding_requests_count_seen_;
+
   DISALLOW_COPY_AND_ASSIGN(URLRequestContext);
 };
 
diff --git a/printing/pdf_metafile_skia.cc b/printing/pdf_metafile_skia.cc
index b2e914b3..aec4d3f 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/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc
index fcf7e6e..f0458fb 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc
+++ b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc
@@ -22,6 +22,8 @@
       return memory_instrumentation::mojom::DumpType::EXPLICITLY_TRIGGERED;
     case base::trace_event::MemoryDumpType::PEAK_MEMORY_USAGE:
       return memory_instrumentation::mojom::DumpType::PEAK_MEMORY_USAGE;
+    case base::trace_event::MemoryDumpType::SUMMARY_ONLY:
+      return memory_instrumentation::mojom::DumpType::SUMMARY_ONLY;
     default:
       CHECK(false) << "Invalid type: " << static_cast<uint8_t>(type);
       // This should not be reached. Just return a random value.
@@ -44,6 +46,9 @@
     case memory_instrumentation::mojom::DumpType::PEAK_MEMORY_USAGE:
       *out = base::trace_event::MemoryDumpType::PEAK_MEMORY_USAGE;
       break;
+    case memory_instrumentation::mojom::DumpType::SUMMARY_ONLY:
+      *out = base::trace_event::MemoryDumpType::SUMMARY_ONLY;
+      break;
     default:
       NOTREACHED() << "Invalid type: " << static_cast<uint8_t>(input);
       return false;
diff --git a/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom b/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom
index 80978bc..9afb800 100644
--- a/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom
+++ b/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom
@@ -9,7 +9,8 @@
 enum DumpType {
   PERIODIC_INTERVAL,
   EXPLICITLY_TRIGGERED,
-  PEAK_MEMORY_USAGE
+  PEAK_MEMORY_USAGE,
+  SUMMARY_ONLY 
 };
 
 enum LevelOfDetail {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 425f730..231830b 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -896,7 +896,7 @@
   "tab_capture_end2end_tests": {
     # TODO(dpranke), TODO(crbug.com/714336): What is the right label to
     # have here (and/or the right way to run this?).
-    "label": "//chrome/test:tab_capture_end2end_tests",
+    "label": "//chrome/test:browser_tests",
     "type": "gpu_browser_test",
     "gtest_filter": "CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*",
   },
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations
index bb2608f..2dcf955 100644
--- a/third_party/WebKit/LayoutTests/LeakExpectations
+++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -84,7 +84,6 @@
 # the tests for IndexedDB are skipped.
 crbug.com/506752 external/wpt/IndexedDB/ [ Skip ]
 crbug.com/506752 storage/indexeddb/ [ Skip ]
-crbug.com/506752 virtual/sharedarraybuffer/storage/indexeddb/ [ Skip ]
 
 # -----------------------------------------------------------------
 # Untriaged but known leaks of ActiveDOMObject (http).
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index ddf3f1a2..5ff05d4 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -9,9 +9,7 @@
 # than 2 seconds in Release mode or 6 seconds in Debug mode should be listed here.
 
 crbug.com/24182 storage/indexeddb/objectstore-cursor.html [ Slow ]
-crbug.com/24182 virtual/sharedarraybuffer/storage/indexeddb/objectstore-cursor.html [ Slow ]
 crbug.com/24182 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Slow ]
-crbug.com/24182 virtual/sharedarraybuffer/storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Slow ]
 crbug.com/24182 editing/selection/modify_move/move-by-word-visually-mac.html [ Slow ]
 crbug.com/24182 editing/selection/modify_move/move-by-word-visually-multi-line.html [ Slow ]
 crbug.com/24182 compositing/culling/filter-occlusion-blur-large.html [ Slow ]
@@ -268,9 +266,7 @@
 crbug.com/364250 [ Debug ] virtual/threaded/animations/interpolation/transform-interpolation.html [ Slow ]
 crbug.com/364250 [ Debug ] virtual/threaded/animations/interpolation/webkit-transform-interpolation.html [ Slow ]
 crbug.com/402379 [ Win7 Debug ] storage/indexeddb/cursor-continue-validity.html [ Slow ]
-crbug.com/402379 [ Win7 Debug ] virtual/sharedarraybuffer/storage/indexeddb/cursor-continue-validity.html [ Slow ]
 crbug.com/402379 [ Win7 Debug ] storage/indexeddb/mozilla/indexes.html [ Slow ]
-crbug.com/402379 [ Win7 Debug ] virtual/sharedarraybuffer/storage/indexeddb/mozilla/indexes.html [ Slow ]
 crbug.com/504706 [ Linux ] inspector/profiler/heap-snapshot-containment-expansion-preserved-when-sorting.html [ Slow ]
 crbug.com/504706 [ Linux ] inspector/profiler/heap-snapshot-containment-sorting.html [ Slow ]
 crbug.com/440452 virtual/display_list_2d_canvas/fast/canvas/canvas-partial-invalidation-zoomed.html [ Slow ]
@@ -389,12 +385,9 @@
 # IDB Observer tests require multiple browsing contexts/workers interacting with
 # IndexedDB, which can be slow.
 crbug.com/660468 [ Linux ] storage/indexeddb/observer-frame.html [ Slow ]
-crbug.com/660468 [ Linux ] virtual/sharedarraybuffer/storage/indexeddb/observer-frame.html [ Slow ]
 crbug.com/660468 [ Linux ] storage/indexeddb/observer-workers.html [ Slow ]
-crbug.com/660468 [ Linux ] virtual/sharedarraybuffer/storage/indexeddb/observer-workers.html [ Slow ]
 
 crbug.com/660492 [ Linux ] storage/indexeddb/structured-clone.html [ Slow ]
-crbug.com/660492 [ Linux ] virtual/sharedarraybuffer/storage/indexeddb/structured-clone.html [ Slow ]
 
 # Foreign fetch tests make many requests, and create multiple browsing contexts,
 # which can be very slow.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index faa6b25..86b8571 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -3327,11 +3327,8 @@
 crbug.com/678346 [ Win7 Debug ] fast/dom/shadow/selections-in-shadow.html [ Pass Timeout ]
 crbug.com/678346 [ Win7 Debug ] virtual/sharedarraybuffer/fast/dom/shadow/selections-in-shadow.html [ Pass Timeout ]
 crbug.com/678346 [ Win7 Debug ] storage/indexeddb/index-cursor.html [ Pass Timeout ]
-crbug.com/678346 [ Win7 Debug ] virtual/sharedarraybuffer/storage/indexeddb/index-cursor.html [ Pass Timeout ]
 crbug.com/678346 [ Win7 Debug ] storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass Timeout ]
-crbug.com/678346 [ Win7 Debug ] virtual/sharedarraybuffer/storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass Timeout ]
 crbug.com/678346 [ Win7 Debug ] storage/indexeddb/structured-clone.html [ Pass Timeout ]
-crbug.com/678346 [ Win7 Debug ] virtual/sharedarraybuffer/storage/indexeddb/structured-clone.html [ Pass Timeout ]
 
 crbug.com/678487 http/tests/inspector/resource-tree/resource-tree-reload.html [ Failure Timeout Pass ]
 crbug.com/678487 virtual/mojo-loading/http/tests/inspector/resource-tree/resource-tree-reload.html [ Failure Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index 52c8cc84..00bf19d 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -300,12 +300,6 @@
   },
   {
     "prefix": "sharedarraybuffer",
-    "base": "storage/indexeddb",
-    "args": ["--js-flags=--harmony-sharedarraybuffer",
-             "--enable-blink-features=SharedArrayBuffer"]
-  },
-  {
-    "prefix": "sharedarraybuffer",
     "base": "webaudio",
     "args": ["--js-flags=--harmony-sharedarraybuffer",
              "--enable-blink-features=SharedArrayBuffer"]
diff --git a/third_party/WebKit/LayoutTests/bindings/location-lifetime.html b/third_party/WebKit/LayoutTests/bindings/location-lifetime.html
new file mode 100644
index 0000000..2fa7c79
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/bindings/location-lifetime.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<iframe id="iframe-for-document.location"></iframe>
+<iframe id="iframe-for-window.location"></iframe>
+<script>
+test(() => {
+  let observation;
+  (function() {
+    let iframe = document.getElementById("iframe-for-document.location");
+    let location = iframe.contentDocument.location;
+    observation = internals.observeGC(location);
+  })();
+  gc();
+  assert_false(observation.wasCollected, "Location wrapper object was collected.");
+}, "document.location shouldn't be collected by GC.");
+
+test(() => {
+  let observation;
+  (function() {
+    let iframe = document.getElementById("iframe-for-window.location");
+    let location = iframe.contentWindow.location;
+    observation = internals.observeGC(location);
+  })();
+  gc();
+  assert_false(observation.wasCollected, "Location wrapper object was collected.");
+}, "window.location shouldn't be collected by GC.");
+</script>
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
deleted file mode 100644
index 97d5761f..0000000
--- a/third_party/WebKit/LayoutTests/fast/multicol/layers-in-multicol-expected.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!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
deleted file mode 100644
index 8bbd920..0000000
--- a/third_party/WebKit/LayoutTests/fast/multicol/layers-split-across-columns-expected.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!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
deleted file mode 100644
index 0b67873..0000000
--- a/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<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
new file mode 100644
index 0000000..1ebb6e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/transform-inside-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority-expected.txt
index b7db852..efeeca04 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority-expected.txt
@@ -2,31 +2,15 @@
 Tests resource priorities.
 
 
-sendSyncScriptRequest
 Request: empty-script.js?sync priority: High
-sendAsyncScriptRequest
 Request: empty-script.js?async priority: Low
-sendScriptRequestPrecededByImage
-Request: abe.png?precedingScript priority: Low
-Request: empty-script.js?precededByImage priority: Medium
-sendScriptRequestPrecededByPreloadedImage
-Request: abe.png?preloaded priority: Low
-Request: empty-script.js?precededByPreloadedImage priority: High
-Request: abe.png?followingPreload priority: Low
-sendXHRSync
+Request: abe.png?preceding priority: Low
+Request: empty-script.js?preceded priority: Medium
+Request: abe.png?precedingPreload priority: Low
+Request: empty-script.js?precededByPreload priority: High
 Request: empty.html?xhr-sync priority: VeryHigh
-sendXHRAsync
 Request: empty.html?xhr-async priority: High
-sendImageRequest
-Request: abe.png?image priority: Low
-sendStyleRequest
-Request: style.css?style priority: VeryHigh
-createIFrame
+Request: abe.png priority: Low
+Request: style.css priority: VeryHigh
 Request: empty.html?iframe priority: VeryHigh
-sendScriptsFromDocumentWriteAfterImage
-Request: abe.png?precedingDocWrite priority: Low
-Request: docwrite.js priority: Medium
-Request: empty-script.js?docWritten-1 priority: High
-Request: empty-script.js?docWritten-2 priority: High
-Request: empty-script.js?docWritten-3 priority: High
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority.html
index 025d4399..01023c0 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resource-priority.html
@@ -33,7 +33,7 @@
 function sendImageRequest()
 {
     var img = document.createElement("img");
-    img.src = "resources/abe.png?image";
+    img.src = "resources/abe.png";
     document.body.appendChild(img);
 }
 
@@ -41,7 +41,7 @@
 {
     var link = document.createElement("link");
     link.rel = "stylesheet";
-    link.href = "resources/style.css?style";
+    link.href = "resources/style.css";
     document.head.appendChild(link);
 }
 
@@ -49,8 +49,8 @@
 {
     var iframe = document.createElement("iframe");
     document.body.appendChild(iframe);
-    iframe.srcdoc = '<html><body><img src="resources/abe.png?precedingScript">'
-        + '<script src="http://localhost:8000/inspector/network/resources/empty-script.js?precededByImage"></s'
+    iframe.srcdoc = '<html><body><img src="resources/abe.png?preceding">'
+        + '<script src="http://localhost:8000/inspector/network/resources/empty-script.js?preceded"></s'
         + 'cript>;</body></html>';
 }
 
@@ -58,18 +58,9 @@
 {
     var iframe = document.createElement("iframe");
     document.body.appendChild(iframe);
-    iframe.srcdoc = '<html><body><link href="resources/abe.png?preloaded" rel=preload as=image>'
-        + '<script src="http://localhost:8000/inspector/network/resources/empty-script.js?precededByPreloadedImage"></s'
-        + 'cript><img src="resources/abe.png?followingPreload"></body></html>';
-}
-
-function sendScriptsFromDocumentWriteAfterImage()
-{
-    var iframe = document.createElement("iframe");
-    document.body.appendChild(iframe);
-    iframe.srcdoc = '<html><body><img src="resources/abe.png?precedingDocWrite">'
-        + '<script src="resources/docwrite.js"></s'
-        + 'cript></body></html>';
+    iframe.srcdoc = '<html><body><link href="resources/abe.png?precedingPreload" rel=preload as=image>'
+        + '<script src="http://localhost:8000/inspector/network/resources/empty-script.js?precededByPreload"></s'
+        + 'cript><img src="resources/abe.png?precedingPreload"></body></html>';
 }
 
 function createIFrame()
@@ -82,41 +73,36 @@
 function test()
 {
     var actions = [
-        {"fn": "sendSyncScriptRequest", "requests": 1},
-        {"fn": "sendAsyncScriptRequest", "requests": 1},
-        {"fn": "sendScriptRequestPrecededByImage", "requests": 2},
-        {"fn": "sendScriptRequestPrecededByPreloadedImage", "requests": 3},
-        {"fn": "sendXHRSync", "requests": 1},
-        {"fn": "sendXHRAsync", "requests": 1},
-        {"fn": "sendImageRequest", "requests": 1},
-        {"fn": "sendStyleRequest", "requests": 1},
-        {"fn": "createIFrame", "requests": 1},
-        {"fn": "sendScriptsFromDocumentWriteAfterImage", "requests": 5},
+        "sendSyncScriptRequest",
+        "sendAsyncScriptRequest",
+        "sendScriptRequestPrecededByImage",
+        "sendScriptRequestPrecededByPreloadedImage",
+        "sendXHRSync",
+        "sendXHRAsync",
+        "sendImageRequest",
+        "sendStyleRequest",
+        "createIFrame"
     ];
     InspectorTest.networkManager.addEventListener(SDK.NetworkManager.Events.RequestStarted, onRequestStarted);
 
     var nextAction = 0;
-    var expectedRequestCount = 0;
-    performNextAction();
+    performNextRequest();
 
-    function performNextAction()
+    function performNextRequest()
     {
         if (nextAction >= actions.length) {
             InspectorTest.networkManager.removeEventListener(SDK.NetworkManager.Events.RequestStarted, onRequestStarted);
             InspectorTest.completeTest();
             return;
         }
-        InspectorTest.addResult(actions[nextAction].fn);
-        expectedRequestCount = actions[nextAction].requests;
-        InspectorTest.evaluateInPage(actions[nextAction++].fn + "()");
+        InspectorTest.evaluateInPage(actions[nextAction++] + "()");
     }
     function onRequestStarted(event)
     {
         var request = event.data;
         InspectorTest.addResult("Request: " + request.name() + " priority: " + request.initialPriority());
-        expectedRequestCount--;
-        if (expectedRequestCount < 1)
-            performNextAction();
+        if (request.name().indexOf("preceded") == -1)
+            performNextRequest();
     }
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/docwrite.js b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/docwrite.js
deleted file mode 100644
index c6dd9f06..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/docwrite.js
+++ /dev/null
@@ -1,3 +0,0 @@
-document.write('<script src="http://localhost:8000/inspector/network/resources/empty-script.js?docWritten-1"></s' + 'cript>');
-document.write('<script src="http://localhost:8000/inspector/network/resources/empty-script.js?docWritten-2"></s' + 'cript>');
-document.write('<script src="http://localhost:8000/inspector/network/resources/empty-script.js?docWritten-3"></s' + 'cript>');
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 a92e6a8..c6cabcbb 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
new file mode 100644
index 0000000..44fc4a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-in-multicol-expected.png
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
new file mode 100644
index 0000000..27fbf58
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/layers-split-across-columns-expected.png
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 b024e71..5e1fff8 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/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
index 47485d6..ab929655 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-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 8d5f6fd3..6f98684 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 b024e71..5e1fff8 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/linux/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png
index 47485d6..ab929655 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-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 3a881330..0acea10 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 07e019c..991aaf7a 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 11b5d71..84b89da 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 f409f9e..1693941 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 07e019c..991aaf7a 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
new file mode 100644
index 0000000..9243efa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.png
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
new file mode 100644
index 0000000..86cf379
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png
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 56d7e380c..af00c64c0 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/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
index 300a55b1..aa3d62632 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-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 7e1243a1..d5d8ba4 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/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
index 497919fc..70f55312 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 38e6870..c57f417b 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 56d7e380c..af00c64c0 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/mac/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png
index 300a55b1..aa3d62632 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-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
new file mode 100644
index 0000000..62b98ea
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-in-multicol-expected.png
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
new file mode 100644
index 0000000..608b610
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/multicol/layers-split-across-columns-expected.png
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 8829276ef..6eb1bf6 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/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
index a281c42..7733c19 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-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 6837fed..5b597ed 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 8829276ef..6eb1bf6 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/win/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png
index a281c42..7733c19 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/disable-spinvalidation/paint/invalidation/svg/tabgroup-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 bbb8278..27dad6f 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 7e9778db..855bfdf8 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 bbb8278..27dad6f 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/storage/indexeddb/shared-array-buffer-throws.html b/third_party/WebKit/LayoutTests/storage/indexeddb/shared-array-buffer-throws.html
deleted file mode 100644
index 07a60c8..0000000
--- a/third_party/WebKit/LayoutTests/storage/indexeddb/shared-array-buffer-throws.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<title>IndexedDB: Attempting to serialize a SharedArrayBuffer should throw</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script>
-
-if (window.SharedArrayBuffer) {
-  indexeddb_test(
-    (t, db) => {
-      db.createObjectStore('store');
-    },
-    (t, db) => {
-      const sab = new SharedArrayBuffer(256);
-      const tx = db.transaction('store', 'readwrite');
-      const store = tx.objectStore('store');
-
-      assert_throws("DataCloneError", () => {
-        store.put({sab: sab}, 'key');
-      });
-      t.done();
-    },
-    'Serializing SharedArrayBuffer throws DataClone error.');
-} else {
-  done();
-}
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/sharedarraybuffer/storage/indexeddb/README.txt b/third_party/WebKit/LayoutTests/virtual/sharedarraybuffer/storage/indexeddb/README.txt
deleted file mode 100644
index 51001f0f..0000000
--- a/third_party/WebKit/LayoutTests/virtual/sharedarraybuffer/storage/indexeddb/README.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# This suite runs the tests in with --js-flags=--harmony-sharedarraybuffer
-# This enables the SharedArrayBuffer language feature in V8.
-# See https://github.com/tc39/ecmascript_sharedmem for more information.
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
index 9ee5682..15d211c9 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
@@ -87,9 +87,6 @@
     Transferables* transferables = nullptr;
     WebBlobInfoArray* blob_info = nullptr;
     bool write_wasm_to_stream = false;
-    // Set when serializing a value for storage; e.g. when writing to
-    // IndexedDB.
-    bool for_storage = false;
   };
   static PassRefPtr<SerializedScriptValue> Serialize(v8::Isolate*,
                                                      v8::Local<v8::Value>,
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
index 9564753..fbde869 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
@@ -75,8 +75,7 @@
   Location* location = window->location();
   DCHECK(location);
 
-  // Keep the wrapper object for the return value alive as long as |this|
-  // object is alive in order to save creation time of the wrapper object.
+  // If we have already created a wrapper object in this world, returns it.
   if (DOMDataStore::SetReturnValue(info.GetReturnValue(), location))
     return;
 
@@ -101,17 +100,6 @@
     wrapper = ToV8(location, holder, isolate);
   }
 
-  // Keep the wrapper object for the return value alive as long as |this|
-  // object is alive in order to save creation time of the wrapper object.
-  //
-  // TODO(dcheng): The hidden reference behavior is broken in many ways. We
-  // should be caching for all DOM attributes. Even if it's not critical for
-  // remote Location objects, we should clean this up to improve
-  // maintainability. In the long-term, this will be superseded by wrapper
-  // tracing.
-  V8PrivateProperty::GetSymbol(isolate, "KeepAlive#Window#location")
-      .Set(holder, wrapper);
-
   V8SetReturnValue(info, wrapper);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
index dee9be5..bc0cf537 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
@@ -51,8 +51,7 @@
       serializer_(script_state_->GetIsolate(), this),
       transferables_(options.transferables),
       blob_info_array_(options.blob_info),
-      inline_wasm_(options.write_wasm_to_stream),
-      for_storage_(options.for_storage) {}
+      inline_wasm_(options.write_wasm_to_stream) {}
 
 RefPtr<SerializedScriptValue> V8ScriptValueSerializer::Serialize(
     v8::Local<v8::Value> value,
@@ -118,37 +117,32 @@
 
 void V8ScriptValueSerializer::FinalizeTransfer(
     ExceptionState& exception_state) {
+  if (!transferables_ && shared_array_buffers_.IsEmpty())
+    return;
+
   // TODO(jbroman): Strictly speaking, this is not correct; transfer should
   // occur in the order of the transfer list.
   // https://html.spec.whatwg.org/multipage/infrastructure.html#structuredclonewithtransfer
 
-  v8::Isolate* isolate = script_state_->GetIsolate();
-
-  // The order of ArrayBuffers and SharedArrayBuffers matters; we use the index
-  // into this array for deserialization.
   ArrayBufferArray array_buffers;
-  if (transferables_)
-    array_buffers.AppendVector(transferables_->array_buffers);
+  array_buffers.AppendVector(transferables_->array_buffers);
   array_buffers.AppendVector(shared_array_buffers_);
 
-  if (!array_buffers.IsEmpty()) {
-    serialized_script_value_->TransferArrayBuffers(isolate, array_buffers,
-                                                   exception_state);
-    if (exception_state.HadException())
-      return;
-  }
+  v8::Isolate* isolate = script_state_->GetIsolate();
+  serialized_script_value_->TransferArrayBuffers(isolate, array_buffers,
+                                                 exception_state);
+  if (exception_state.HadException())
+    return;
 
-  if (transferables_) {
-    serialized_script_value_->TransferImageBitmaps(
-        isolate, transferables_->image_bitmaps, exception_state);
-    if (exception_state.HadException())
-      return;
+  serialized_script_value_->TransferImageBitmaps(
+      isolate, transferables_->image_bitmaps, exception_state);
+  if (exception_state.HadException())
+    return;
 
-    serialized_script_value_->TransferOffscreenCanvas(
-        isolate, transferables_->offscreen_canvases, exception_state);
-    if (exception_state.HadException())
-      return;
-  }
+  serialized_script_value_->TransferOffscreenCanvas(
+      isolate, transferables_->offscreen_canvases, exception_state);
+  if (exception_state.HadException())
+    return;
 }
 
 void V8ScriptValueSerializer::WriteUTF8String(const String& string) {
@@ -405,18 +399,6 @@
 v8::Maybe<uint32_t> V8ScriptValueSerializer::GetSharedArrayBufferId(
     v8::Isolate* isolate,
     v8::Local<v8::SharedArrayBuffer> v8_shared_array_buffer) {
-  if (for_storage_) {
-    DCHECK(exception_state_);
-    DCHECK_EQ(isolate, script_state_->GetIsolate());
-    ExceptionState exception_state(isolate, exception_state_->Context(),
-                                   exception_state_->InterfaceName(),
-                                   exception_state_->PropertyName());
-    exception_state.ThrowDOMException(
-        kDataCloneError,
-        "A SharedArrayBuffer can not be serialized for storage.");
-    return v8::Nothing<uint32_t>();
-  }
-
   DOMSharedArrayBuffer* shared_array_buffer =
       V8SharedArrayBuffer::toImpl(v8_shared_array_buffer);
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h
index 8606080..d01afa95 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.h
@@ -99,7 +99,6 @@
   WebBlobInfoArray* blob_info_array_ = nullptr;
   ArrayBufferArray shared_array_buffers_;
   bool inline_wasm_ = false;
-  bool for_storage_ = false;
 #if DCHECK_IS_ON()
   bool serialize_invoked_ = false;
 #endif
diff --git a/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
index e4da7d3..a63d9fb 100644
--- a/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
+++ b/third_party/WebKit/Source/core/css/ActiveStyleSheetsTest.cpp
@@ -421,7 +421,7 @@
   EXPECT_EQ(0u, changed_rule_sets.size());
 
   CSSStyleSheet* sheet1 = CreateSheet();
-  MediaQuerySet* mq =
+  RefPtr<MediaQuerySet> mq =
       MediaQueryParser::ParseMediaQuerySet("(min-width: 9000px)");
   sheet1->SetMediaQueries(mq);
   sheet1->MatchesMediaQueries(MediaQueryEvaluator());
diff --git a/third_party/WebKit/Source/core/css/CSSMediaRule.cpp b/third_party/WebKit/Source/core/css/CSSMediaRule.cpp
index bba764b72..36d6566 100644
--- a/third_party/WebKit/Source/core/css/CSSMediaRule.cpp
+++ b/third_party/WebKit/Source/core/css/CSSMediaRule.cpp
@@ -32,7 +32,7 @@
 
 CSSMediaRule::~CSSMediaRule() {}
 
-MediaQuerySet* CSSMediaRule::MediaQueries() const {
+RefPtr<MediaQuerySet> CSSMediaRule::MediaQueries() const {
   return ToStyleRuleMedia(group_rule_.Get())->MediaQueries();
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSMediaRule.h b/third_party/WebKit/Source/core/css/CSSMediaRule.h
index 8930537..5913849 100644
--- a/third_party/WebKit/Source/core/css/CSSMediaRule.h
+++ b/third_party/WebKit/Source/core/css/CSSMediaRule.h
@@ -53,7 +53,7 @@
 
   CSSRule::Type type() const override { return kMediaRule; }
 
-  MediaQuerySet* MediaQueries() const;
+  RefPtr<MediaQuerySet> MediaQueries() const;
 
   mutable Member<MediaList> media_cssom_wrapper_;
 };
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
index a33670b5..887c142 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
+++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
@@ -205,8 +205,8 @@
   DidMutate();
 }
 
-void CSSStyleSheet::SetMediaQueries(MediaQuerySet* media_queries) {
-  media_queries_ = media_queries;
+void CSSStyleSheet::SetMediaQueries(RefPtr<MediaQuerySet> media_queries) {
+  media_queries_ = std::move(media_queries);
   if (media_cssom_wrapper_ && media_queries_)
     media_cssom_wrapper_->Reattach(media_queries_.Get());
 }
@@ -217,7 +217,7 @@
 
   if (!media_queries_)
     return true;
-  return evaluator.Eval(media_queries_,
+  return evaluator.Eval(*media_queries_,
                         &viewport_dependent_media_query_results_,
                         &device_dependent_media_query_results_);
 }
@@ -442,9 +442,6 @@
 
 DEFINE_TRACE(CSSStyleSheet) {
   visitor->Trace(contents_);
-  visitor->Trace(media_queries_);
-  visitor->Trace(viewport_dependent_media_query_results_);
-  visitor->Trace(device_dependent_media_query_results_);
   visitor->Trace(owner_node_);
   visitor->Trace(owner_rule_);
   visitor->Trace(media_cssom_wrapper_);
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.h b/third_party/WebKit/Source/core/css/CSSStyleSheet.h
index d14803fd..eb00fc5 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleSheet.h
+++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.h
@@ -99,8 +99,8 @@
 
   void ClearOwnerRule() { owner_rule_ = nullptr; }
   Document* OwnerDocument() const;
-  const MediaQuerySet* MediaQueries() const { return media_queries_; }
-  void SetMediaQueries(MediaQuerySet*);
+  const MediaQuerySet* MediaQueries() const { return media_queries_.Get(); }
+  void SetMediaQueries(RefPtr<MediaQuerySet>);
   bool MatchesMediaQueries(const MediaQueryEvaluator&);
   bool HasMediaQueryResults() const {
     return !viewport_dependent_media_query_results_.IsEmpty() ||
@@ -167,7 +167,7 @@
   bool is_disabled_ = false;
   bool load_completed_ = false;
   String title_;
-  Member<MediaQuerySet> media_queries_;
+  RefPtr<MediaQuerySet> media_queries_;
   MediaQueryResultList viewport_dependent_media_query_results_;
   MediaQueryResultList device_dependent_media_query_results_;
 
diff --git a/third_party/WebKit/Source/core/css/MediaList.cpp b/third_party/WebKit/Source/core/css/MediaList.cpp
index f6edcc5..93e67a4 100644
--- a/third_party/WebKit/Source/core/css/MediaList.cpp
+++ b/third_party/WebKit/Source/core/css/MediaList.cpp
@@ -22,7 +22,6 @@
 #include <memory>
 #include "bindings/core/v8/ExceptionState.h"
 #include "core/css/CSSStyleSheet.h"
-#include "core/css/MediaQuery.h"
 #include "core/css/MediaQueryExp.h"
 #include "core/css/parser/MediaQueryParser.h"
 #include "platform/wtf/text/StringBuilder.h"
@@ -58,7 +57,7 @@
     queries_[i] = o.queries_[i]->Copy();
 }
 
-MediaQuerySet* MediaQuerySet::Create(const String& media_string) {
+RefPtr<MediaQuerySet> MediaQuerySet::Create(const String& media_string) {
   if (media_string.IsEmpty())
     return MediaQuerySet::Create();
 
@@ -66,7 +65,7 @@
 }
 
 bool MediaQuerySet::Set(const String& media_string) {
-  MediaQuerySet* result = Create(media_string);
+  RefPtr<MediaQuerySet> result = Create(media_string);
   // TODO(keishi) Changed DCHECK to CHECK for crbug.com/699269 diagnosis
   for (const auto& query : result->queries_) {
     CHECK(query);
@@ -79,25 +78,25 @@
   // To "parse a media query" for a given string means to follow "the parse
   // a media query list" steps and return "null" if more than one media query
   // is returned, or else the returned media query.
-  MediaQuerySet* result = Create(query_string);
+  RefPtr<MediaQuerySet> result = Create(query_string);
 
   // Only continue if exactly one media query is found, as described above.
   if (result->queries_.size() != 1)
     return true;
 
-  MediaQuery* new_query = result->queries_[0].Release();
+  std::unique_ptr<MediaQuery> new_query = std::move(result->queries_[0]);
   // TODO(keishi) Changed DCHECK to CHECK for crbug.com/699269 diagnosis
   CHECK(new_query);
 
   // If comparing with any of the media queries in the collection of media
   // queries returns true terminate these steps.
   for (size_t i = 0; i < queries_.size(); ++i) {
-    MediaQuery* query = queries_[i].Get();
-    if (*query == *new_query)
+    MediaQuery& query = *queries_[i];
+    if (query == *new_query)
       return true;
   }
 
-  queries_.push_back(new_query);
+  queries_.push_back(std::move(new_query));
   return true;
 }
 
@@ -105,13 +104,13 @@
   // To "parse a media query" for a given string means to follow "the parse
   // a media query list" steps and return "null" if more than one media query
   // is returned, or else the returned media query.
-  MediaQuerySet* result = Create(query_string_to_remove);
+  RefPtr<MediaQuerySet> result = Create(query_string_to_remove);
 
   // Only continue if exactly one media query is found, as described above.
   if (result->queries_.size() != 1)
     return true;
 
-  MediaQuery* new_query = result->queries_[0].Release();
+  std::unique_ptr<MediaQuery> new_query = std::move(result->queries_[0]);
   // TODO(keishi) Changed DCHECK to CHECK for crbug.com/699269 diagnosis
   CHECK(new_query);
 
@@ -119,8 +118,8 @@
   // comparing with the media query returns true.
   bool found = false;
   for (size_t i = 0; i < queries_.size(); ++i) {
-    MediaQuery* query = queries_[i].Get();
-    if (*query == *new_query) {
+    MediaQuery& query = *queries_[i];
+    if (query == *new_query) {
       queries_.erase(i);
       --i;
       found = true;
@@ -130,10 +129,10 @@
   return found;
 }
 
-void MediaQuerySet::AddMediaQuery(MediaQuery* media_query) {
+void MediaQuerySet::AddMediaQuery(std::unique_ptr<MediaQuery> media_query) {
   // TODO(keishi) Changed DCHECK to CHECK for crbug.com/699269 diagnosis
   CHECK(media_query);
-  queries_.push_back(media_query);
+  queries_.push_back(std::move(media_query));
 }
 
 String MediaQuerySet::MediaText() const {
@@ -150,16 +149,13 @@
   return text.ToString();
 }
 
-DEFINE_TRACE(MediaQuerySet) {
-  visitor->Trace(queries_);
-}
-
-MediaList::MediaList(MediaQuerySet* media_queries, CSSStyleSheet* parent_sheet)
+MediaList::MediaList(RefPtr<MediaQuerySet> media_queries,
+                     CSSStyleSheet* parent_sheet)
     : media_queries_(media_queries),
       parent_style_sheet_(parent_sheet),
       parent_rule_(nullptr) {}
 
-MediaList::MediaList(MediaQuerySet* media_queries, CSSRule* parent_rule)
+MediaList::MediaList(RefPtr<MediaQuerySet> media_queries, CSSRule* parent_rule)
     : media_queries_(media_queries),
       parent_style_sheet_(nullptr),
       parent_rule_(parent_rule) {}
@@ -174,7 +170,8 @@
 }
 
 String MediaList::item(unsigned index) const {
-  const HeapVector<Member<MediaQuery>>& queries = media_queries_->QueryVector();
+  const Vector<std::unique_ptr<MediaQuery>>& queries =
+      media_queries_->QueryVector();
   if (index < queries.size())
     return queries[index]->CssText();
   return String();
@@ -210,7 +207,7 @@
     parent_style_sheet_->DidMutate();
 }
 
-void MediaList::Reattach(MediaQuerySet* media_queries) {
+void MediaList::Reattach(RefPtr<MediaQuerySet> media_queries) {
   // TODO(keishi) Changed DCHECK to CHECK for crbug.com/699269 diagnosis
   CHECK(media_queries);
   for (const auto& query : media_queries->QueryVector()) {
@@ -220,7 +217,6 @@
 }
 
 DEFINE_TRACE(MediaList) {
-  visitor->Trace(media_queries_);
   visitor->Trace(parent_style_sheet_);
   visitor->Trace(parent_rule_);
 }
diff --git a/third_party/WebKit/Source/core/css/MediaList.h b/third_party/WebKit/Source/core/css/MediaList.h
index 4942ad1..486bfca3f 100644
--- a/third_party/WebKit/Source/core/css/MediaList.h
+++ b/third_party/WebKit/Source/core/css/MediaList.h
@@ -24,6 +24,7 @@
 
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "core/CoreExport.h"
+#include "core/css/MediaQuery.h"
 #include "core/dom/ExceptionCode.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/Forward.h"
@@ -38,44 +39,49 @@
 class MediaList;
 class MediaQuery;
 
-class CORE_EXPORT MediaQuerySet : public GarbageCollected<MediaQuerySet> {
+class CORE_EXPORT MediaQuerySet : public RefCounted<MediaQuerySet> {
  public:
-  static MediaQuerySet* Create() { return new MediaQuerySet(); }
-  static MediaQuerySet* Create(const String& media_string);
+  static RefPtr<MediaQuerySet> Create() {
+    return AdoptRef(new MediaQuerySet());
+  }
+  static RefPtr<MediaQuerySet> Create(const String& media_string);
 
   bool Set(const String&);
   bool Add(const String&);
   bool Remove(const String&);
 
-  void AddMediaQuery(MediaQuery*);
+  void AddMediaQuery(std::unique_ptr<MediaQuery>);
 
-  const HeapVector<Member<MediaQuery>>& QueryVector() const { return queries_; }
+  const Vector<std::unique_ptr<MediaQuery>>& QueryVector() const {
+    return queries_;
+  }
 
   String MediaText() const;
 
-  MediaQuerySet* Copy() const { return new MediaQuerySet(*this); }
-
-  DECLARE_TRACE();
+  RefPtr<MediaQuerySet> Copy() const {
+    return AdoptRef(new MediaQuerySet(*this));
+  }
 
  private:
   MediaQuerySet();
   MediaQuerySet(const MediaQuerySet&);
 
-  HeapVector<Member<MediaQuery>> queries_;
+  Vector<std::unique_ptr<MediaQuery>> queries_;
 };
 
-class MediaList final : public GarbageCollected<MediaList>,
+class MediaList final : public GarbageCollectedFinalized<MediaList>,
                         public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static MediaList* Create(MediaQuerySet* media_queries,
+  static MediaList* Create(RefPtr<MediaQuerySet> media_queries,
                            CSSStyleSheet* parent_sheet) {
-    return new MediaList(media_queries, parent_sheet);
+    return new MediaList(std::move(media_queries), parent_sheet);
   }
 
-  static MediaList* Create(MediaQuerySet* media_queries, CSSRule* parent_rule) {
-    return new MediaList(media_queries, parent_rule);
+  static MediaList* Create(RefPtr<MediaQuerySet> media_queries,
+                           CSSRule* parent_rule) {
+    return new MediaList(std::move(media_queries), parent_rule);
   }
 
   unsigned length() const { return media_queries_->QueryVector().size(); }
@@ -92,19 +98,16 @@
 
   const MediaQuerySet* Queries() const { return media_queries_.Get(); }
 
-  void Reattach(MediaQuerySet*);
+  void Reattach(RefPtr<MediaQuerySet>);
 
   DECLARE_TRACE();
 
  private:
-  MediaList(MediaQuerySet*, CSSStyleSheet* parent_sheet);
-  MediaList(MediaQuerySet*, CSSRule* parent_rule);
+  MediaList(RefPtr<MediaQuerySet>, CSSStyleSheet* parent_sheet);
+  MediaList(RefPtr<MediaQuerySet>, CSSRule* parent_rule);
 
-  Member<MediaQuerySet> media_queries_;
-  // Cleared in ~CSSStyleSheet destructor when oilpan is not enabled.
+  RefPtr<MediaQuerySet> media_queries_;
   Member<CSSStyleSheet> parent_style_sheet_;
-  // Cleared in the ~CSSMediaRule and ~CSSImportRule destructors when oilpan is
-  // not enabled.
   Member<CSSRule> parent_rule_;
 };
 
diff --git a/third_party/WebKit/Source/core/css/MediaQuery.cpp b/third_party/WebKit/Source/core/css/MediaQuery.cpp
index 3488aba..b91c5db 100644
--- a/third_party/WebKit/Source/core/css/MediaQuery.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQuery.cpp
@@ -61,29 +61,29 @@
     result.Append(" and ");
   }
 
-  result.Append(expressions_.at(0)->Serialize());
+  result.Append(expressions_.at(0).Serialize());
   for (size_t i = 1; i < expressions_.size(); ++i) {
     result.Append(" and ");
-    result.Append(expressions_.at(i)->Serialize());
+    result.Append(expressions_.at(i).Serialize());
   }
   return result.ToString();
 }
 
-static bool ExpressionCompare(const Member<MediaQueryExp>& a,
-                              const Member<MediaQueryExp>& b) {
-  return CodePointCompare(a->Serialize(), b->Serialize()) < 0;
+static bool ExpressionCompare(const MediaQueryExp& a, const MediaQueryExp& b) {
+  return CodePointCompare(a.Serialize(), b.Serialize()) < 0;
 }
 
-MediaQuery* MediaQuery::CreateNotAll() {
-  return new MediaQuery(MediaQuery::kNot, MediaTypeNames::all,
-                        ExpressionHeapVector());
+std::unique_ptr<MediaQuery> MediaQuery::CreateNotAll() {
+  return WTF::MakeUnique<MediaQuery>(MediaQuery::kNot, MediaTypeNames::all,
+                                     ExpressionHeapVector());
 }
 
-MediaQuery* MediaQuery::Create(RestrictorType restrictor,
-                               String media_type,
-                               ExpressionHeapVector expressions) {
-  return new MediaQuery(restrictor, std::move(media_type),
-                        std::move(expressions));
+std::unique_ptr<MediaQuery> MediaQuery::Create(
+    RestrictorType restrictor,
+    String media_type,
+    ExpressionHeapVector expressions) {
+  return WTF::MakeUnique<MediaQuery>(restrictor, std::move(media_type),
+                                     std::move(expressions));
 }
 
 MediaQuery::MediaQuery(RestrictorType restrictor,
@@ -95,11 +95,11 @@
   NonCopyingSort(expressions_.begin(), expressions_.end(), ExpressionCompare);
 
   // Remove all duplicated expressions.
-  MediaQueryExp* key = 0;
+  MediaQueryExp key = MediaQueryExp::Invalid();
   for (int i = expressions_.size() - 1; i >= 0; --i) {
-    MediaQueryExp* exp = expressions_.at(i).Get();
-
-    if (key && *exp == *key)
+    MediaQueryExp exp = expressions_.at(i);
+    CHECK(exp.IsValid());
+    if (exp == key)
       expressions_.erase(i);
     else
       key = exp;
@@ -112,7 +112,7 @@
       serialization_cache_(o.serialization_cache_) {
   expressions_.ReserveInitialCapacity(o.expressions_.size());
   for (unsigned i = 0; i < o.expressions_.size(); ++i)
-    expressions_.push_back(o.expressions_[i]->Copy());
+    expressions_.push_back(o.expressions_[i]);
 }
 
 MediaQuery::~MediaQuery() {}
@@ -130,8 +130,4 @@
   return serialization_cache_;
 }
 
-DEFINE_TRACE(MediaQuery) {
-  visitor->Trace(expressions_);
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/MediaQuery.h b/third_party/WebKit/Source/core/css/MediaQuery.h
index 9be5c34..8223f50 100644
--- a/third_party/WebKit/Source/core/css/MediaQuery.h
+++ b/third_party/WebKit/Source/core/css/MediaQuery.h
@@ -39,17 +39,19 @@
 namespace blink {
 class MediaQueryExp;
 
-using ExpressionHeapVector = HeapVector<Member<MediaQueryExp>>;
+using ExpressionHeapVector = Vector<MediaQueryExp>;
 
-class CORE_EXPORT MediaQuery : public GarbageCollectedFinalized<MediaQuery> {
+class CORE_EXPORT MediaQuery {
  public:
   enum RestrictorType { kOnly, kNot, kNone };
 
-  static MediaQuery* Create(RestrictorType,
-                            String media_type,
-                            ExpressionHeapVector);
-  static MediaQuery* CreateNotAll();
+  static std::unique_ptr<MediaQuery> Create(RestrictorType,
+                                            String media_type,
+                                            ExpressionHeapVector);
+  static std::unique_ptr<MediaQuery> CreateNotAll();
 
+  MediaQuery(RestrictorType, String media_type, ExpressionHeapVector);
+  MediaQuery(const MediaQuery&);
   ~MediaQuery();
 
   RestrictorType Restrictor() const { return restrictor_; }
@@ -58,14 +60,11 @@
   bool operator==(const MediaQuery& other) const;
   String CssText() const;
 
-  MediaQuery* Copy() const { return new MediaQuery(*this); }
-
-  DECLARE_TRACE();
+  std::unique_ptr<MediaQuery> Copy() const {
+    return WTF::MakeUnique<MediaQuery>(*this);
+  }
 
  private:
-  MediaQuery(RestrictorType, String media_type, ExpressionHeapVector);
-  MediaQuery(const MediaQuery&);
-
   MediaQuery& operator=(const MediaQuery&) = delete;
 
   RestrictorType restrictor_;
diff --git a/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp b/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp
index f8c46e4..a05ca2f9 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp
@@ -112,42 +112,41 @@
 }
 
 bool MediaQueryEvaluator::Eval(
-    const MediaQuery* query,
+    const MediaQuery& query,
     MediaQueryResultList* viewport_dependent_media_query_results,
     MediaQueryResultList* device_dependent_media_query_results) const {
-  if (!MediaTypeMatch(query->MediaType()))
-    return ApplyRestrictor(query->Restrictor(), false);
+  if (!MediaTypeMatch(query.MediaType()))
+    return ApplyRestrictor(query.Restrictor(), false);
 
-  const ExpressionHeapVector& expressions = query->Expressions();
+  const ExpressionHeapVector& expressions = query.Expressions();
   // Iterate through expressions, stop if any of them eval to false (AND
   // semantics).
   size_t i = 0;
   for (; i < expressions.size(); ++i) {
-    bool expr_result = Eval(expressions.at(i).Get());
+    bool expr_result = Eval(expressions.at(i));
     if (viewport_dependent_media_query_results &&
-        expressions.at(i)->IsViewportDependent())
+        expressions.at(i).IsViewportDependent()) {
       viewport_dependent_media_query_results->push_back(
-          new MediaQueryResult(*expressions.at(i), expr_result));
+          MediaQueryResult(expressions.at(i), expr_result));
+    }
     if (device_dependent_media_query_results &&
-        expressions.at(i)->IsDeviceDependent())
+        expressions.at(i).IsDeviceDependent()) {
       device_dependent_media_query_results->push_back(
-          new MediaQueryResult(*expressions.at(i), expr_result));
+          MediaQueryResult(expressions.at(i), expr_result));
+    }
     if (!expr_result)
       break;
   }
 
   // Assume true if we are at the end of the list, otherwise assume false.
-  return ApplyRestrictor(query->Restrictor(), expressions.size() == i);
+  return ApplyRestrictor(query.Restrictor(), expressions.size() == i);
 }
 
 bool MediaQueryEvaluator::Eval(
-    const MediaQuerySet* query_set,
+    const MediaQuerySet& query_set,
     MediaQueryResultList* viewport_dependent_media_query_results,
     MediaQueryResultList* device_dependent_media_query_results) const {
-  if (!query_set)
-    return true;
-
-  const HeapVector<Member<MediaQuery>>& queries = query_set->QueryVector();
+  const Vector<std::unique_ptr<MediaQuery>>& queries = query_set.QueryVector();
   if (!queries.size())
     return true;  // Empty query list evaluates to true.
 
@@ -155,8 +154,8 @@
   bool result = false;
   for (size_t i = 0; i < queries.size() && !result; ++i) {
     // TODO(sof): CHECK() added for crbug.com/699269 diagnosis, remove sooner.
-    CHECK_EQ(queries.data(), query_set->QueryVector().data());
-    result = Eval(queries[i].Get(), viewport_dependent_media_query_results,
+    CHECK_EQ(queries.data(), query_set.QueryVector().data());
+    result = Eval(*queries[i], viewport_dependent_media_query_results,
                   device_dependent_media_query_results);
   }
 
@@ -809,7 +808,7 @@
 #undef ADD_TO_FUNCTIONMAP
 }
 
-bool MediaQueryEvaluator::Eval(const MediaQueryExp* expr) const {
+bool MediaQueryEvaluator::Eval(const MediaQueryExp& expr) const {
   if (!media_values_ || !media_values_->HasValues())
     return true;
 
@@ -817,9 +816,9 @@
 
   // Call the media feature evaluation function. Assume no prefix and let
   // trampoline functions override the prefix if prefix is used.
-  EvalFunc func = g_function_map->at(expr->MediaFeature().Impl());
+  EvalFunc func = g_function_map->at(expr.MediaFeature().Impl());
   if (func)
-    return func(expr->ExpValue(), kNoPrefix, *media_values_);
+    return func(expr.ExpValue(), kNoPrefix, *media_values_);
 
   return false;
 }
diff --git a/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h b/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h
index 7fe8fe8..4d30601 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h
+++ b/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h
@@ -41,7 +41,7 @@
 class MediaValues;
 class MediaValuesInitialViewport;
 
-using MediaQueryResultList = HeapVector<Member<MediaQueryResult>>;
+using MediaQueryResultList = Vector<MediaQueryResult>;
 
 // Class that evaluates css media queries as defined in
 // CSS3 Module "Media Queries" (http://www.w3.org/TR/css3-mediaqueries/)
@@ -83,17 +83,17 @@
   bool MediaTypeMatch(const String& media_type_to_match) const;
 
   // Evaluates a list of media queries.
-  bool Eval(const MediaQuerySet*,
+  bool Eval(const MediaQuerySet&,
             MediaQueryResultList* viewport_dependent = nullptr,
             MediaQueryResultList* device_dependent = nullptr) const;
 
   // Evaluates media query.
-  bool Eval(const MediaQuery*,
+  bool Eval(const MediaQuery&,
             MediaQueryResultList* viewport_dependent = nullptr,
             MediaQueryResultList* device_dependent = nullptr) const;
 
   // Evaluates media query subexpression, ie "and (media-feature: value)" part.
-  bool Eval(const MediaQueryExp*) const;
+  bool Eval(const MediaQueryExp&) const;
 
   DECLARE_TRACE();
 
diff --git a/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp b/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp
index db02731..75372d2 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp
@@ -139,11 +139,10 @@
 
 void TestMQEvaluator(TestCase* test_cases,
                      const MediaQueryEvaluator& media_query_evaluator) {
-  Persistent<MediaQuerySet> query_set = nullptr;
+  RefPtr<MediaQuerySet> query_set = nullptr;
   for (unsigned i = 0; test_cases[i].input; ++i) {
     query_set = MediaQuerySet::Create(test_cases[i].input);
-    EXPECT_EQ(test_cases[i].output,
-              media_query_evaluator.Eval(query_set.Get()));
+    EXPECT_EQ(test_cases[i].output, media_query_evaluator.Eval(*query_set));
   }
 }
 
@@ -194,8 +193,8 @@
   page_holder.reset();
   ASSERT_EQ(nullptr, frame->View());
   MediaQueryEvaluator media_query_evaluator(frame);
-  MediaQuerySet* query_set = MediaQuerySet::Create("foobar");
-  EXPECT_FALSE(media_query_evaluator.Eval(query_set));
+  RefPtr<MediaQuerySet> query_set = MediaQuerySet::Create("foobar");
+  EXPECT_FALSE(media_query_evaluator.Eval(*query_set));
 }
 
 TEST(MediaQueryEvaluatorTest, CachedFloatViewport) {
diff --git a/third_party/WebKit/Source/core/css/MediaQueryExp.cpp b/third_party/WebKit/Source/core/css/MediaQueryExp.cpp
index b97736c1..334a816 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryExp.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryExp.cpp
@@ -218,7 +218,7 @@
                              const MediaQueryExpValue& exp_value)
     : media_feature_(media_feature), exp_value_(exp_value) {}
 
-MediaQueryExp* MediaQueryExp::CreateIfValid(
+MediaQueryExp MediaQueryExp::Create(
     const String& media_feature,
     const Vector<CSSParserToken, 4>& token_list) {
   DCHECK(!media_feature.IsNull());
@@ -236,7 +236,7 @@
     if (token.GetType() == kIdentToken) {
       CSSValueID ident = token.Id();
       if (!FeatureWithValidIdent(lower_media_feature, ident))
-        return nullptr;
+        return Invalid();
       exp_value.id = ident;
       exp_value.is_id = true;
     } else if (token.GetType() == kNumberToken ||
@@ -262,10 +262,10 @@
         exp_value.unit = CSSPrimitiveValue::UnitType::kNumber;
         exp_value.is_value = true;
       } else {
-        return nullptr;
+        return Invalid();
       }
     } else {
-      return nullptr;
+      return Invalid();
     }
   } else if (token_list.size() == 3 &&
              FeatureWithAspectRatio(lower_media_feature)) {
@@ -275,23 +275,23 @@
     const CSSParserToken& delimiter = token_list[1];
     const CSSParserToken& denominator = token_list[2];
     if (delimiter.GetType() != kDelimiterToken || delimiter.Delimiter() != '/')
-      return nullptr;
+      return Invalid();
     if (numerator.GetType() != kNumberToken || numerator.NumericValue() <= 0 ||
         numerator.GetNumericValueType() != kIntegerValueType)
-      return nullptr;
+      return Invalid();
     if (denominator.GetType() != kNumberToken ||
         denominator.NumericValue() <= 0 ||
         denominator.GetNumericValueType() != kIntegerValueType)
-      return nullptr;
+      return Invalid();
 
     exp_value.numerator = (unsigned)numerator.NumericValue();
     exp_value.denominator = (unsigned)denominator.NumericValue();
     exp_value.is_ratio = true;
   } else {
-    return nullptr;
+    return Invalid();
   }
 
-  return new MediaQueryExp(lower_media_feature, exp_value);
+  return MediaQueryExp(lower_media_feature, exp_value);
 }
 
 MediaQueryExp::~MediaQueryExp() {}
diff --git a/third_party/WebKit/Source/core/css/MediaQueryExp.h b/third_party/WebKit/Source/core/css/MediaQueryExp.h
index 20f3fe71..6f962b3 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryExp.h
+++ b/third_party/WebKit/Source/core/css/MediaQueryExp.h
@@ -77,17 +77,26 @@
   }
 };
 
-class CORE_EXPORT MediaQueryExp
-    : public GarbageCollectedFinalized<MediaQueryExp> {
+class CORE_EXPORT MediaQueryExp {
+  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+
  public:
-  static MediaQueryExp* CreateIfValid(const String& media_feature,
-                                      const Vector<CSSParserToken, 4>&);
+  // Returns an invalid MediaQueryExp if the arguments are invalid.
+  static MediaQueryExp Create(const String& media_feature,
+                              const Vector<CSSParserToken, 4>&);
+  static MediaQueryExp Invalid() {
+    return MediaQueryExp(String(), MediaQueryExpValue());
+  }
+
+  MediaQueryExp(const MediaQueryExp& other);
   ~MediaQueryExp();
 
   const String& MediaFeature() const { return media_feature_; }
 
   MediaQueryExpValue ExpValue() const { return exp_value_; }
 
+  bool IsValid() const { return !media_feature_.IsNull(); }
+
   bool operator==(const MediaQueryExp& other) const;
 
   bool IsViewportDependent() const;
@@ -96,12 +105,6 @@
 
   String Serialize() const;
 
-  MediaQueryExp* Copy() const { return new MediaQueryExp(*this); }
-
-  MediaQueryExp(const MediaQueryExp& other);
-
-  DEFINE_INLINE_TRACE() {}
-
  private:
   MediaQueryExp(const String&, const MediaQueryExpValue&);
 
diff --git a/third_party/WebKit/Source/core/css/MediaQueryList.cpp b/third_party/WebKit/Source/core/css/MediaQueryList.cpp
index c8d8670cb3..5c4f66b6 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryList.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryList.cpp
@@ -29,13 +29,13 @@
 
 MediaQueryList* MediaQueryList::Create(ExecutionContext* context,
                                        MediaQueryMatcher* matcher,
-                                       MediaQuerySet* media) {
-  return new MediaQueryList(context, matcher, media);
+                                       RefPtr<MediaQuerySet> media) {
+  return new MediaQueryList(context, matcher, RefPtr<MediaQuerySet>(media));
 }
 
 MediaQueryList::MediaQueryList(ExecutionContext* context,
                                MediaQueryMatcher* matcher,
-                               MediaQuerySet* media)
+                               RefPtr<MediaQuerySet> media)
     : ContextLifecycleObserver(context),
       matcher_(matcher),
       media_(media),
@@ -116,7 +116,6 @@
 
 DEFINE_TRACE(MediaQueryList) {
   visitor->Trace(matcher_);
-  visitor->Trace(media_);
   visitor->Trace(listeners_);
   EventTargetWithInlineData::Trace(visitor);
   ContextLifecycleObserver::Trace(visitor);
diff --git a/third_party/WebKit/Source/core/css/MediaQueryList.h b/third_party/WebKit/Source/core/css/MediaQueryList.h
index c67b340..aa86b6d 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryList.h
+++ b/third_party/WebKit/Source/core/css/MediaQueryList.h
@@ -52,7 +52,7 @@
  public:
   static MediaQueryList* Create(ExecutionContext*,
                                 MediaQueryMatcher*,
-                                MediaQuerySet*);
+                                RefPtr<MediaQuerySet>);
   ~MediaQueryList() override;
 
   String media() const;
@@ -86,12 +86,12 @@
   ExecutionContext* GetExecutionContext() const override;
 
  private:
-  MediaQueryList(ExecutionContext*, MediaQueryMatcher*, MediaQuerySet*);
+  MediaQueryList(ExecutionContext*, MediaQueryMatcher*, RefPtr<MediaQuerySet>);
 
   bool UpdateMatches();
 
   Member<MediaQueryMatcher> matcher_;
-  Member<MediaQuerySet> media_;
+  RefPtr<MediaQuerySet> media_;
   using ListenerList = HeapListHashSet<Member<MediaQueryListListener>>;
   ListenerList listeners_;
   bool matches_dirty_;
diff --git a/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp b/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp
index b6a4eee..b28d994e 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp
@@ -66,7 +66,7 @@
     evaluator_ = CreateEvaluator();
 
   if (evaluator_)
-    return evaluator_->Eval(media);
+    return evaluator_->Eval(*media);
 
   return false;
 }
@@ -75,7 +75,7 @@
   if (!document_)
     return nullptr;
 
-  MediaQuerySet* media = MediaQuerySet::Create(query);
+  RefPtr<MediaQuerySet> media = MediaQuerySet::Create(query);
   return MediaQueryList::Create(document_, this, media);
 }
 
diff --git a/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp b/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp
index ba01d973..6b2d275 100644
--- a/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQueryMatcherTest.cpp
@@ -17,11 +17,11 @@
       DummyPageHolder::Create(IntSize(500, 500));
   MediaQueryMatcher* matcher =
       MediaQueryMatcher::Create(page_holder->GetDocument());
-  MediaQuerySet* query_set = MediaQuerySet::Create(MediaTypeNames::all);
-  ASSERT_TRUE(matcher->Evaluate(query_set));
+  RefPtr<MediaQuerySet> query_set = MediaQuerySet::Create(MediaTypeNames::all);
+  ASSERT_TRUE(matcher->Evaluate(query_set.Get()));
 
   matcher->DocumentDetached();
-  ASSERT_FALSE(matcher->Evaluate(query_set));
+  ASSERT_FALSE(matcher->Evaluate(query_set.Get()));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/MediaQuerySetTest.cpp b/third_party/WebKit/Source/core/css/MediaQuerySetTest.cpp
index 458f085f..a390c0a3 100644
--- a/third_party/WebKit/Source/core/css/MediaQuerySetTest.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQuerySetTest.cpp
@@ -182,7 +182,8 @@
   };
 
   for (unsigned i = 0; test_cases[i].input; ++i) {
-    MediaQuerySet* query_set = MediaQuerySet::Create(test_cases[i].input);
+    RefPtr<MediaQuerySet> query_set =
+        MediaQuerySet::Create(test_cases[i].input);
     TestMediaQuery(test_cases[i], *query_set);
   }
 }
diff --git a/third_party/WebKit/Source/core/css/RuleFeature.cpp b/third_party/WebKit/Source/core/css/RuleFeature.cpp
index 56a734e..d511aa5c 100644
--- a/third_party/WebKit/Source/core/css/RuleFeature.cpp
+++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp
@@ -1217,8 +1217,6 @@
 DEFINE_TRACE(RuleFeatureSet) {
   visitor->Trace(sibling_rules_);
   visitor->Trace(uncommon_attribute_rules_);
-  visitor->Trace(viewport_dependent_media_query_results_);
-  visitor->Trace(device_dependent_media_query_results_);
 }
 
 void RuleFeatureSet::InvalidationSetFeatures::Add(
diff --git a/third_party/WebKit/Source/core/css/RuleSet.cpp b/third_party/WebKit/Source/core/css/RuleSet.cpp
index c69cbae..e19d5d2 100644
--- a/third_party/WebKit/Source/core/css/RuleSet.cpp
+++ b/third_party/WebKit/Source/core/css/RuleSet.cpp
@@ -305,7 +305,7 @@
     } else if (rule->IsMediaRule()) {
       StyleRuleMedia* media_rule = ToStyleRuleMedia(rule);
       if (!media_rule->MediaQueries() ||
-          medium.Eval(media_rule->MediaQueries(),
+          medium.Eval(*media_rule->MediaQueries(),
                       &features_.ViewportDependentMediaQueryResults(),
                       &features_.DeviceDependentMediaQueryResults()))
         AddChildRules(media_rule->ChildRules(), medium, add_rule_flags);
@@ -336,7 +336,7 @@
     CHECK_EQ(import_rules.data(), sheet->ImportRules().data());
     if (import_rule->GetStyleSheet() &&
         (!import_rule->MediaQueries() ||
-         medium.Eval(import_rule->MediaQueries(),
+         medium.Eval(*import_rule->MediaQueries(),
                      &features_.ViewportDependentMediaQueryResults(),
                      &features_.DeviceDependentMediaQueryResults())))
       AddRulesFromSheet(import_rule->GetStyleSheet(), medium, add_rule_flags);
diff --git a/third_party/WebKit/Source/core/css/StyleMedia.cpp b/third_party/WebKit/Source/core/css/StyleMedia.cpp
index 1dfa898..c08c9ac16 100644
--- a/third_party/WebKit/Source/core/css/StyleMedia.cpp
+++ b/third_party/WebKit/Source/core/css/StyleMedia.cpp
@@ -53,12 +53,12 @@
   if (!document_element)
     return false;
 
-  MediaQuerySet* media = MediaQuerySet::Create();
+  RefPtr<MediaQuerySet> media = MediaQuerySet::Create();
   if (!media->Set(query))
     return false;
 
   MediaQueryEvaluator screen_eval(GetFrame());
-  return screen_eval.Eval(media);
+  return screen_eval.Eval(*media);
 }
 
 DEFINE_TRACE(StyleMedia) {
diff --git a/third_party/WebKit/Source/core/css/StyleRule.cpp b/third_party/WebKit/Source/core/css/StyleRule.cpp
index 9756aec..5c5bc6d0 100644
--- a/third_party/WebKit/Source/core/css/StyleRule.cpp
+++ b/third_party/WebKit/Source/core/css/StyleRule.cpp
@@ -353,7 +353,7 @@
     : StyleRuleGroup(condition_rule),
       condition_text_(condition_rule.condition_text_) {}
 
-StyleRuleMedia::StyleRuleMedia(MediaQuerySet* media,
+StyleRuleMedia::StyleRuleMedia(RefPtr<MediaQuerySet> media,
                                HeapVector<Member<StyleRuleBase>>& adopt_rules)
     : StyleRuleCondition(kMedia, adopt_rules), media_queries_(media) {}
 
@@ -363,11 +363,6 @@
     media_queries_ = media_rule.media_queries_->Copy();
 }
 
-DEFINE_TRACE_AFTER_DISPATCH(StyleRuleMedia) {
-  visitor->Trace(media_queries_);
-  StyleRuleCondition::TraceAfterDispatch(visitor);
-}
-
 StyleRuleSupports::StyleRuleSupports(
     const String& condition_text,
     bool condition_is_supported,
@@ -375,6 +370,10 @@
     : StyleRuleCondition(kSupports, condition_text, adopt_rules),
       condition_is_supported_(condition_is_supported) {}
 
+DEFINE_TRACE_AFTER_DISPATCH(StyleRuleMedia) {
+  StyleRuleCondition::TraceAfterDispatch(visitor);
+}
+
 StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& supports_rule)
     : StyleRuleCondition(supports_rule),
       condition_is_supported_(supports_rule.condition_is_supported_) {}
diff --git a/third_party/WebKit/Source/core/css/StyleRule.h b/third_party/WebKit/Source/core/css/StyleRule.h
index 2965c92..aa8dcbc 100644
--- a/third_party/WebKit/Source/core/css/StyleRule.h
+++ b/third_party/WebKit/Source/core/css/StyleRule.h
@@ -239,7 +239,7 @@
 class CORE_EXPORT StyleRuleMedia : public StyleRuleCondition {
  public:
   static StyleRuleMedia* Create(
-      MediaQuerySet* media,
+      RefPtr<MediaQuerySet> media,
       HeapVector<Member<StyleRuleBase>>& adopt_rules) {
     return new StyleRuleMedia(media, adopt_rules);
   }
@@ -251,11 +251,11 @@
   DECLARE_TRACE_AFTER_DISPATCH();
 
  private:
-  StyleRuleMedia(MediaQuerySet*,
+  StyleRuleMedia(RefPtr<MediaQuerySet>,
                  HeapVector<Member<StyleRuleBase>>& adopt_rules);
   StyleRuleMedia(const StyleRuleMedia&);
 
-  Member<MediaQuerySet> media_queries_;
+  RefPtr<MediaQuerySet> media_queries_;
 };
 
 class StyleRuleSupports : public StyleRuleCondition {
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp
index 0bb1e09..a236a30 100644
--- a/third_party/WebKit/Source/core/css/StyleRuleImport.cpp
+++ b/third_party/WebKit/Source/core/css/StyleRuleImport.cpp
@@ -32,11 +32,12 @@
 namespace blink {
 
 StyleRuleImport* StyleRuleImport::Create(const String& href,
-                                         MediaQuerySet* media) {
+                                         RefPtr<MediaQuerySet> media) {
   return new StyleRuleImport(href, media);
 }
 
-StyleRuleImport::StyleRuleImport(const String& href, MediaQuerySet* media)
+StyleRuleImport::StyleRuleImport(const String& href,
+                                 RefPtr<MediaQuerySet> media)
     : StyleRuleBase(kImport),
       parent_style_sheet_(nullptr),
       style_sheet_client_(new ImportedStyleSheetClient(this)),
@@ -58,7 +59,6 @@
 DEFINE_TRACE_AFTER_DISPATCH(StyleRuleImport) {
   visitor->Trace(style_sheet_client_);
   visitor->Trace(parent_style_sheet_);
-  visitor->Trace(media_queries_);
   visitor->Trace(style_sheet_);
   visitor->Trace(resource_);
   StyleRuleBase::TraceAfterDispatch(visitor);
diff --git a/third_party/WebKit/Source/core/css/StyleRuleImport.h b/third_party/WebKit/Source/core/css/StyleRuleImport.h
index 0e2242e..0d8134c 100644
--- a/third_party/WebKit/Source/core/css/StyleRuleImport.h
+++ b/third_party/WebKit/Source/core/css/StyleRuleImport.h
@@ -36,7 +36,7 @@
   USING_PRE_FINALIZER(StyleRuleImport, Dispose);
 
  public:
-  static StyleRuleImport* Create(const String& href, MediaQuerySet*);
+  static StyleRuleImport* Create(const String& href, RefPtr<MediaQuerySet>);
 
   ~StyleRuleImport();
 
@@ -96,7 +96,7 @@
                         const String& charset,
                         const CSSStyleSheetResource*);
 
-  StyleRuleImport(const String& href, MediaQuerySet*);
+  StyleRuleImport(const String& href, RefPtr<MediaQuerySet>);
 
   void Dispose();
 
@@ -104,7 +104,7 @@
 
   Member<ImportedStyleSheetClient> style_sheet_client_;
   String str_href_;
-  Member<MediaQuerySet> media_queries_;
+  RefPtr<MediaQuerySet> media_queries_;
   Member<StyleSheetContents> style_sheet_;
   Member<CSSStyleSheetResource> resource_;
   bool loading_;
diff --git a/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp b/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp
index 5883eda..37e023c 100644
--- a/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp
+++ b/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp
@@ -38,7 +38,7 @@
   // FIXME: We should test comma-seperated media conditions
   for (unsigned i = 0; test_cases[i].input; ++i) {
     CSSTokenizer tokenizer(test_cases[i].input);
-    MediaQuerySet* media_condition_query_set =
+    RefPtr<MediaQuerySet> media_condition_query_set =
         MediaQueryParser::ParseMediaCondition(tokenizer.TokenRange());
     ASSERT_EQ(media_condition_query_set->QueryVector().size(), (unsigned)1);
     String query_text = media_condition_query_set->QueryVector()[0]->CssText();
diff --git a/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp b/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp
index 96a40f2..60039b1 100644
--- a/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp
@@ -10,16 +10,17 @@
 
 namespace blink {
 
-MediaQuerySet* MediaQueryParser::ParseMediaQuerySet(
+RefPtr<MediaQuerySet> MediaQueryParser::ParseMediaQuerySet(
     const String& query_string) {
   return ParseMediaQuerySet(CSSTokenizer(query_string).TokenRange());
 }
 
-MediaQuerySet* MediaQueryParser::ParseMediaQuerySet(CSSParserTokenRange range) {
+RefPtr<MediaQuerySet> MediaQueryParser::ParseMediaQuerySet(
+    CSSParserTokenRange range) {
   return MediaQueryParser(kMediaQuerySetParser).ParseImpl(range);
 }
 
-MediaQuerySet* MediaQueryParser::ParseMediaCondition(
+RefPtr<MediaQuerySet> MediaQueryParser::ParseMediaCondition(
     CSSParserTokenRange range) {
   return MediaQueryParser(kMediaConditionParser).ParseImpl(range);
 }
@@ -226,7 +227,7 @@
 }
 
 // The state machine loop
-MediaQuerySet* MediaQueryParser::ParseImpl(CSSParserTokenRange range) {
+RefPtr<MediaQuerySet> MediaQueryParser::ParseImpl(CSSParserTokenRange range) {
   while (!range.AtEnd())
     ProcessToken(range.Consume());
 
@@ -257,20 +258,18 @@
   expressions_.clear();
 }
 
-MediaQuery* MediaQueryData::TakeMediaQuery() {
-  MediaQuery* media_query = MediaQuery::Create(
+std::unique_ptr<MediaQuery> MediaQueryData::TakeMediaQuery() {
+  std::unique_ptr<MediaQuery> media_query = MediaQuery::Create(
       restrictor_, std::move(media_type_), std::move(expressions_));
   Clear();
   return media_query;
 }
 
 bool MediaQueryData::AddExpression() {
-  MediaQueryExp* expression =
-      MediaQueryExp::CreateIfValid(media_feature_, value_list_);
-  bool is_valid = !!expression;
+  MediaQueryExp expression = MediaQueryExp::Create(media_feature_, value_list_);
   expressions_.push_back(expression);
   value_list_.clear();
-  return is_valid;
+  return expression.IsValid();
 }
 
 bool MediaQueryData::TryAddParserToken(CSSParserTokenType type,
diff --git a/third_party/WebKit/Source/core/css/parser/MediaQueryParser.h b/third_party/WebKit/Source/core/css/parser/MediaQueryParser.h
index 35ba945..69000eb 100644
--- a/third_party/WebKit/Source/core/css/parser/MediaQueryParser.h
+++ b/third_party/WebKit/Source/core/css/parser/MediaQueryParser.h
@@ -36,7 +36,7 @@
   bool AddExpression();
   bool TryAddParserToken(CSSParserTokenType, const CSSParserToken&);
   void SetMediaType(const String&);
-  MediaQuery* TakeMediaQuery();
+  std::unique_ptr<MediaQuery> TakeMediaQuery();
 
   inline bool CurrentMediaQueryChanged() const {
     return (restrictor_ != MediaQuery::kNone || media_type_set_ ||
@@ -56,9 +56,9 @@
   WTF_MAKE_NONCOPYABLE(MediaQueryParser);
 
  public:
-  static MediaQuerySet* ParseMediaQuerySet(const String&);
-  static MediaQuerySet* ParseMediaQuerySet(CSSParserTokenRange);
-  static MediaQuerySet* ParseMediaCondition(CSSParserTokenRange);
+  static RefPtr<MediaQuerySet> ParseMediaQuerySet(const String&);
+  static RefPtr<MediaQuerySet> ParseMediaQuerySet(CSSParserTokenRange);
+  static RefPtr<MediaQuerySet> ParseMediaCondition(CSSParserTokenRange);
 
  private:
   enum ParserType {
@@ -69,7 +69,7 @@
   MediaQueryParser(ParserType);
   virtual ~MediaQueryParser();
 
-  MediaQuerySet* ParseImpl(CSSParserTokenRange);
+  RefPtr<MediaQuerySet> ParseImpl(CSSParserTokenRange);
 
   void ProcessToken(const CSSParserToken&);
 
@@ -95,7 +95,7 @@
   State state_;
   ParserType parser_type_;
   MediaQueryData media_query_data_;
-  Member<MediaQuerySet> query_set_;
+  RefPtr<MediaQuerySet> query_set_;
   MediaQueryBlockWatcher block_watcher_;
 
   const static State kReadRestrictor;
diff --git a/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp b/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp
index 5f7d95f..adba378 100644
--- a/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp
@@ -53,7 +53,7 @@
 }
 
 bool SizesAttributeParser::MediaConditionMatches(
-    MediaQuerySet* media_condition) {
+    const MediaQuerySet& media_condition) {
   // A Media Condition cannot have a media type other then screen.
   MediaQueryEvaluator media_query_evaluator(*media_values_);
   return media_query_evaluator.Eval(media_condition);
@@ -80,9 +80,10 @@
     if (!CalculateLengthInPixels(
             range.MakeSubRange(length_token_start, length_token_end), length))
       continue;
-    MediaQuerySet* media_condition = MediaQueryParser::ParseMediaCondition(
-        range.MakeSubRange(media_condition_start, length_token_start));
-    if (!media_condition || !MediaConditionMatches(media_condition))
+    RefPtr<MediaQuerySet> media_condition =
+        MediaQueryParser::ParseMediaCondition(
+            range.MakeSubRange(media_condition_start, length_token_start));
+    if (!media_condition || !MediaConditionMatches(*media_condition))
       continue;
     length_ = length;
     length_was_set_ = true;
diff --git a/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.h b/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.h
index 0407b10..d5fa6b17 100644
--- a/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.h
+++ b/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.h
@@ -26,10 +26,10 @@
   bool Parse(CSSParserTokenRange);
   float EffectiveSize();
   bool CalculateLengthInPixels(CSSParserTokenRange, float& result);
-  bool MediaConditionMatches(MediaQuerySet* media_condition);
+  bool MediaConditionMatches(const MediaQuerySet& media_condition);
   float EffectiveSizeDefaultValue();
 
-  Member<MediaQuerySet> media_condition_;
+  RefPtr<MediaQuerySet> media_condition_;
   Member<MediaValues> media_values_;
   float length_;
   bool length_was_set_;
diff --git a/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h b/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h
index 89443ed..9f79077 100644
--- a/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h
+++ b/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h
@@ -29,21 +29,19 @@
 
 namespace blink {
 
-class MediaQueryResult : public GarbageCollected<MediaQueryResult> {
-  WTF_MAKE_NONCOPYABLE(MediaQueryResult);
+class MediaQueryResult {
+  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
 
  public:
   MediaQueryResult(const MediaQueryExp& expr, bool result)
-      : expression_(&expr), result_(result) {}
+      : expression_(expr), result_(result) {}
 
-  DEFINE_INLINE_TRACE() { visitor->Trace(expression_); }
-
-  const MediaQueryExp* Expression() const { return expression_; }
+  const MediaQueryExp& Expression() const { return expression_; }
 
   bool Result() const { return result_; }
 
  private:
-  Member<const MediaQueryExp> expression_;
+  const MediaQueryExp expression_;
   bool result_;
 };
 
diff --git a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp
index 45b17a2..61b2720 100644
--- a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp
@@ -257,8 +257,6 @@
 DEFINE_TRACE(ScopedStyleResolver) {
   visitor->Trace(scope_);
   visitor->Trace(author_style_sheets_);
-  visitor->Trace(viewport_dependent_media_query_results_);
-  visitor->Trace(device_dependent_media_query_results_);
   visitor->Trace(keyframes_rule_map_);
   visitor->Trace(tree_boundary_crossing_rule_set_);
 }
diff --git a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h
index 675babd..6a57b4f 100644
--- a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h
+++ b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h
@@ -43,7 +43,8 @@
 
 // This class selects a ComputedStyle for a given element based on a collection
 // of stylesheets.
-class ScopedStyleResolver final : public GarbageCollected<ScopedStyleResolver> {
+class ScopedStyleResolver final
+    : public GarbageCollectedFinalized<ScopedStyleResolver> {
   WTF_MAKE_NONCOPYABLE(ScopedStyleResolver);
 
  public:
diff --git a/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp
index c3614055b..1d81d4c7 100644
--- a/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp
@@ -106,7 +106,7 @@
       StyleRuleMedia* media_rule = ToStyleRuleMedia(rule);
       if (!media_rule->MediaQueries() ||
           initial_viewport_medium_->Eval(
-              media_rule->MediaQueries(),
+              *media_rule->MediaQueries(),
               &viewport_dependent_media_query_results_,
               &device_dependent_media_query_results_))
         CollectViewportChildRules(media_rule->ChildRules(), origin);
@@ -126,7 +126,7 @@
     if (!import_rule->GetStyleSheet()->HasViewportRule())
       continue;
     if (import_rule->MediaQueries() &&
-        initial_viewport_medium_->Eval(import_rule->MediaQueries(),
+        initial_viewport_medium_->Eval(*import_rule->MediaQueries(),
                                        &viewport_dependent_media_query_results_,
                                        &device_dependent_media_query_results_))
       CollectViewportRulesFromAuthorSheetContents(
@@ -148,7 +148,7 @@
   if (!contents.HasViewportRule() && contents.ImportRules().IsEmpty())
     return;
   if (sheet.MediaQueries() &&
-      !initial_viewport_medium_->Eval(sheet.MediaQueries(),
+      !initial_viewport_medium_->Eval(*sheet.MediaQueries(),
                                       &viewport_dependent_media_query_results_,
                                       &device_dependent_media_query_results_))
     return;
@@ -309,8 +309,8 @@
 
   auto& results = viewport_dependent_media_query_results_;
   for (unsigned i = 0; i < results.size(); i++) {
-    if (initial_viewport_medium_->Eval(results[i]->Expression()) !=
-        results[i]->Result()) {
+    if (initial_viewport_medium_->Eval(results[i].Expression()) !=
+        results[i].Result()) {
       needs_update_ = kCollectRules;
       break;
     }
@@ -343,8 +343,6 @@
   visitor->Trace(document_);
   visitor->Trace(property_set_);
   visitor->Trace(initial_viewport_medium_);
-  visitor->Trace(viewport_dependent_media_query_results_);
-  visitor->Trace(device_dependent_media_query_results_);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h b/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h
index 136587a..aa224c6 100644
--- a/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h
+++ b/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h
@@ -43,7 +43,7 @@
 class StyleRuleViewport;
 
 class CORE_EXPORT ViewportStyleResolver
-    : public GarbageCollected<ViewportStyleResolver> {
+    : public GarbageCollectedFinalized<ViewportStyleResolver> {
  public:
   static ViewportStyleResolver* Create(Document& document) {
     return new ViewportStyleResolver(document);
diff --git a/third_party/WebKit/Source/core/dom/StyleElement.cpp b/third_party/WebKit/Source/core/dom/StyleElement.cpp
index 71e83c7f..78a431c 100644
--- a/third_party/WebKit/Source/core/dom/StyleElement.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleElement.cpp
@@ -152,11 +152,11 @@
   // If type is empty or CSS, this is a CSS style sheet.
   const AtomicString& type = this->type();
   if (IsCSS(element, type) && passes_content_security_policy_checks) {
-    MediaQuerySet* media_queries = MediaQuerySet::Create(media());
+    RefPtr<MediaQuerySet> media_queries = MediaQuerySet::Create(media());
 
     MediaQueryEvaluator screen_eval("screen");
     MediaQueryEvaluator print_eval("print");
-    if (screen_eval.Eval(media_queries) || print_eval.Eval(media_queries)) {
+    if (screen_eval.Eval(*media_queries) || print_eval.Eval(*media_queries)) {
       loading_ = true;
       TextPosition start_position =
           start_position_ == TextPosition::BelowRangePosition()
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
index d758f34fb..0634c6e 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -1136,7 +1136,7 @@
   const auto& results =
       global_rule_set_.GetRuleFeatureSet().ViewportDependentMediaQueryResults();
   for (unsigned i = 0; i < results.size(); ++i) {
-    if (evaluator.Eval(results[i]->Expression()) != results[i]->Result())
+    if (evaluator.Eval(results[i].Expression()) != results[i].Result())
       return true;
   }
   return false;
@@ -1147,7 +1147,7 @@
   const auto& results =
       global_rule_set_.GetRuleFeatureSet().DeviceDependentMediaQueryResults();
   for (unsigned i = 0; i < results.size(); ++i) {
-    if (evaluator.Eval(results[i]->Expression()) != results[i]->Result())
+    if (evaluator.Eval(results[i].Expression()) != results[i].Result())
       return true;
   }
   return false;
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
index 64c5d4e..b3ce2ee 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -34,6 +34,7 @@
 DOMWindow::DOMWindow(Frame& frame)
     : frame_(frame),
       window_proxy_manager_(frame.GetWindowProxyManager()),
+      location_(this, nullptr),
       window_is_closing_(false) {}
 
 DOMWindow::~DOMWindow() {
@@ -465,4 +466,9 @@
   EventTargetWithInlineData::Trace(visitor);
 }
 
+DEFINE_TRACE_WRAPPERS(DOMWindow) {
+  visitor->TraceWrappers(location_);
+  EventTargetWithInlineData::TraceWrappers(visitor);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.h b/third_party/WebKit/Source/core/frame/DOMWindow.h
index 54bda63..be224d4 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.h
@@ -5,6 +5,7 @@
 #ifndef DOMWindow_h
 #define DOMWindow_h
 
+#include "bindings/core/v8/TraceWrapperMember.h"
 #include "bindings/core/v8/Transferables.h"
 #include "core/CoreExport.h"
 #include "core/events/EventTarget.h"
@@ -51,6 +52,8 @@
   // GarbageCollectedFinalized overrides:
   DECLARE_VIRTUAL_TRACE();
 
+  DECLARE_VIRTUAL_TRACE_WRAPPERS();
+
   virtual bool IsLocalDOMWindow() const = 0;
   virtual bool IsRemoteDOMWindow() const = 0;
 
@@ -127,7 +130,7 @@
   // of this object.
   const Member<WindowProxyManager> window_proxy_manager_;
   Member<InputDeviceCapabilitiesConstants> input_capabilities_;
-  mutable Member<Location> location_;
+  mutable TraceWrapperMember<Location> location_;
 
   // Set to true when close() has been called. Needed for
   // |window.closed| determinism; having it return 'true'
diff --git a/third_party/WebKit/Source/core/frame/Location.h b/third_party/WebKit/Source/core/frame/Location.h
index d5d506f..f7c32d4 100644
--- a/third_party/WebKit/Source/core/frame/Location.h
+++ b/third_party/WebKit/Source/core/frame/Location.h
@@ -39,9 +39,9 @@
 namespace blink {
 
 class Document;
-class LocalDOMWindow;
 class ExceptionState;
 class KURL;
+class LocalDOMWindow;
 
 // This class corresponds to the Location interface. Location is the only
 // interface besides Window that is accessible cross-origin and must handle
diff --git a/third_party/WebKit/Source/core/frame/Location.idl b/third_party/WebKit/Source/core/frame/Location.idl
index 6f62693..ba72bee 100644
--- a/third_party/WebKit/Source/core/frame/Location.idl
+++ b/third_party/WebKit/Source/core/frame/Location.idl
@@ -30,6 +30,7 @@
 
 [
     CheckSecurity=Receiver,
+    DependentLifetime,
     Unforgeable,
 ] interface Location {
     // |assign| is *NOT* cross-origin accessible in the spec, but it needs
diff --git a/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp b/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
index 5e4c556..8ef2bc6 100644
--- a/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSourceElement.cpp
@@ -75,7 +75,7 @@
     return;
   }
 
-  MediaQuerySet* set = MediaQuerySet::Create(media);
+  RefPtr<MediaQuerySet> set = MediaQuerySet::Create(media);
   media_query_list_ = MediaQueryList::Create(
       &GetDocument(), &GetDocument().GetMediaQueryMatcher(), set);
   AddMediaQueryListListener();
diff --git a/third_party/WebKit/Source/core/html/LinkStyle.cpp b/third_party/WebKit/Source/core/html/LinkStyle.cpp
index 1e70376..37ae854 100644
--- a/third_party/WebKit/Source/core/html/LinkStyle.cpp
+++ b/third_party/WebKit/Source/core/html/LinkStyle.cpp
@@ -305,9 +305,9 @@
   bool media_query_matches = true;
   LocalFrame* frame = LoadingFrame();
   if (!owner_->Media().IsEmpty() && frame) {
-    MediaQuerySet* media = MediaQuerySet::Create(owner_->Media());
+    RefPtr<MediaQuerySet> media = MediaQuerySet::Create(owner_->Media());
     MediaQueryEvaluator evaluator(frame);
-    media_query_matches = evaluator.Eval(media);
+    media_query_matches = evaluator.Eval(*media);
   }
 
   // Don't hold up layout tree construction and script execution on
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
index 00ead606..eb8af21c 100644
--- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
@@ -100,8 +100,7 @@
     const MediaValuesCached::MediaValuesCachedData& media_values_cached_data) {
   preload_scanner_.reset(new TokenPreloadScanner(
       document_url, std::move(cached_document_parameters),
-      media_values_cached_data,
-      TokenPreloadScanner::ScannerType::kMainDocument));
+      media_values_cached_data));
 }
 
 BackgroundHTMLParser::Configuration::Configuration()
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
index 379bf39..6ad3557 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -722,8 +722,7 @@
     // crbug.com/465478
     if (preloader_) {
       if (!preload_scanner_) {
-        preload_scanner_ = CreatePreloadScanner(
-            TokenPreloadScanner::ScannerType::kMainDocument);
+        preload_scanner_ = CreatePreloadScanner();
         preload_scanner_->AppendToEnd(input_.Current());
       }
       ScanAndPreload(preload_scanner_.get());
@@ -798,10 +797,8 @@
   if (IsPaused()) {
     // Check the document.write() output with a separate preload scanner as
     // the main scanner can't deal with insertions.
-    if (!insertion_preload_scanner_) {
-      insertion_preload_scanner_ =
-          CreatePreloadScanner(TokenPreloadScanner::ScannerType::kInsertion);
-    }
+    if (!insertion_preload_scanner_)
+      insertion_preload_scanner_ = CreatePreloadScanner();
     insertion_preload_scanner_->AppendToEnd(source);
     ScanAndPreload(insertion_preload_scanner_.get());
   }
@@ -902,10 +899,8 @@
     if (GetDocument()->Loader()->GetResponse().AppCacheID() != 0)
       return;
 
-    if (!preload_scanner_) {
-      preload_scanner_ =
-          CreatePreloadScanner(TokenPreloadScanner::ScannerType::kMainDocument);
-    }
+    if (!preload_scanner_)
+      preload_scanner_ = CreatePreloadScanner();
 
     preload_scanner_->AppendToEnd(source);
     ScanAndPreload(preload_scanner_.get());
@@ -1261,12 +1256,11 @@
   FetchQueuedPreloads();
 }
 
-std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::CreatePreloadScanner(
-    TokenPreloadScanner::ScannerType scanner_type) {
+std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::CreatePreloadScanner() {
   return HTMLPreloadScanner::Create(
       options_, GetDocument()->Url(),
       CachedDocumentParameters::Create(GetDocument()),
-      MediaValuesCached::MediaValuesCachedData(*GetDocument()), scanner_type);
+      MediaValuesCached::MediaValuesCachedData(*GetDocument()));
 }
 
 void HTMLDocumentParser::ScanAndPreload(HTMLPreloadScanner* scanner) {
@@ -1312,8 +1306,7 @@
   int current_preload_count =
       GetDocument()->Loader()->Fetcher()->CountPreloads();
 
-  std::unique_ptr<HTMLPreloadScanner> scanner =
-      CreatePreloadScanner(TokenPreloadScanner::ScannerType::kInsertion);
+  std::unique_ptr<HTMLPreloadScanner> scanner = CreatePreloadScanner();
   scanner->AppendToEnd(SegmentedString(written_source));
   ScanAndPreload(scanner.get());
 
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
index 11ed0f8..28ef5ee 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
@@ -223,8 +223,7 @@
            IsExecutingScript();
   }
 
-  std::unique_ptr<HTMLPreloadScanner> CreatePreloadScanner(
-      TokenPreloadScanner::ScannerType);
+  std::unique_ptr<HTMLPreloadScanner> CreatePreloadScanner();
 
   // Let the given HTMLPreloadScanner scan the input it has, and then preloads
   // resources using the resulting PreloadRequests and |m_preloader|.
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
index 8b065f6a..101d5c9 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
@@ -127,18 +127,16 @@
 
 static bool MediaAttributeMatches(const MediaValuesCached& media_values,
                                   const String& attribute_value) {
-  MediaQuerySet* media_queries = MediaQuerySet::Create(attribute_value);
+  RefPtr<MediaQuerySet> media_queries = MediaQuerySet::Create(attribute_value);
   MediaQueryEvaluator media_query_evaluator(media_values);
-  return media_query_evaluator.Eval(media_queries);
+  return media_query_evaluator.Eval(*media_queries);
 }
 
 class TokenPreloadScanner::StartTagScanner {
   STACK_ALLOCATED();
 
  public:
-  StartTagScanner(const StringImpl* tag_impl,
-                  MediaValuesCached* media_values,
-                  TokenPreloadScanner::ScannerType scanner_type)
+  StartTagScanner(const StringImpl* tag_impl, MediaValuesCached* media_values)
       : tag_impl_(tag_impl),
         link_is_style_sheet_(false),
         link_is_preconnect_(false),
@@ -153,8 +151,7 @@
         cross_origin_(kCrossOriginAttributeNotSet),
         media_values_(media_values),
         referrer_policy_set_(false),
-        referrer_policy_(kReferrerPolicyDefault),
-        scanner_type_(scanner_type) {
+        referrer_policy_(kReferrerPolicyDefault) {
     if (Match(tag_impl_, imgTag) || Match(tag_impl_, sourceTag)) {
       source_size_ = SizesAttributeParser(media_values_, String()).length();
       return;
@@ -261,8 +258,6 @@
     request->SetCharset(Charset());
     request->SetDefer(defer_);
     request->SetIntegrityMetadata(integrity_metadata_);
-    if (scanner_type_ == ScannerType::kInsertion)
-      request->SetFromInsertionScanner(true);
 
     return request;
   }
@@ -579,14 +574,12 @@
   bool referrer_policy_set_;
   ReferrerPolicy referrer_policy_;
   IntegrityMetadataSet integrity_metadata_;
-  TokenPreloadScanner::ScannerType scanner_type_;
 };
 
 TokenPreloadScanner::TokenPreloadScanner(
     const KURL& document_url,
     std::unique_ptr<CachedDocumentParameters> document_parameters,
-    const MediaValuesCached::MediaValuesCachedData& media_values_cached_data,
-    const ScannerType scanner_type)
+    const MediaValuesCached::MediaValuesCachedData& media_values_cached_data)
     : document_url_(document_url),
       in_style_(false),
       in_picture_(false),
@@ -594,7 +587,6 @@
       template_count_(0),
       document_parameters_(std::move(document_parameters)),
       media_values_(MediaValuesCached::Create(media_values_cached_data)),
-      scanner_type_(scanner_type),
       did_rewind_(false) {
   DCHECK(document_parameters_.get());
   DCHECK(media_values_.Get());
@@ -862,7 +854,7 @@
         return;
       }
 
-      StartTagScanner scanner(tag_impl, media_values_, scanner_type_);
+      StartTagScanner scanner(tag_impl, media_values_);
       scanner.ProcessAttributes(token.Attributes());
       // TODO(yoav): ViewportWidth is currently racy and might be zero in some
       // cases, at least in tests. That problem will go away once
@@ -896,12 +888,10 @@
     const HTMLParserOptions& options,
     const KURL& document_url,
     std::unique_ptr<CachedDocumentParameters> document_parameters,
-    const MediaValuesCached::MediaValuesCachedData& media_values_cached_data,
-    const TokenPreloadScanner::ScannerType scanner_type)
+    const MediaValuesCached::MediaValuesCachedData& media_values_cached_data)
     : scanner_(document_url,
                std::move(document_parameters),
-               media_values_cached_data,
-               scanner_type),
+               media_values_cached_data),
       tokenizer_(HTMLTokenizer::Create(options)) {}
 
 HTMLPreloadScanner::~HTMLPreloadScanner() {}
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h
index 9971f77b..d5936af 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h
@@ -82,12 +82,9 @@
   USING_FAST_MALLOC(TokenPreloadScanner);
 
  public:
-  enum class ScannerType { kMainDocument, kInsertion };
-
   TokenPreloadScanner(const KURL& document_url,
                       std::unique_ptr<CachedDocumentParameters>,
-                      const MediaValuesCached::MediaValuesCachedData&,
-                      const ScannerType);
+                      const MediaValuesCached::MediaValuesCachedData&);
   ~TokenPreloadScanner();
 
   void Scan(const HTMLToken&,
@@ -165,7 +162,6 @@
   std::unique_ptr<CachedDocumentParameters> document_parameters_;
   Persistent<MediaValuesCached> media_values_;
   ClientHintsPreferences client_hints_preferences_;
-  ScannerType scanner_type_;
 
   bool did_rewind_ = false;
 
@@ -181,11 +177,11 @@
       const HTMLParserOptions& options,
       const KURL& document_url,
       std::unique_ptr<CachedDocumentParameters> document_parameters,
-      const MediaValuesCached::MediaValuesCachedData& media_values_cached_data,
-      const TokenPreloadScanner::ScannerType scanner_type) {
+      const MediaValuesCached::MediaValuesCachedData&
+          media_values_cached_data) {
     return WTF::WrapUnique(new HTMLPreloadScanner(
         options, document_url, std::move(document_parameters),
-        media_values_cached_data, scanner_type));
+        media_values_cached_data));
   }
 
   ~HTMLPreloadScanner();
@@ -198,8 +194,7 @@
   HTMLPreloadScanner(const HTMLParserOptions&,
                      const KURL& document_url,
                      std::unique_ptr<CachedDocumentParameters>,
-                     const MediaValuesCached::MediaValuesCachedData&,
-                     const TokenPreloadScanner::ScannerType);
+                     const MediaValuesCached::MediaValuesCachedData&);
 
   TokenPreloadScanner scanner_;
   SegmentedString source_;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp
index 60e5765..794dcd55 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp
@@ -64,8 +64,7 @@
   MockResourcePreloader preloader;
 
   std::unique_ptr<HTMLPreloadScanner> scanner = HTMLPreloadScanner::Create(
-      options, document_url, std::move(document_parameters), media_data,
-      TokenPreloadScanner::ScannerType::kMainDocument);
+      options, document_url, std::move(document_parameters), media_data);
 
   TextResourceDecoderForFuzzing decoder(fuzzed_data);
   CString bytes = fuzzed_data.ConsumeRemainingBytes();
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
index 3e746aad..ca30bb2 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
@@ -189,8 +189,7 @@
     scanner_ = HTMLPreloadScanner::Create(
         options, document_url,
         CachedDocumentParameters::Create(&dummy_page_holder_->GetDocument()),
-        CreateMediaValuesData(),
-        TokenPreloadScanner::ScannerType::kMainDocument);
+        CreateMediaValuesData());
   }
 
   void SetUp() override { RunSetUp(kViewportEnabled); }
diff --git a/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp b/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp
index 939bbc1..0d559a74 100644
--- a/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp
+++ b/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp
@@ -81,13 +81,7 @@
     params.SetCharset(charset_.IsEmpty() ? document->characterSet().GetString()
                                          : charset_);
   }
-  FetchParameters::SpeculativePreloadType speculative_preload_type =
-      FetchParameters::SpeculativePreloadType::kInDocument;
-  if (from_insertion_scanner_) {
-    speculative_preload_type =
-        FetchParameters::SpeculativePreloadType::kInserted;
-  }
-  params.SetSpeculativePreloadType(speculative_preload_type, discovery_time_);
+  params.SetSpeculativePreload(true, discovery_time_);
 
   return document->Loader()->StartPreload(resource_type_, params);
 }
diff --git a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
index cecfccbf..5ce1490 100644
--- a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
+++ b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
@@ -98,9 +98,6 @@
   const IntegrityMetadataSet& IntegrityMetadata() const {
     return integrity_metadata_;
   }
-  void SetFromInsertionScanner(const bool from_insertion_scanner) {
-    from_insertion_scanner_ = from_insertion_scanner;
-  }
 
  private:
   PreloadRequest(const String& initiator_name,
@@ -125,8 +122,7 @@
         client_hints_preferences_(client_hints_preferences),
         request_type_(request_type),
         referrer_policy_(referrer_policy),
-        referrer_source_(referrer_source),
-        from_insertion_scanner_(false) {}
+        referrer_source_(referrer_source) {}
 
   KURL CompleteURL(Document*);
 
@@ -146,7 +142,6 @@
   ReferrerPolicy referrer_policy_;
   ReferrerSource referrer_source_;
   IntegrityMetadataSet integrity_metadata_;
-  bool from_insertion_scanner_;
 };
 
 typedef Vector<std::unique_ptr<PreloadRequest>> PreloadRequestStream;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index 78b1fa9..e580572 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -1612,7 +1612,8 @@
   }
 
   const MediaQuerySet* queries = media->Queries();
-  const HeapVector<Member<MediaQuery>>& query_vector = queries->QueryVector();
+  const Vector<std::unique_ptr<MediaQuery>>& query_vector =
+      queries->QueryVector();
   LocalFrame* frame = nullptr;
   if (parent_style_sheet) {
     if (Document* document = parent_style_sheet->OwnerDocument())
@@ -1629,15 +1630,15 @@
   MediaValues* media_values = MediaValues::CreateDynamicIfFrameExists(frame);
   bool has_media_query_items = false;
   for (size_t i = 0; i < query_vector.size(); ++i) {
-    MediaQuery* query = query_vector.at(i).Get();
-    const ExpressionHeapVector& expressions = query->Expressions();
+    MediaQuery& query = *query_vector.at(i);
+    const ExpressionHeapVector& expressions = query.Expressions();
     std::unique_ptr<protocol::Array<protocol::CSS::MediaQueryExpression>>
         expression_array =
             protocol::Array<protocol::CSS::MediaQueryExpression>::create();
     bool has_expression_items = false;
     for (size_t j = 0; j < expressions.size(); ++j) {
-      MediaQueryExp* media_query_exp = expressions.at(j).Get();
-      MediaQueryExpValue exp_value = media_query_exp->ExpValue();
+      const MediaQueryExp& media_query_exp = expressions.at(j);
+      MediaQueryExpValue exp_value = media_query_exp.ExpValue();
       if (!exp_value.is_value)
         continue;
       const char* value_name =
@@ -1647,7 +1648,7 @@
               protocol::CSS::MediaQueryExpression::create()
                   .setValue(exp_value.value)
                   .setUnit(String(value_name))
-                  .setFeature(media_query_exp->MediaFeature())
+                  .setFeature(media_query_exp.MediaFeature())
                   .build();
 
       if (inspector_style_sheet && media->ParentRule())
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.cpp b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
index d93287e..867e8fa 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
@@ -301,9 +301,9 @@
     }
 
     // Preload only if media matches
-    MediaQuerySet* media_queries = MediaQuerySet::Create(media);
+    RefPtr<MediaQuerySet> media_queries = MediaQuerySet::Create(media);
     MediaQueryEvaluator evaluator(*media_values);
-    if (!evaluator.Eval(media_queries))
+    if (!evaluator.Eval(*media_queries))
       return nullptr;
   }
   if (caller == kLinkCalledFromHeader)
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index c72135b..a57d2f7c 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(SkShader::MakePictureShader(
+  flags.setShader(MakePaintShaderRecord(
       PaintRecordForCurrentFrame(float_bounds, url), SkShader::kRepeat_TileMode,
       SkShader::kRepeat_TileMode, &local_matrix, &bounds));
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
index 6c2834d..e535711 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
@@ -381,7 +381,6 @@
   options.blob_info = &blob_info;
   options.write_wasm_to_stream =
       ExecutionContext::From(script_state)->IsSecureContext();
-  options.for_storage = true;
   RefPtr<SerializedScriptValue> serialized_value =
       SerializedScriptValue::Serialize(isolate, value.V8Value(), options,
                                        exception_state);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
index d588778..f0a5e2f0 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
@@ -90,7 +90,7 @@
   ++g_hardware_context_count;
 #if DEBUG_AUDIONODE_REFERENCES
   fprintf(stderr, "[%16p]: AudioContext::AudioContext(): %u #%u\n",
-          audioContext, audioContext->m_contextId, s_hardwareContextCount);
+          audio_context, audio_context->context_id_, g_hardware_context_count);
 #endif
 
   DEFINE_STATIC_LOCAL(SparseHistogram, max_channel_count_histogram,
@@ -114,7 +114,7 @@
 AudioContext::~AudioContext() {
 #if DEBUG_AUDIONODE_REFERENCES
   fprintf(stderr, "[%16p]: AudioContext::~AudioContext(): %u\n", this,
-          m_contextId);
+          context_id_);
 #endif
 }
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
index 3ecee4d..fe8ceac4 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
@@ -58,9 +58,9 @@
   SetInternalChannelInterpretation(AudioBus::kSpeakers);
 
 #if DEBUG_AUDIONODE_REFERENCES
-  if (!s_isNodeCountInitialized) {
-    s_isNodeCountInitialized = true;
-    atexit(AudioHandler::printNodeCounts);
+  if (!is_node_count_initialized_) {
+    is_node_count_initialized_ = true;
+    atexit(AudioHandler::PrintNodeCounts);
   }
 #endif
   InstanceCounters::IncrementCounter(InstanceCounters::kAudioHandlerCounter);
@@ -72,10 +72,10 @@
   DCHECK(!GetNode());
   InstanceCounters::DecrementCounter(InstanceCounters::kAudioHandlerCounter);
 #if DEBUG_AUDIONODE_REFERENCES
-  --s_nodeCount[getNodeType()];
+  --node_count_[GetNodeType()];
   fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::~AudioHandler() %d [%d]\n",
-          context(), this, getNodeType(), m_connectionRefCount,
-          s_nodeCount[getNodeType()]);
+          Context(), this, GetNodeType(), connection_ref_count_,
+          node_count_[GetNodeType()]);
 #endif
 }
 
@@ -169,9 +169,9 @@
   node_type_ = type;
 
 #if DEBUG_AUDIONODE_REFERENCES
-  ++s_nodeCount[type];
+  ++node_count_[type];
   fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::AudioHandler [%3d]\n",
-          context(), this, getNodeType(), s_nodeCount[getNodeType()]);
+          Context(), this, GetNodeType(), node_count_[GetNodeType()]);
 #endif
 }
 
@@ -454,8 +454,8 @@
 
 #if DEBUG_AUDIONODE_REFERENCES
   fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::ref   %3d [%3d]\n",
-          context(), this, getNodeType(), m_connectionRefCount,
-          s_nodeCount[getNodeType()]);
+          Context(), this, GetNodeType(), connection_ref_count_,
+          node_count_[GetNodeType()]);
 #endif
   // See the disabling code in disableOutputsIfNecessary(). This handles
   // the case where a node is being re-connected after being used at least
@@ -492,8 +492,8 @@
 
 #if DEBUG_AUDIONODE_REFERENCES
   fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::deref %3d [%3d]\n",
-          context(), this, getNodeType(), m_connectionRefCount,
-          s_nodeCount[getNodeType()]);
+          Context(), this, GetNodeType(), connection_ref_count_,
+          node_count_[GetNodeType()]);
 #endif
 
   if (!connection_ref_count_)
@@ -502,17 +502,17 @@
 
 #if DEBUG_AUDIONODE_REFERENCES
 
-bool AudioHandler::s_isNodeCountInitialized = false;
-int AudioHandler::s_nodeCount[NodeTypeEnd];
+bool AudioHandler::is_node_count_initialized_ = false;
+int AudioHandler::node_count_[kNodeTypeEnd];
 
-void AudioHandler::printNodeCounts() {
+void AudioHandler::PrintNodeCounts() {
   fprintf(stderr, "\n\n");
   fprintf(stderr, "===========================\n");
   fprintf(stderr, "AudioNode: reference counts\n");
   fprintf(stderr, "===========================\n");
 
-  for (unsigned i = 0; i < NodeTypeEnd; ++i)
-    fprintf(stderr, "%2d: %d\n", i, s_nodeCount[i]);
+  for (unsigned i = 0; i < kNodeTypeEnd; ++i)
+    fprintf(stderr, "%2d: %d\n", i, node_count_[i]);
 
   fprintf(stderr, "===========================\n\n\n");
 }
@@ -546,7 +546,7 @@
   DCHECK(IsMainThread());
 #if DEBUG_AUDIONODE_REFERENCES
   fprintf(stderr, "[%16p]: %16p: %2d: AudioNode::dispose %16p\n", context(),
-          this, handler().getNodeType(), m_handler.get());
+          this, Handler().GetNodeType(), handler_.Get());
 #endif
   BaseAudioContext::AutoLocker locker(context());
   Handler().Dispose();
@@ -561,7 +561,7 @@
 
 #if DEBUG_AUDIONODE_REFERENCES
   fprintf(stderr, "[%16p]: %16p: %2d: AudioNode::AudioNode %16p\n", context(),
-          this, m_handler->getNodeType(), m_handler.get());
+          this, handler_->GetNodeType(), handler_.Get());
 #endif
 }
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.h b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
index 292b3388..0a81af0 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
@@ -186,7 +186,7 @@
   virtual void CheckNumberOfChannelsForInput(AudioNodeInput*);
 
 #if DEBUG_AUDIONODE_REFERENCES
-  static void printNodeCounts();
+  static void PrintNodeCounts();
 #endif
 
   // tailTime() is the length of time (not counting latency time) where
@@ -281,8 +281,8 @@
   bool is_disabled_;
 
 #if DEBUG_AUDIONODE_REFERENCES
-  static bool s_isNodeCountInitialized;
-  static int s_nodeCount[NodeTypeEnd];
+  static bool is_node_count_initialized_;
+  static int node_count_[kNodeTypeEnd];
 #endif
 
   ChannelCountMode channel_count_mode_;
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
index 5d11344..998596b 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
@@ -104,7 +104,7 @@
 
 #if DEBUG_AUDIONODE_REFERENCES
   fprintf(stderr, "[%16p]: OfflineAudioContext::OfflineAudioContext()\n",
-          audioContext);
+          audio_context);
 #endif
   DEFINE_STATIC_LOCAL(SparseHistogram, offline_context_channel_count_histogram,
                       ("WebAudio.OfflineAudioContext.ChannelCount"));
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
index 75f9fdd2..a215a535 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPathDisplayItem.cpp
@@ -23,11 +23,12 @@
   list->AppendClipPathItem(clip_path_, true);
 }
 
-void BeginClipPathDisplayItem::AnalyzeForGpuRasterization(
-    SkPictureGpuAnalyzer& analyzer) const {
+int BeginClipPathDisplayItem::NumberOfSlowPaths() 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 42434ae..3952c877 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;
 
-  void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override;
+  int NumberOfSlowPaths() 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 cdcd8fd..7eac3491 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/CompositingRecorder.cpp
@@ -29,58 +29,8 @@
 CompositingRecorder::~CompositingRecorder() {
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
     return;
-  // 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_);
-  }
+  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 a9afcd1..d5f344e6 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -17,8 +17,6 @@
 #include "platform/wtf/text/WTFString.h"
 #endif
 
-class SkPictureGpuAnalyzer;
-
 namespace blink {
 
 class GraphicsContext;
@@ -337,7 +335,7 @@
   virtual bool DrawsContent() const { return false; }
 
   // Override to implement specific analysis strategies.
-  virtual void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const {}
+  virtual int NumberOfSlowPaths() const { return 0; }
 
 #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 8691f50c..694762a 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -7,7 +7,6 @@
 #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 d88ea7c..6a76f3be 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingDisplayItem.cpp
@@ -10,7 +10,6 @@
 #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 {
 
@@ -30,14 +29,8 @@
   return record_.get();
 }
 
-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());
+int DrawingDisplayItem::NumberOfSlowPaths() const {
+  return record_ ? record_->numSlowPaths() : 0;
 }
 
 #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 e5f989f8..3dedbcbd 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_;
   }
 
-  void AnalyzeForGpuRasterization(SkPictureGpuAnalyzer&) const override;
+  int NumberOfSlowPaths() 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 fc8ebc1a..9e74558a 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -16,6 +16,8 @@
 #include <stdio.h>
 #endif
 
+static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5;
+
 namespace blink {
 
 void PaintController::SetTracksRasterInvalidations(bool value) {
@@ -536,7 +538,7 @@
       !new_display_item_list_.IsEmpty())
     GenerateChunkRasterInvalidationRects(new_paint_chunks_.LastChunk());
 
-  SkPictureGpuAnalyzer gpu_analyzer;
+  int num_slow_paths = 0;
 
   current_cache_generation_ =
       DisplayItemClient::CacheGenerationOrInvalidationReason::Next();
@@ -555,8 +557,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 (gpu_analyzer.suitableForGpuRasterization())
-      item.AnalyzeForGpuRasterization(gpu_analyzer);
+    if (num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto)
+      num_slow_paths += item.NumberOfSlowPaths();
 
     // TODO(wkorman): Only compute and append visual rect for drawings.
     new_display_item_list_.AppendVisualRect(
@@ -594,7 +596,7 @@
   new_display_item_list_.ShrinkToFit();
   current_paint_artifact_ = PaintArtifact(
       std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(),
-      gpu_analyzer.suitableForGpuRasterization());
+      num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto);
   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 c497fbade..9904efe 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -2273,40 +2273,6 @@
     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) {
@@ -2356,11 +2322,6 @@
   TestInvalidationInSubsequence();
 }
 
-TEST_F(PaintControllerUnderInvalidationTest,
-       FoldCompositingDrawingInSubsequence) {
-  TestFoldCompositingDrawingInSubsequence();
-}
-
 #endif  // defined(GTEST_HAS_DEATH_TEST) && !OS(ANDROID)
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp
index 95cbd432..8cbba33 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp
@@ -39,7 +39,7 @@
     : resource_request_(resource_request),
       charset_(charset),
       options_(ResourceFetcher::DefaultResourceOptions()),
-      speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
+      speculative_preload_(false),
       preload_discovery_time_(0.0),
       defer_(kNoDefer),
       origin_restriction_(kUseDefaultOriginRestrictionForType),
@@ -52,7 +52,7 @@
                                  const ResourceLoaderOptions& options)
     : resource_request_(resource_request),
       options_(options),
-      speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
+      speculative_preload_(false),
       preload_discovery_time_(0.0),
       defer_(kNoDefer),
       origin_restriction_(kUseDefaultOriginRestrictionForType),
@@ -65,7 +65,7 @@
                                  const FetchInitiatorInfo& initiator)
     : resource_request_(resource_request),
       options_(ResourceFetcher::DefaultResourceOptions()),
-      speculative_preload_type_(SpeculativePreloadType::kNotSpeculative),
+      speculative_preload_(false),
       preload_discovery_time_(0.0),
       defer_(kNoDefer),
       origin_restriction_(kUseDefaultOriginRestrictionForType),
@@ -129,10 +129,9 @@
   }
 }
 
-void FetchParameters::SetSpeculativePreloadType(
-    SpeculativePreloadType speculative_preload_type,
-    double discovery_time) {
-  speculative_preload_type_ = speculative_preload_type;
+void FetchParameters::SetSpeculativePreload(bool speculative_preload,
+                                            double discovery_time) {
+  speculative_preload_ = speculative_preload;
   preload_discovery_time_ = discovery_time;
 }
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.h b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.h
index f5b4842..a736299 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.h
@@ -47,11 +47,6 @@
 
  public:
   enum DeferOption { kNoDefer, kLazyLoad, kIdleLoad };
-  enum class SpeculativePreloadType {
-    kNotSpeculative,
-    kInDocument,  // The request was discovered in the main document
-    kInserted     // The request was discovered in a document.write()
-  };
   enum OriginRestriction {
     kUseDefaultOriginRestrictionForType,
     kRestrictToSameOrigin,
@@ -108,14 +103,9 @@
     return client_hint_preferences_;
   }
 
-  bool IsSpeculativePreload() const {
-    return speculative_preload_type_ != SpeculativePreloadType::kNotSpeculative;
-  }
-  SpeculativePreloadType GetSpeculativePreloadType() const {
-    return speculative_preload_type_;
-  }
-  void SetSpeculativePreloadType(SpeculativePreloadType,
-                                 double discovery_time = 0);
+  bool IsSpeculativePreload() const { return speculative_preload_; }
+  void SetSpeculativePreload(bool speculative_preload,
+                             double discovery_time = 0);
 
   double PreloadDiscoveryTime() { return preload_discovery_time_; }
 
@@ -172,7 +162,7 @@
   ResourceRequest resource_request_;
   String charset_;
   ResourceLoaderOptions options_;
-  SpeculativePreloadType speculative_preload_type_;
+  bool speculative_preload_;
   double preload_discovery_time_;
   DeferOption defer_;
   OriginRestriction origin_restriction_;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index 0554a74b..4f4e498 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -158,7 +158,7 @@
     const ResourceRequest& resource_request,
     ResourcePriority::VisibilityStatus visibility,
     FetchParameters::DeferOption defer_option,
-    FetchParameters::SpeculativePreloadType speculative_preload_type,
+    bool is_speculative_preload,
     bool is_link_preload) {
   ResourceLoadPriority priority = TypeToPriority(type);
 
@@ -189,9 +189,7 @@
     // Preload late in document: Medium
     if (FetchParameters::kLazyLoad == defer_option) {
       priority = kResourceLoadPriorityLow;
-    } else if (speculative_preload_type ==
-                   FetchParameters::SpeculativePreloadType::kInDocument &&
-               image_fetched_) {
+    } else if (is_speculative_preload && image_fetched_) {
       // Speculative preload is used as a signal for scripts at the bottom of
       // the document.
       priority = kResourceLoadPriorityMedium;
@@ -517,7 +515,7 @@
   resource_request.SetPriority(ComputeLoadPriority(
       factory.GetType(), params.GetResourceRequest(),
       ResourcePriority::kNotVisible, params.Defer(),
-      params.GetSpeculativePreloadType(), params.IsLinkPreload()));
+      params.IsSpeculativePreload(), params.IsLinkPreload()));
   InitializeResourceRequest(resource_request, factory.GetType(),
                             params.Defer());
   network_instrumentation::resourcePrioritySet(identifier,
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h
index dafdd00..bd7e918 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h
@@ -168,8 +168,7 @@
       const ResourceRequest&,
       ResourcePriority::VisibilityStatus,
       FetchParameters::DeferOption = FetchParameters::kNoDefer,
-      FetchParameters::SpeculativePreloadType =
-          FetchParameters::SpeculativePreloadType::kNotSpeculative,
+      bool is_speculative_preload = false,
       bool is_link_preload = false);
 
   enum PrepareRequestResult { kAbort, kContinue, kBlock };
diff --git a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
index 6379d6a..e3eada5 100644
--- a/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
+++ b/third_party/WebKit/Source/platform/mac/LocalCurrentGraphicsContext.mm
@@ -24,6 +24,7 @@
 #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/third_party/WebKit/Source/platform/scheduler/base/task_queue.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
index de227cc..43a8bc5 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
-#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
 
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
@@ -233,4 +233,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_time_observer.h b/third_party/WebKit/Source/platform/scheduler/base/task_time_observer.h
index 0257e32..1131f8f 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_time_observer.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_time_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
-#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
 
 #include "base/time/time.h"
 #include "public/platform/WebCommon.h"
@@ -42,4 +42,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
index 65f2f5c7..4e1a370 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_WORKER_SCHEDULER_H_
-#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_WORKER_SCHEDULER_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_WORKER_SCHEDULER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_WORKER_SCHEDULER_H_
 
 #include "base/macros.h"
 #include "platform/scheduler/child/worker_scheduler.h"
@@ -58,4 +58,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_WORKER_SCHEDULER_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_WORKER_SCHEDULER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
index cee9b58..5fe0cb1 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
@@ -52,7 +52,7 @@
             new IdleCanceledDelayedTaskSweeper("test",
                                                scheduler_helper_.get(),
                                                idle_helper_->IdleTaskRunner())),
-        default_task_runner_(scheduler_helper_->DefaultTaskQueue()) {
+        default_task_queue_(scheduler_helper_->DefaultTaskQueue()) {
     clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
   }
 
@@ -84,7 +84,7 @@
   std::unique_ptr<IdleHelper> idle_helper_;
   std::unique_ptr<IdleCanceledDelayedTaskSweeper>
       idle_canceled_delayed_taks_sweeper_;
-  scoped_refptr<TaskQueue> default_task_runner_;
+  scoped_refptr<TaskQueue> default_task_queue_;
 
   DISALLOW_COPY_AND_ASSIGN(IdleCanceledDelayedTaskSweeperTest);
 };
@@ -94,28 +94,28 @@
   TestClass class2;
 
   // Post one task we won't cancel.
-  default_task_runner_->PostDelayedTask(
+  default_task_queue_->PostDelayedTask(
       FROM_HERE,
       base::Bind(&TestClass::NopTask, class1.weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(100));
 
   // And a bunch we will.
-  default_task_runner_->PostDelayedTask(
+  default_task_queue_->PostDelayedTask(
       FROM_HERE,
       base::Bind(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(101));
 
-  default_task_runner_->PostDelayedTask(
+  default_task_queue_->PostDelayedTask(
       FROM_HERE,
       base::Bind(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(102));
 
-  default_task_runner_->PostDelayedTask(
+  default_task_queue_->PostDelayedTask(
       FROM_HERE,
       base::Bind(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(103));
 
-  default_task_runner_->PostDelayedTask(
+  default_task_queue_->PostDelayedTask(
       FROM_HERE,
       base::Bind(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(104));
@@ -130,7 +130,7 @@
   idle_helper_->EnableLongIdlePeriod();
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(40));
 
-  EXPECT_EQ(1u, default_task_runner_->GetNumberOfPendingTasks());
+  EXPECT_EQ(1u, default_task_queue_->GetNumberOfPendingTasks());
 }
 
 }  // namespace scheduler
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
index 346d8c9..64f18e2 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
@@ -37,21 +37,20 @@
                                tracing_category,
                                disabled_by_default_tracing_category,
                                disabled_by_default_verbose_tracing_category)),
-      control_task_runner_(
+      control_task_queue_(
           NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::CONTROL)
                            .SetShouldNotifyObservers(false))),
-      default_task_runner_(NewTaskQueue(default_task_queue_spec)),
+      default_task_queue_(NewTaskQueue(default_task_queue_spec)),
       observer_(nullptr),
       tracing_category_(tracing_category),
       disabled_by_default_tracing_category_(
           disabled_by_default_tracing_category) {
-  control_task_runner_->SetQueuePriority(TaskQueue::CONTROL_PRIORITY);
+  control_task_queue_->SetQueuePriority(TaskQueue::CONTROL_PRIORITY);
 
   task_queue_manager_->SetWorkBatchSize(4);
 
   DCHECK(task_queue_manager_delegate_);
-  task_queue_manager_delegate_->SetDefaultTaskRunner(
-      default_task_runner_.get());
+  task_queue_manager_delegate_->SetDefaultTaskRunner(default_task_queue_.get());
 }
 
 SchedulerHelper::~SchedulerHelper() {
@@ -83,11 +82,11 @@
 
 scoped_refptr<TaskQueue> SchedulerHelper::DefaultTaskQueue() {
   CheckOnValidThread();
-  return default_task_runner_;
+  return default_task_queue_;
 }
 
 scoped_refptr<TaskQueue> SchedulerHelper::ControlTaskQueue() {
-  return control_task_runner_;
+  return control_task_queue_;
 }
 
 size_t SchedulerHelper::GetNumberOfPendingTasks() const {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
index 0dcdc5cf..46bb9ee 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
@@ -119,8 +119,8 @@
   base::ThreadChecker thread_checker_;
   scoped_refptr<SchedulerTqmDelegate> task_queue_manager_delegate_;
   std::unique_ptr<TaskQueueManager> task_queue_manager_;
-  scoped_refptr<TaskQueue> control_task_runner_;
-  scoped_refptr<TaskQueue> default_task_runner_;
+  scoped_refptr<TaskQueue> control_task_queue_;
+  scoped_refptr<TaskQueue> default_task_queue_;
 
   Observer* observer_;  // NOT OWNED
   const char* tracing_category_;
diff --git a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc
index 553f8efe..2adcdb1f 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.cc
@@ -22,7 +22,6 @@
     scoped_refptr<TaskQueue> timer_task_runner)
     : child_scheduler_(child_scheduler),
       idle_task_runner_(idle_task_runner),
-      timer_task_runner_(timer_task_runner),
       loading_web_task_runner_(WebTaskRunnerImpl::Create(loading_task_runner)),
       timer_web_task_runner_(WebTaskRunnerImpl::Create(timer_task_runner)) {}
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.h
index c1745d9..29736e0 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler_impl.h
@@ -56,7 +56,6 @@
 
   ChildScheduler* child_scheduler_;  // NOT OWNED
   scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
-  scoped_refptr<TaskQueue> timer_task_runner_;
   RefPtr<WebTaskRunnerImpl> loading_web_task_runner_;
   RefPtr<WebTaskRunnerImpl> timer_web_task_runner_;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
index 0f8e9c9..706b2f4 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
@@ -66,14 +66,14 @@
       thread_->message_loop(), base::MakeUnique<base::DefaultTickClock>());
   worker_scheduler_ = CreateWorkerScheduler();
   worker_scheduler_->Init();
-  task_runner_ = worker_scheduler_->DefaultTaskQueue();
+  task_queue_ = worker_scheduler_->DefaultTaskQueue();
   idle_task_runner_ = worker_scheduler_->IdleTaskRunner();
   web_scheduler_.reset(new WebSchedulerImpl(
       worker_scheduler_.get(), worker_scheduler_->IdleTaskRunner(),
       worker_scheduler_->DefaultTaskQueue(),
       worker_scheduler_->DefaultTaskQueue()));
   base::MessageLoop::current()->AddDestructionObserver(this);
-  web_task_runner_ = WebTaskRunnerImpl::Create(task_runner_);
+  web_task_runner_ = WebTaskRunnerImpl::Create(task_queue_);
   completion->Signal();
 }
 
@@ -84,7 +84,7 @@
 }
 
 void WebThreadImplForWorkerScheduler::WillDestroyCurrentMessageLoop() {
-  task_runner_ = nullptr;
+  task_queue_ = nullptr;
   idle_task_runner_ = nullptr;
   web_scheduler_.reset();
   worker_scheduler_.reset();
@@ -106,7 +106,7 @@
 
 base::SingleThreadTaskRunner* WebThreadImplForWorkerScheduler::GetTaskRunner()
     const {
-  return task_runner_.get();
+  return task_queue_.get();
 }
 
 SingleThreadIdleTaskRunner* WebThreadImplForWorkerScheduler::GetIdleTaskRunner()
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
index 47c4e3e..5b9e0057 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
-#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
 
 #include "base/threading/thread.h"
 #include "public/platform/WebPrivatePtr.h"
@@ -73,7 +73,7 @@
   std::unique_ptr<scheduler::WorkerScheduler> worker_scheduler_;
   std::unique_ptr<scheduler::WebSchedulerImpl> web_scheduler_;
   scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
-  scoped_refptr<TaskQueue> task_runner_;
+  scoped_refptr<TaskQueue> task_queue_;
   scoped_refptr<scheduler::SingleThreadIdleTaskRunner> idle_task_runner_;
   scoped_refptr<SchedulerTqmDelegate> task_runner_delegate_;
   WebPrivatePtr<WebTaskRunnerImpl> web_task_runner_;
@@ -82,4 +82,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler.h
index 3712cab..99f0d40 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_WORKER_GLOBAL_SCOPE_SCHEDULER_H_
-#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_WORKER_GLOBAL_SCOPE_SCHEDULER_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WORKER_GLOBAL_SCOPE_SCHEDULER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WORKER_GLOBAL_SCOPE_SCHEDULER_H_
 
 #include "platform/scheduler/base/task_queue.h"
 #include "platform/scheduler/child/web_task_runner_impl.h"
@@ -46,4 +46,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_WORKER_GLOBAL_SCOPE_SCHEDULER_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WORKER_GLOBAL_SCOPE_SCHEDULER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h
index e470778..2e34af7 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
-#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
 
 #include <memory>
 
@@ -47,4 +47,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
index bd7c08f3..82c1e55 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
@@ -36,17 +36,17 @@
         main_task_runner_, "test.scheduler", "test.scheduler",
         "test.scheduler.debug");
     manager_->AddTaskTimeObserver(&test_task_time_observer_);
-    task_runner_ =
+    task_queue_ =
         manager_->NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::TEST));
     initial_time_ = clock_->NowTicks();
     auto_advancing_time_domain_.reset(
         new AutoAdvancingVirtualTimeDomain(initial_time_));
     manager_->RegisterTimeDomain(auto_advancing_time_domain_.get());
-    task_runner_->SetTimeDomain(auto_advancing_time_domain_.get());
+    task_queue_->SetTimeDomain(auto_advancing_time_domain_.get());
   }
 
   void TearDown() override {
-    task_runner_->UnregisterTaskQueue();
+    task_queue_->UnregisterTaskQueue();
     manager_->UnregisterTimeDomain(auto_advancing_time_domain_.get());
   }
 
@@ -56,7 +56,7 @@
   scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
   scoped_refptr<SchedulerTqmDelegate> main_task_runner_;
   std::unique_ptr<TaskQueueManager> manager_;
-  scoped_refptr<TaskQueue> task_runner_;
+  scoped_refptr<TaskQueue> task_queue_;
   std::unique_ptr<AutoAdvancingVirtualTimeDomain> auto_advancing_time_domain_;
   TestTaskTimeObserver test_task_time_observer_;
 };
@@ -70,8 +70,8 @@
 TEST_F(AutoAdvancingVirtualTimeDomainTest, VirtualTimeAdvances) {
   base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
   bool task_run = false;
-  task_runner_->PostDelayedTask(FROM_HERE, base::Bind(NopTask, &task_run),
-                                delay);
+  task_queue_->PostDelayedTask(FROM_HERE, base::Bind(NopTask, &task_run),
+                               delay);
 
   mock_task_runner_->RunUntilIdle();
 
@@ -84,8 +84,8 @@
 TEST_F(AutoAdvancingVirtualTimeDomainTest, VirtualTimeDoesNotAdvance) {
   base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
   bool task_run = false;
-  task_runner_->PostDelayedTask(FROM_HERE, base::Bind(NopTask, &task_run),
-                                delay);
+  task_queue_->PostDelayedTask(FROM_HERE, base::Bind(NopTask, &task_run),
+                               delay);
 
   auto_advancing_time_domain_->SetCanAdvanceVirtualTime(false);
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.cc b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.cc
index b40f8e2a..d3d5a8d 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.cc
@@ -14,17 +14,17 @@
     base::TickClock* time_source,
     int sample_count,
     double estimation_percentile)
-    : compositor_task_runner_(compositor_task_runner),
+    : compositor_task_queue_(compositor_task_runner),
       per_frame_compositor_task_runtime_(sample_count),
       time_source_(time_source),
       estimation_percentile_(estimation_percentile),
       nesting_level_(0),
       did_commit_(false) {
-  compositor_task_runner_->AddTaskObserver(this);
+  compositor_task_queue_->AddTaskObserver(this);
 }
 
 IdleTimeEstimator::~IdleTimeEstimator() {
-  compositor_task_runner_->RemoveTaskObserver(this);
+  compositor_task_queue_->RemoveTaskObserver(this);
 }
 
 base::TimeDelta IdleTimeEstimator::GetExpectedIdleDuration(
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.h b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.h
index 6074155..5987d914 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator.h
@@ -40,7 +40,7 @@
   void DidProcessTask(const base::PendingTask& pending_task) override;
 
  private:
-  scoped_refptr<TaskQueue> compositor_task_runner_;
+  scoped_refptr<TaskQueue> compositor_task_queue_;
   cc::RollingTimeDeltaHistory per_frame_compositor_task_runtime_;
   base::TickClock* time_source_;  // NOT OWNED
   double estimation_percentile_;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
index 00b2e06..d116859 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
@@ -48,10 +48,10 @@
     manager_ = base::MakeUnique<TaskQueueManager>(
         main_task_runner_, "test.scheduler", "test.scheduler",
         "test.scheduler.debug");
-    compositor_task_runner_ = manager_->NewTaskQueue(
+    compositor_task_queue_ = manager_->NewTaskQueue(
         TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR));
     estimator_.reset(new IdleTimeEstimatorForTest(
-        compositor_task_runner_, test_time_source_.get(), 10, 50));
+        compositor_task_queue_, test_time_source_.get(), 10, 50));
   }
 
   void SimulateFrameWithOneCompositorTask(int compositor_time) {
@@ -91,7 +91,7 @@
   scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
   scoped_refptr<SchedulerTqmDelegate> main_task_runner_;
   std::unique_ptr<TaskQueueManager> manager_;
-  scoped_refptr<TaskQueue> compositor_task_runner_;
+  scoped_refptr<TaskQueue> compositor_task_queue_;
   std::unique_ptr<IdleTimeEstimatorForTest> estimator_;
   const base::TimeDelta frame_length_;
   TestTaskTimeObserver test_task_time_observer_;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
index 4ae63b51..112af82 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -101,12 +101,12 @@
                                           &helper_,
                                           idle_helper_.IdleTaskRunner()),
       render_widget_scheduler_signals_(this),
-      control_task_runner_(helper_.ControlTaskQueue()),
-      compositor_task_runner_(
+      control_task_queue_(helper_.ControlTaskQueue()),
+      compositor_task_queue_(
           helper_.NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR)
                                    .SetShouldMonitorQuiescence(true))),
-      compositor_task_runner_enabled_voter_(
-          compositor_task_runner_->CreateQueueEnabledVoter()),
+      compositor_task_queue_enabled_voter_(
+          compositor_task_queue_->CreateQueueEnabledVoter()),
       delayed_update_policy_runner_(
           base::Bind(&RendererSchedulerImpl::UpdatePolicy,
                      base::Unretained(this)),
@@ -114,7 +114,7 @@
       seqlock_queueing_time_estimator_(
           QueueingTimeEstimator(this, base::TimeDelta::FromSeconds(1))),
       main_thread_only_(this,
-                        compositor_task_runner_,
+                        compositor_task_queue_,
                         helper_.scheduler_tqm_delegate().get(),
                         helper_.scheduler_tqm_delegate()->NowTicks()),
       policy_may_need_update_(&any_thread_lock_),
@@ -130,9 +130,9 @@
       base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded,
                  weak_factory_.GetWeakPtr()));
 
-  default_loading_task_runner_ =
+  default_loading_task_queue_ =
       NewLoadingTaskQueue(TaskQueue::QueueType::DEFAULT_LOADING);
-  default_timer_task_runner_ =
+  default_timer_task_queue_ =
       NewTimerTaskQueue(TaskQueue::QueueType::DEFAULT_TIMER);
 
   TRACE_EVENT_OBJECT_CREATED_WITH_ID(
@@ -272,7 +272,7 @@
 scoped_refptr<base::SingleThreadTaskRunner>
 RendererSchedulerImpl::CompositorTaskRunner() {
   helper_.CheckOnValidThread();
-  return compositor_task_runner_;
+  return compositor_task_queue_;
 }
 
 scoped_refptr<SingleThreadIdleTaskRunner>
@@ -283,13 +283,13 @@
 scoped_refptr<base::SingleThreadTaskRunner>
 RendererSchedulerImpl::LoadingTaskRunner() {
   helper_.CheckOnValidThread();
-  return default_loading_task_runner_;
+  return default_loading_task_queue_;
 }
 
 scoped_refptr<base::SingleThreadTaskRunner>
 RendererSchedulerImpl::TimerTaskRunner() {
   helper_.CheckOnValidThread();
-  return default_timer_task_runner_;
+  return default_timer_task_queue_;
 }
 
 scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskQueue() {
@@ -298,17 +298,17 @@
 
 scoped_refptr<TaskQueue> RendererSchedulerImpl::CompositorTaskQueue() {
   helper_.CheckOnValidThread();
-  return compositor_task_runner_;
+  return compositor_task_queue_;
 }
 
 scoped_refptr<TaskQueue> RendererSchedulerImpl::LoadingTaskQueue() {
   helper_.CheckOnValidThread();
-  return default_loading_task_runner_;
+  return default_loading_task_queue_;
 }
 
 scoped_refptr<TaskQueue> RendererSchedulerImpl::TimerTaskQueue() {
   helper_.CheckOnValidThread();
-  return default_timer_task_runner_;
+  return default_timer_task_queue_;
 }
 
 scoped_refptr<TaskQueue> RendererSchedulerImpl::ControlTaskQueue() {
@@ -491,7 +491,7 @@
     // hidden.
     base::TimeDelta end_idle_when_hidden_delay =
         base::TimeDelta::FromMilliseconds(kEndIdleWhenHiddenDelayMillis);
-    control_task_runner_->PostDelayedTask(
+    control_task_queue_->PostDelayedTask(
         FROM_HERE, end_renderer_hidden_idle_period_closure_.GetCallback(),
         end_idle_when_hidden_delay);
     GetMainThreadOnly().renderer_hidden = true;
@@ -540,7 +540,7 @@
   base::TimeDelta suspend_timers_when_backgrounded_delay =
       base::TimeDelta::FromMilliseconds(
           kSuspendTimersWhenBackgroundedDelayMillis);
-  control_task_runner_->PostDelayedTask(
+  control_task_queue_->PostDelayedTask(
       FROM_HERE, suspend_timers_when_backgrounded_closure_.GetCallback(),
       suspend_timers_when_backgrounded_delay);
 }
@@ -848,7 +848,7 @@
     case UseCase::MAIN_THREAD_GESTURE:
     case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING:
     case UseCase::SYNCHRONIZED_GESTURE:
-      return compositor_task_runner_->HasPendingImmediateWork() ||
+      return compositor_task_queue_->HasPendingImmediateWork() ||
              GetMainThreadOnly().touchstart_expected_soon;
 
     case UseCase::TOUCHSTART:
@@ -891,7 +891,7 @@
   any_thread_lock_.AssertAcquired();
   if (!policy_may_need_update_.IsSet()) {
     policy_may_need_update_.SetWhileLocked(true);
-    control_task_runner_->PostTask(from_here, update_policy_closure_);
+    control_task_queue_->PostTask(from_here, update_policy_closure_);
   }
 }
 
@@ -1165,8 +1165,7 @@
   }
 
   ApplyTaskQueuePolicy(
-      compositor_task_runner_.get(),
-      compositor_task_runner_enabled_voter_.get(),
+      compositor_task_queue_.get(), compositor_task_queue_enabled_voter_.get(),
       GetMainThreadOnly().current_policy.compositor_queue_policy,
       new_policy.compositor_queue_policy);
 
@@ -1206,7 +1205,7 @@
     }
   }
 
-  DCHECK(compositor_task_runner_->IsQueueEnabled());
+  DCHECK(compositor_task_queue_->IsQueueEnabled());
   GetMainThreadOnly().current_policy = new_policy;
 }
 
@@ -1361,7 +1360,7 @@
   GetMainThreadOnly().timer_queue_suspend_count++;
   ForceUpdatePolicy();
 #ifndef NDEBUG
-  DCHECK(!default_timer_task_runner_->IsQueueEnabled());
+  DCHECK(!default_timer_task_queue_->IsQueueEnabled());
   for (const auto& runner : timer_task_runners_) {
     DCHECK(!runner.first->IsQueueEnabled());
   }
@@ -1655,11 +1654,11 @@
   //
   // Per-frame task runners (loading, timers, etc.) are configured with a more
   // specific blame context by WebFrameSchedulerImpl.
-  control_task_runner_->SetBlameContext(blame_context);
+  control_task_queue_->SetBlameContext(blame_context);
   DefaultTaskQueue()->SetBlameContext(blame_context);
-  default_loading_task_runner_->SetBlameContext(blame_context);
-  default_timer_task_runner_->SetBlameContext(blame_context);
-  compositor_task_runner_->SetBlameContext(blame_context);
+  default_loading_task_queue_->SetBlameContext(blame_context);
+  default_timer_task_queue_->SetBlameContext(blame_context);
+  compositor_task_queue_->SetBlameContext(blame_context);
   idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context);
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
index b36150b..1af8c53 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -400,10 +400,10 @@
   std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
   RenderWidgetSignals render_widget_scheduler_signals_;
 
-  const scoped_refptr<TaskQueue> control_task_runner_;
-  const scoped_refptr<TaskQueue> compositor_task_runner_;
+  const scoped_refptr<TaskQueue> control_task_queue_;
+  const scoped_refptr<TaskQueue> compositor_task_queue_;
   std::unique_ptr<TaskQueue::QueueEnabledVoter>
-      compositor_task_runner_enabled_voter_;
+      compositor_task_queue_enabled_voter_;
 
   using TaskQueueVoterMap =
       std::map<scoped_refptr<TaskQueue>,
@@ -412,8 +412,8 @@
   TaskQueueVoterMap loading_task_runners_;
   TaskQueueVoterMap timer_task_runners_;
   std::set<scoped_refptr<TaskQueue>> unthrottled_task_runners_;
-  scoped_refptr<TaskQueue> default_loading_task_runner_;
-  scoped_refptr<TaskQueue> default_timer_task_runner_;
+  scoped_refptr<TaskQueue> default_loading_task_queue_;
+  scoped_refptr<TaskQueue> default_timer_task_queue_;
 
   // Note |virtual_time_domain_| is lazily created.
   std::unique_ptr<AutoAdvancingVirtualTimeDomain> virtual_time_domain_;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
index 1dfe3798..d37e3f92 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
@@ -75,7 +75,7 @@
 TaskQueueThrottler::TaskQueueThrottler(
     RendererSchedulerImpl* renderer_scheduler,
     const char* tracing_category)
-    : task_runner_(renderer_scheduler->ControlTaskQueue()),
+    : control_task_queue_(renderer_scheduler->ControlTaskQueue()),
       renderer_scheduler_(renderer_scheduler),
       tick_clock_(renderer_scheduler->tick_clock()),
       tracing_category_(tracing_category),
@@ -108,7 +108,7 @@
 }
 
 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
-  DCHECK_NE(task_queue, task_runner_.get());
+  DCHECK_NE(task_queue, control_task_queue_.get());
 
   std::pair<TaskQueueMap::iterator, bool> insert_result =
       queue_details_.insert(std::make_pair(task_queue, Metadata()));
@@ -194,8 +194,8 @@
 void TaskQueueThrottler::OnQueueNextWakeUpChanged(
     TaskQueue* queue,
     base::TimeTicks next_wake_up) {
-  if (!task_runner_->RunsTasksOnCurrentThread()) {
-    task_runner_->PostTask(
+  if (!control_task_queue_->RunsTasksOnCurrentThread()) {
+    control_task_queue_->PostTask(
         FROM_HERE,
         base::Bind(forward_immediate_work_callback_, queue, next_wake_up));
     return;
@@ -303,7 +303,7 @@
   TRACE_EVENT1(tracing_category_,
                "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks",
                "delay_till_next_pump_ms", delay.InMilliseconds());
-  task_runner_->PostDelayedTask(
+  control_task_queue_->PostDelayedTask(
       from_here, pump_throttled_tasks_closure_.GetCallback(), delay);
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.h b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.h
index 8e8567b..a6d1f842 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.h
@@ -128,7 +128,9 @@
   static base::TimeTicks AlignedThrottledRunTime(
       base::TimeTicks unthrottled_runtime);
 
-  const scoped_refptr<TaskQueue>& task_runner() const { return task_runner_; }
+  const scoped_refptr<TaskQueue>& task_queue() const {
+    return control_task_queue_;
+  }
 
   // Returned object is owned by |TaskQueueThrottler|.
   CPUTimeBudgetPool* CreateCPUTimeBudgetPool(const char* name);
@@ -174,7 +176,7 @@
   TaskQueueMap queue_details_;
   base::Callback<void(TaskQueue*, base::TimeTicks)>
       forward_immediate_work_callback_;
-  scoped_refptr<TaskQueue> task_runner_;
+  scoped_refptr<TaskQueue> control_task_queue_;
   RendererSchedulerImpl* renderer_scheduler_;  // NOT OWNED
   base::TickClock* tick_clock_;                // NOT OWNED
   const char* tracing_category_;               // NOT OWNED
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
index 1814fbc..0c9df83 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
@@ -271,14 +271,14 @@
        ThrotlingAnEmptyQueueDoesNotPostPumpThrottledTasksLocked) {
   task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
 
-  EXPECT_TRUE(task_queue_throttler_->task_runner()->IsEmpty());
+  EXPECT_TRUE(task_queue_throttler_->task_queue()->IsEmpty());
 }
 
 TEST_F(TaskQueueThrottlerTest, OnTimeDomainHasImmediateWork_EnabledQueue) {
   task_queue_throttler_->OnQueueNextWakeUpChanged(timer_queue_.get(),
                                                   base::TimeTicks());
   // Check PostPumpThrottledTasksLocked was called.
-  EXPECT_FALSE(task_queue_throttler_->task_runner()->IsEmpty());
+  EXPECT_FALSE(task_queue_throttler_->task_queue()->IsEmpty());
 }
 
 TEST_F(TaskQueueThrottlerTest, OnTimeDomainHasImmediateWork_DisabledQueue) {
@@ -289,7 +289,7 @@
   task_queue_throttler_->OnQueueNextWakeUpChanged(timer_queue_.get(),
                                                   base::TimeTicks());
   // Check PostPumpThrottledTasksLocked was not called.
-  EXPECT_TRUE(task_queue_throttler_->task_runner()->IsEmpty());
+  EXPECT_TRUE(task_queue_throttler_->task_queue()->IsEmpty());
 }
 
 TEST_F(TaskQueueThrottlerTest,
@@ -301,11 +301,11 @@
   voter->SetQueueEnabled(false);
 
   task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
-  EXPECT_TRUE(task_queue_throttler_->task_runner()->IsEmpty());
+  EXPECT_TRUE(task_queue_throttler_->task_queue()->IsEmpty());
 
   // Enabling it should trigger a call to PostPumpThrottledTasksLocked.
   voter->SetQueueEnabled(true);
-  EXPECT_FALSE(task_queue_throttler_->task_runner()->IsEmpty());
+  EXPECT_FALSE(task_queue_throttler_->task_queue()->IsEmpty());
 }
 
 TEST_F(TaskQueueThrottlerTest,
@@ -318,11 +318,11 @@
   voter->SetQueueEnabled(false);
 
   task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
-  EXPECT_TRUE(task_queue_throttler_->task_runner()->IsEmpty());
+  EXPECT_TRUE(task_queue_throttler_->task_queue()->IsEmpty());
 
   // Enabling it should trigger a call to PostPumpThrottledTasksLocked.
   voter->SetQueueEnabled(true);
-  EXPECT_FALSE(task_queue_throttler_->task_runner()->IsEmpty());
+  EXPECT_FALSE(task_queue_throttler_->task_queue()->IsEmpty());
 }
 
 TEST_F(TaskQueueThrottlerTest, WakeUpForNonDelayedTask) {
diff --git a/third_party/WebKit/Source/platform/scheduler/utility/webthread_impl_for_utility_thread.h b/third_party/WebKit/Source/platform/scheduler/utility/webthread_impl_for_utility_thread.h
index ece38941..3fdb2e9 100644
--- a/third_party/WebKit/Source/platform/scheduler/utility/webthread_impl_for_utility_thread.h
+++ b/third_party/WebKit/Source/platform/scheduler/utility/webthread_impl_for_utility_thread.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_UTILITY_WEBTHREAD_IMPL_FOR_UTILITY_THREAD_H_
-#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_UTILITY_WEBTHREAD_IMPL_FOR_UTILITY_THREAD_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_UTILITY_WEBTHREAD_IMPL_FOR_UTILITY_THREAD_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_UTILITY_WEBTHREAD_IMPL_FOR_UTILITY_THREAD_H_
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
@@ -38,4 +38,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_UTILITY_WEBTHREAD_IMPL_FOR_UTILITY_THREAD_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_UTILITY_WEBTHREAD_IMPL_FOR_UTILITY_THREAD_H_
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index ed8f2031f..b76c0f6 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -39229,6 +39229,14 @@
   <summary>True if a URLRequest's referrer is empty or valid when set.</summary>
 </histogram>
 
+<histogram name="Net.URLRequestContext.OutstandingRequests" units="count">
+  <owner>xunjieli@chromium.org</owner>
+  <summary>
+    Indicates the number of URLRequests that are handed out by a
+    URLRequestContext and are not yet destroyed.
+  </summary>
+</histogram>
+
 <histogram name="Net.ValidDNSName" enum="Boolean">
   <owner>palmer@chromium.org</owner>
   <summary>
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc
index 31ef57f..80eeda5 100644
--- a/ui/gfx/canvas.cc
+++ b/ui/gfx/canvas.cc
@@ -584,7 +584,7 @@
   // Ensure that the bitmap is zeroed, since the code expects that.
   memset(bitmap_->getPixels(), 0, bitmap_->getSafeSize());
 
-  owned_canvas_ = cc::SkiaPaintCanvas(bitmap_.value());
+  owned_canvas_.emplace(bitmap_.value());
   return &owned_canvas_.value();
 }
 
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index c77bdf4..ce75522 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -5,6 +5,7 @@
 #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"