diff --git a/DEPS b/DEPS
index 7b54c04b..bcce914 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '96d5b9a273a5513fb3215fc06452cda82c3d6872',
+  'skia_revision': 'b712089b93fadf3f3b560e9b21803f4c7626c94e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -56,7 +56,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': 'd3074448541662f242bcee623049c13a231b5648',
+  'buildtools_revision': '88811f48a6b79786ef35be86825642fc33011151',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '2c2b58de54d8788cccaddf3f3846c9fa1de00306',
+  'catapult_revision': '0146f4833cb3c65b3792e756676909648961cdaa',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 320b7fce..630db84 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1385,7 +1385,12 @@
     if (enabled_frame_pointers) {
       cflags = [ "-fno-omit-frame-pointer" ]
     } else {
-      cflags = [ "-fomit-frame-pointer" ]
+      if (is_android || current_cpu != "arm") {
+        # TODO(710131): Remove this special-casing for ARM 32 bit once we
+        # have determined why -fomit-frame-pointer triggers CPU errata in
+        # ARM A12/A17 devices.
+        cflags = [ "-fomit-frame-pointer" ]
+      }
     }
   }
   # On Windows, the flag to enable framepointers "/Oy-" must always come after
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index f7918544..c62ac3a 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -647,6 +647,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",
@@ -764,6 +766,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",
@@ -934,6 +937,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 6b9a0df..d45e84b 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -11,19 +11,24 @@
 #include "build/build_config.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_image.h"
-#include "cc/paint/paint_record.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 
 namespace cc {
 
 class DisplayItemList;
 class PaintFlags;
+class PaintOpBuffer;
+
+using PaintRecord = PaintOpBuffer;
 
 class CC_PAINT_EXPORT PaintCanvas {
  public:
   virtual ~PaintCanvas() {}
 
   virtual SkMetaData& getMetaData() = 0;
+
+  // TODO(enne): this only appears to mostly be used to determine if this is
+  // recording or not, so could be simplified or removed.
   virtual SkImageInfo imageInfo() const = 0;
 
   // TODO(enne): It would be nice to get rid of flush() entirely, as it
@@ -42,7 +47,7 @@
                            int y) = 0;
   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;
@@ -93,6 +98,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,
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..a98392a
--- /dev/null
+++ b/cc/paint/paint_op_buffer.cc
@@ -0,0 +1,556 @@
+// 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) {
+      op->record->GetFirstOp()->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);
+}
+
+DrawDisplayItemListOp::DrawDisplayItemListOp(
+    scoped_refptr<DisplayItemList> list)
+    : list(list) {}
+
+size_t DrawDisplayItemListOp::AdditionalBytesUsed() const {
+  return list->ApproximateMemoryUsage();
+}
+
+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() = 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..b5f60a4d
--- /dev/null
+++ b/cc/paint/paint_op_buffer.h
@@ -0,0 +1,782 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PAINT_PAINT_OP_BUFFER_H_
+#define CC_PAINT_PAINT_OP_BUFFER_H_
+
+#include <stdint.h>
+
+#include "base/logging.h"
+#include "cc/paint/paint_canvas.h"
+#include "cc/paint/paint_export.h"
+#include "cc/paint/paint_flags.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
+
+// PaintOpBuffer is a reimplementation of SkLiteDL.
+// See: third_party/skia/src/core/SkLiteDL.h.
+
+namespace cc {
+
+class DisplayItemList;
+
+class ThreadsafeMatrix : public SkMatrix {
+ public:
+  explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) {
+    (void)getType();
+  }
+};
+
+class 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 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 PaintOpWithDataArrayBase : PaintOpWithData {
+  // Helper class for static asserts in push functions.
+  using PaintOpWithData::PaintOpWithData;
+};
+
+template <typename T>
+struct 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 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 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 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 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 ConcatOp final : PaintOp {
+  static constexpr PaintOpType kType = PaintOpType::Concat;
+  explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {}
+  void Raster(SkCanvas* canvas) const;
+
+  ThreadsafeMatrix matrix;
+};
+
+struct 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 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 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 DrawDisplayItemListOp final : PaintOp {
+  static constexpr PaintOpType kType = PaintOpType::DrawDisplayItemList;
+  static constexpr bool kIsDrawOp = true;
+  explicit DrawDisplayItemListOp(scoped_refptr<DisplayItemList> list);
+  ~DrawDisplayItemListOp();
+  void Raster(SkCanvas* canvas) const;
+  size_t AdditionalBytesUsed() const;
+  // TODO(enne): DisplayItemList should know number of slow paths.
+
+  scoped_refptr<DisplayItemList> list;
+};
+
+struct 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 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 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 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 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 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 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 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 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 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 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 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 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 NoopOp final : PaintOp {
+  static constexpr PaintOpType kType = PaintOpType::Noop;
+  void Raster(SkCanvas* canvas) const {}
+};
+
+struct RestoreOp final : PaintOp {
+  static constexpr PaintOpType kType = PaintOpType::Restore;
+  void Raster(SkCanvas* canvas) const;
+};
+
+struct RotateOp final : PaintOp {
+  static constexpr PaintOpType kType = PaintOpType::Rotate;
+  explicit RotateOp(SkScalar degrees) : degrees(degrees) {}
+  void Raster(SkCanvas* canvas) const;
+
+  SkScalar degrees;
+};
+
+struct SaveOp final : PaintOp {
+  static constexpr PaintOpType kType = PaintOpType::Save;
+  void Raster(SkCanvas* canvas) const;
+};
+
+struct 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 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 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 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 TranslateOp final : PaintOp {
+  static constexpr PaintOpType kType = PaintOpType::Translate;
+  TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
+  void Raster(SkCanvas* canvas) const;
+
+  SkScalar dx;
+  SkScalar dy;
+};
+
+using LargestPaintOp = DrawDRRectOp;
+
+class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
+ public:
+  enum { kInitialBufferSize = 4096 };
+
+  PaintOpBuffer();
+  explicit PaintOpBuffer(const SkRect& cull_rect);
+  ~PaintOpBuffer() override;
+
+  void Reset();
+
+  void playback(SkCanvas* canvas) const;
+  void playback(SkCanvas* canvas, SkPicture::AbortCallback* callback) const;
+
+  // TODO(enne): These are no longer approximate.  Rename these.
+  int approximateOpCount() const { return op_count_; }
+  size_t approximateBytesUsed() const {
+    return sizeof(*this) + reserved_ + subrecord_bytes_used_;
+  }
+  int numSlowPaths() const { return num_slow_paths_; }
+
+  // Resize the PaintOpBuffer to exactly fit the current amount of used space.
+  void ShrinkToFit();
+
+  const SkRect& cullRect() const { return cull_rect_; }
+
+  PaintOp* GetFirstOp() const {
+    return reinterpret_cast<PaintOp*>(const_cast<char*>(&first_op_[0]));
+  }
+
+  template <typename T, typename... Args>
+  void push(Args&&... args) {
+    static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp.");
+    static_assert(!std::is_convertible<T, PaintOpWithData>::value,
+                  "Type needs to use push_with_data");
+    push_internal<T>(0, std::forward<Args>(args)...);
+  }
+
+  template <typename T, typename... Args>
+  void push_with_data(const void* data, size_t bytes, Args&&... args) {
+    static_assert(std::is_convertible<T, PaintOpWithData>::value,
+                  "T is not a PaintOpWithData");
+#if !defined(OS_CHROMEOS)
+    // TODO(enne): non-linux chromeos builds think that DrawTextOp
+    // can be converted to a PaintOpWithDataArrayBase.  OOPS.
+    static_assert(!std::is_convertible<T, PaintOpWithDataArrayBase>::value,
+                  "Type needs to use push_with_data_array");
+#endif
+    DCHECK_GE(bytes, 0u);
+    T* op = push_internal<T>(bytes, bytes, std::forward<Args>(args)...);
+    memcpy(paint_op_data(op), data, bytes);
+
+#if DCHECK_IS_ON()
+    // Double check the data fits between op and next op and doesn't clobber.
+    char* op_start = reinterpret_cast<char*>(op);
+    char* op_end = op_start + sizeof(T);
+    char* next_op = op_start + op->skip;
+    char* data_start = reinterpret_cast<char*>(paint_op_data(op));
+    char* data_end = data_start + bytes;
+    DCHECK_GE(data_start, op_end);
+    DCHECK_LT(data_start, next_op);
+    DCHECK_LE(data_end, next_op);
+#endif
+  }
+
+  template <typename T, typename M, typename... Args>
+  void push_with_data_array(const void* data,
+                            size_t bytes,
+                            const M* array,
+                            size_t count,
+                            Args&&... args) {
+    static_assert(std::is_convertible<T, PaintOpWithDataArray<M>>::value,
+                  "T is not a PaintOpWithDataArray");
+    DCHECK_GE(bytes, 0u);
+    DCHECK_GE(count, 0u);
+    size_t array_size = sizeof(M) * count;
+    size_t total_size = bytes + array_size;
+    T* op =
+        push_internal<T>(total_size, bytes, count, std::forward<Args>(args)...);
+    memcpy(paint_op_data(op), data, bytes);
+    memcpy(paint_op_array<M>(op), array, array_size);
+
+#if DCHECK_IS_ON()
+    // Double check data and array don't clobber op, next op, or each other
+    char* op_start = reinterpret_cast<char*>(op);
+    char* op_end = op_start + sizeof(T);
+    char* next_op = op_start + op->skip;
+    char* data_start = reinterpret_cast<char*>(paint_op_data(op));
+    char* data_end = data_start + bytes;
+    char* array_start = reinterpret_cast<char*>(paint_op_array<M>(op));
+    char* array_end = array_start + array_size;
+    DCHECK_GE(data_start, op_end);
+    DCHECK_LE(data_start, array_start);
+    DCHECK_GE(array_start, data_end);
+    DCHECK_LE(array_end, next_op);
+#endif
+  }
+
+  class Iterator {
+   public:
+    explicit Iterator(const PaintOpBuffer* buffer)
+        : buffer_(buffer), ptr_(buffer_->data_.get()) {}
+
+    PaintOp* operator->() const {
+      return op_idx_ ? reinterpret_cast<PaintOp*>(ptr_) : buffer_->GetFirstOp();
+    }
+    PaintOp* operator*() const { return operator->(); }
+    Iterator begin() { return Iterator(buffer_, buffer_->data_.get(), 0); }
+    Iterator end() {
+      return Iterator(buffer_, buffer_->data_.get() + buffer_->used_,
+                      buffer_->approximateOpCount());
+    }
+    bool operator!=(const Iterator& other) {
+      // Not valid to compare iterators on different buffers.
+      DCHECK_EQ(other.buffer_, buffer_);
+      return other.op_idx_ != op_idx_;
+    }
+    Iterator& operator++() {
+      if (!op_idx_++)
+        return *this;
+      PaintOp* op = **this;
+      uint32_t type = op->type;
+      CHECK_LE(type, static_cast<uint32_t>(PaintOpType::LastPaintOpType));
+      ptr_ += op->skip;
+      return *this;
+    }
+    operator bool() const { return op_idx_ < buffer_->approximateOpCount(); }
+
+    int op_idx() const { return op_idx_; }
+
+    // Return the next op without advancing the iterator, or nullptr if none.
+    PaintOp* peek1() const {
+      if (op_idx_ + 1 >= buffer_->approximateOpCount())
+        return nullptr;
+      if (!op_idx_)
+        return reinterpret_cast<PaintOp*>(ptr_);
+      return reinterpret_cast<PaintOp*>(ptr_ + (*this)->skip);
+    }
+
+    // Return the op two ops ahead without advancing the iterator, or nullptr if
+    // none.
+    PaintOp* peek2() const {
+      if (op_idx_ + 2 >= buffer_->approximateOpCount())
+        return nullptr;
+      char* next = ptr_ + reinterpret_cast<PaintOp*>(ptr_)->skip;
+      PaintOp* next_op = reinterpret_cast<PaintOp*>(next);
+      if (!op_idx_)
+        return next_op;
+      return reinterpret_cast<PaintOp*>(next + next_op->skip);
+    }
+
+   private:
+    Iterator(const PaintOpBuffer* buffer, char* ptr, int op_idx)
+        : buffer_(buffer), ptr_(ptr), op_idx_(op_idx) {}
+
+    const PaintOpBuffer* buffer_ = nullptr;
+    char* ptr_ = nullptr;
+    int op_idx_ = 0;
+  };
+
+ private:
+  template <typename T, bool HasFlags>
+  struct CountSlowPathsFromFlags {
+    static int Count(const T* op) { return 0; }
+  };
+
+  template <typename T>
+  struct CountSlowPathsFromFlags<T, true> {
+    static int Count(const T* op) { return op->flags.getPathEffect() ? 1 : 0; }
+  };
+
+  template <typename T, typename... Args>
+  T* push_internal(size_t bytes, Args&&... args) {
+    size_t skip = SkAlignPtr(sizeof(T) + bytes);
+    DCHECK_LT(skip, static_cast<size_t>(1) << 24);
+    if (used_ + skip > reserved_ || !op_count_) {
+      if (!op_count_) {
+        if (bytes) {
+          // Internal first_op buffer doesn't have room for extra data.
+          // If the op wants extra bytes, then we'll just store a Noop
+          // in the first_op and proceed from there.  This seems unlikely
+          // to be a common case.
+          push<NoopOp>();
+        } else {
+          T* op = reinterpret_cast<T*>(&first_op_[0]);
+          new (op) T{std::forward<Args>(args)...};
+          op->type = static_cast<uint32_t>(T::kType);
+          op->skip = 0;
+          op_count_++;
+          return op;
+        }
+      }
+
+      // Start reserved_ at kInitialBufferSize and then double.
+      // ShrinkToFit can make this smaller afterwards.
+      while (used_ + skip > reserved_)
+        reserved_ = reserved_ ? reserved_ * 2 : kInitialBufferSize;
+      data_.realloc(reserved_);
+    }
+    DCHECK_LE(used_ + skip, reserved_);
+
+    T* op = reinterpret_cast<T*>(data_.get() + used_);
+    used_ += skip;
+    new (op) T(std::forward<Args>(args)...);
+    op->type = static_cast<uint32_t>(T::kType);
+    op->skip = skip;
+    op_count_++;
+
+    num_slow_paths_ += CountSlowPathsFromFlags<T, T::kHasPaintFlags>::Count(op);
+    num_slow_paths_ += op->CountSlowPaths();
+
+    subrecord_bytes_used_ += op->AdditionalBytesUsed();
+
+    return op;
+  }
+
+  // As a performance optimization because n=1 is an extremely common case just
+  // store the first op in the PaintOpBuffer itself to avoid an extra alloc.
+  char first_op_[sizeof(LargestPaintOp)];
+  SkAutoTMalloc<char> data_;
+  size_t used_ = 0;
+  size_t reserved_ = 0;
+  int op_count_ = 0;
+
+  // Record paths for veto-to-msaa for gpu raster.
+  int num_slow_paths_ = 0;
+  // Record additional bytes used by referenced sub-records and display lists.
+  size_t subrecord_bytes_used_ = 0;
+  SkRect cull_rect_;
+
+  DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer);
+};
+
+}  // namespace cc
+
+#endif  // CC_PAINT_PAINT_OP_BUFFER_H_
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
new file mode 100644
index 0000000..5e0bf2aa
--- /dev/null
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -0,0 +1,259 @@
+// 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());
+}
+
+}  // 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..c43f965 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(), bounds);
+  return getRecordingCanvas();
+}
+
+sk_sp<PaintRecord> PaintRecorder::finishRecordingAsPicture() {
+  // SkPictureRecorder users expect that their saves are automatically
+  // closed for them.
+  //
+  // NOTE: Blink paint in general doesn't appear to need this, but the
+  // RecordingImageBufferSurface::fallBackToRasterCanvas finishing off the
+  // current frame depends on this.  Maybe we could remove this assumption and
+  // just have callers do it.
+  canvas_->restoreToCount(1);
+
+  // Some users (e.g. printing) use the existence of the recording canvas
+  // to know if recording is finished, so reset it here.
+  canvas_.reset();
+
+  buffer_->ShrinkToFit();
+  return std::move(buffer_);
+}
+
 }  // namespace cc
diff --git a/cc/paint/paint_recorder.h b/cc/paint/paint_recorder.h
index 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..7f2ba61
--- /dev/null
+++ b/cc/paint/record_paint_canvas.cc
@@ -0,0 +1,384 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/paint/record_paint_canvas.h"
+
+#include "base/memory/ptr_util.h"
+#include "cc/paint/display_item_list.h"
+#include "cc/paint/paint_op_buffer.h"
+#include "cc/paint/paint_record.h"
+#include "cc/paint/paint_recorder.h"
+#include "third_party/skia/include/core/SkAnnotation.h"
+#include "third_party/skia/include/core/SkMetaData.h"
+#include "third_party/skia/include/utils/SkNWayCanvas.h"
+
+namespace cc {
+
+RecordPaintCanvas::RecordPaintCanvas(PaintOpBuffer* buffer,
+                                     const SkRect& cull_rect)
+    : buffer_(buffer),
+      canvas_(static_cast<int>(std::ceil(cull_rect.right())),
+              static_cast<int>(std::ceil(cull_rect.bottom()))) {
+  DCHECK(buffer_);
+
+  // This is part of the "recording canvases have a size, but why" dance.
+  // By creating a canvas of size (right x bottom) and then clipping it,
+  // It makes getDeviceClipBounds return the original cull rect, which code
+  // in GraphicsContextCanvas on Mac expects.  (Just creating an SkNoDrawCanvas
+  // with the cull_rect makes a canvas of size (width x height) instead
+  // which is incorrect.  SkRecorder cheats with private resetForNextCanvas.
+  canvas_.clipRect(SkRect::Make(cull_rect.roundOut()), SkClipOp::kIntersect,
+                   false);
+}
+
+RecordPaintCanvas::~RecordPaintCanvas() = default;
+
+SkMetaData& RecordPaintCanvas::getMetaData() {
+  // This could just be SkMetaData owned by RecordPaintCanvas, but since
+  // SkCanvas already has one, we might as well use it directly.
+  return canvas_.getMetaData();
+}
+
+SkImageInfo RecordPaintCanvas::imageInfo() const {
+  return canvas_.imageInfo();
+}
+
+void RecordPaintCanvas::flush() {
+  // This is a noop when recording.
+}
+
+SkISize RecordPaintCanvas::getBaseLayerSize() const {
+  return canvas_.getBaseLayerSize();
+}
+
+bool RecordPaintCanvas::writePixels(const SkImageInfo& info,
+                                    const void* pixels,
+                                    size_t row_bytes,
+                                    int x,
+                                    int y) {
+  NOTREACHED();
+  return false;
+}
+
+int RecordPaintCanvas::save() {
+  buffer_->push<SaveOp>();
+  return canvas_.save();
+}
+
+int RecordPaintCanvas::saveLayer(const SkRect* bounds,
+                                 const PaintFlags* flags) {
+  if (flags) {
+    if (flags->IsSimpleOpacity()) {
+      // TODO(enne): maybe more callers should know this and call
+      // saveLayerAlpha instead of needing to check here.
+      uint8_t alpha = SkColorGetA(flags->getColor());
+      return saveLayerAlpha(bounds, alpha);
+    }
+
+    // TODO(enne): it appears that image filters affect matrices and color
+    // matrices affect transparent flags on SkCanvas layers, but it's not clear
+    // whether those are actually needed and we could just skip ToSkPaint here.
+    buffer_->push<SaveLayerOp>(bounds, flags);
+    const SkPaint& paint = ToSkPaint(*flags);
+    return canvas_.saveLayer(bounds, &paint);
+  }
+  buffer_->push<SaveLayerOp>(bounds, flags);
+  return canvas_.saveLayer(bounds, nullptr);
+}
+
+int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
+  buffer_->push<SaveLayerAlphaOp>(bounds, alpha);
+  return canvas_.saveLayerAlpha(bounds, alpha);
+}
+
+void RecordPaintCanvas::restore() {
+  buffer_->push<RestoreOp>();
+  canvas_.restore();
+}
+
+int RecordPaintCanvas::getSaveCount() const {
+  return canvas_.getSaveCount();
+}
+
+void RecordPaintCanvas::restoreToCount(int save_count) {
+  DCHECK_GE(save_count, 1);
+  int diff = canvas_.getSaveCount() - save_count;
+  DCHECK_GE(diff, 0);
+  for (int i = 0; i < diff; ++i)
+    restore();
+}
+
+void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) {
+  buffer_->push<TranslateOp>(dx, dy);
+  canvas_.translate(dx, dy);
+}
+
+void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) {
+  buffer_->push<ScaleOp>(sx, sy);
+  canvas_.scale(sx, sy);
+}
+
+void RecordPaintCanvas::rotate(SkScalar degrees) {
+  buffer_->push<RotateOp>(degrees);
+  canvas_.rotate(degrees);
+}
+
+void RecordPaintCanvas::concat(const SkMatrix& matrix) {
+  buffer_->push<ConcatOp>(matrix);
+  canvas_.concat(matrix);
+}
+
+void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) {
+  buffer_->push<SetMatrixOp>(matrix);
+  canvas_.setMatrix(matrix);
+}
+
+void RecordPaintCanvas::clipRect(const SkRect& rect,
+                                 SkClipOp op,
+                                 bool antialias) {
+  buffer_->push<ClipRectOp>(rect, op, antialias);
+  canvas_.clipRect(rect, op, antialias);
+}
+
+void RecordPaintCanvas::clipRRect(const SkRRect& rrect,
+                                  SkClipOp op,
+                                  bool antialias) {
+  // TODO(enne): does this happen? Should the caller know this?
+  if (rrect.isRect()) {
+    clipRect(rrect.getBounds(), op, antialias);
+    return;
+  }
+  buffer_->push<ClipRRectOp>(rrect, op, antialias);
+  canvas_.clipRRect(rrect, op, antialias);
+}
+
+void RecordPaintCanvas::clipPath(const SkPath& path,
+                                 SkClipOp op,
+                                 bool antialias) {
+  if (!path.isInverseFillType() && canvas_.getTotalMatrix().rectStaysRect()) {
+    // TODO(enne): do these cases happen? should the caller know that this isn't
+    // a path?
+    SkRect rect;
+    if (path.isRect(&rect)) {
+      clipRect(rect, op, antialias);
+      return;
+    }
+    SkRRect rrect;
+    if (path.isOval(&rect)) {
+      rrect.setOval(rect);
+      clipRRect(rrect, op, antialias);
+      return;
+    }
+    if (path.isRRect(&rrect)) {
+      clipRRect(rrect, op, antialias);
+      return;
+    }
+  }
+
+  buffer_->push<ClipPathOp>(path, op, antialias);
+  canvas_.clipPath(path, op, antialias);
+  return;
+}
+
+bool RecordPaintCanvas::quickReject(const SkRect& rect) const {
+  return canvas_.quickReject(rect);
+}
+
+bool RecordPaintCanvas::quickReject(const SkPath& path) const {
+  return canvas_.quickReject(path);
+}
+
+SkRect RecordPaintCanvas::getLocalClipBounds() const {
+  return canvas_.getLocalClipBounds();
+}
+
+bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
+  return canvas_.getLocalClipBounds(bounds);
+}
+
+SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
+  return canvas_.getDeviceClipBounds();
+}
+
+bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
+  return canvas_.getDeviceClipBounds(bounds);
+}
+
+void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) {
+  buffer_->push<DrawColorOp>(color, mode);
+}
+
+void RecordPaintCanvas::clear(SkColor color) {
+  buffer_->push<DrawColorOp>(color, SkBlendMode::kSrc);
+}
+
+void RecordPaintCanvas::drawLine(SkScalar x0,
+                                 SkScalar y0,
+                                 SkScalar x1,
+                                 SkScalar y1,
+                                 const PaintFlags& flags) {
+  buffer_->push<DrawLineOp>(x0, y0, x1, y1, flags);
+}
+
+void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
+  buffer_->push<DrawRectOp>(rect, flags);
+}
+
+void RecordPaintCanvas::drawIRect(const SkIRect& rect,
+                                  const PaintFlags& flags) {
+  buffer_->push<DrawIRectOp>(rect, flags);
+}
+
+void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
+  buffer_->push<DrawOvalOp>(oval, flags);
+}
+
+void RecordPaintCanvas::drawRRect(const SkRRect& rrect,
+                                  const PaintFlags& flags) {
+  buffer_->push<DrawRRectOp>(rrect, flags);
+}
+
+void RecordPaintCanvas::drawDRRect(const SkRRect& outer,
+                                   const SkRRect& inner,
+                                   const PaintFlags& flags) {
+  if (outer.isEmpty())
+    return;
+  if (inner.isEmpty()) {
+    drawRRect(outer, flags);
+    return;
+  }
+  buffer_->push<DrawDRRectOp>(outer, inner, flags);
+}
+
+void RecordPaintCanvas::drawCircle(SkScalar cx,
+                                   SkScalar cy,
+                                   SkScalar radius,
+                                   const PaintFlags& flags) {
+  buffer_->push<DrawCircleOp>(cx, cy, radius, flags);
+}
+
+void RecordPaintCanvas::drawArc(const SkRect& oval,
+                                SkScalar start_angle,
+                                SkScalar sweep_angle,
+                                bool use_center,
+                                const PaintFlags& flags) {
+  buffer_->push<DrawArcOp>(oval, start_angle, sweep_angle, use_center, flags);
+}
+
+void RecordPaintCanvas::drawRoundRect(const SkRect& rect,
+                                      SkScalar rx,
+                                      SkScalar ry,
+                                      const PaintFlags& flags) {
+  // TODO(enne): move this into base class?
+  if (rx > 0 && ry > 0) {
+    SkRRect rrect;
+    rrect.setRectXY(rect, rx, ry);
+    drawRRect(rrect, flags);
+  } else {
+    drawRect(rect, flags);
+  }
+}
+
+void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
+  buffer_->push<DrawPathOp>(path, flags);
+}
+
+void RecordPaintCanvas::drawImage(const PaintImage& image,
+                                  SkScalar left,
+                                  SkScalar top,
+                                  const PaintFlags* flags) {
+  buffer_->push<DrawImageOp>(image, left, top, flags);
+}
+
+void RecordPaintCanvas::drawImageRect(const PaintImage& image,
+                                      const SkRect& src,
+                                      const SkRect& dst,
+                                      const PaintFlags* flags,
+                                      SrcRectConstraint constraint) {
+  buffer_->push<DrawImageRectOp>(image, src, dst, flags, constraint);
+}
+
+void RecordPaintCanvas::drawBitmap(const SkBitmap& bitmap,
+                                   SkScalar left,
+                                   SkScalar top,
+                                   const PaintFlags* flags) {
+  // TODO(enne): Move into base class?
+  if (bitmap.drawsNothing())
+    return;
+  drawImage(PaintImage(SkImage::MakeFromBitmap(bitmap),
+                       PaintImage::AnimationType::UNKNOWN,
+                       PaintImage::CompletionState::UNKNOWN),
+            left, top, flags);
+}
+
+void RecordPaintCanvas::drawText(const void* text,
+                                 size_t byte_length,
+                                 SkScalar x,
+                                 SkScalar y,
+                                 const PaintFlags& flags) {
+  buffer_->push_with_data<DrawTextOp>(text, byte_length, x, y, flags);
+}
+
+void RecordPaintCanvas::drawPosText(const void* text,
+                                    size_t byte_length,
+                                    const SkPoint pos[],
+                                    const PaintFlags& flags) {
+  size_t count = ToSkPaint(flags).countText(text, byte_length);
+  buffer_->push_with_data_array<DrawPosTextOp>(text, byte_length, pos, count,
+                                               flags);
+}
+
+void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
+                                     SkScalar x,
+                                     SkScalar y,
+                                     const PaintFlags& flags) {
+  buffer_->push<DrawTextBlobOp>(blob, x, y, flags);
+}
+
+void RecordPaintCanvas::drawDisplayItemList(
+    scoped_refptr<DisplayItemList> list) {
+  buffer_->push<DrawDisplayItemListOp>(list);
+}
+
+void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
+  // TODO(enne): If this is small, maybe flatten it?
+  buffer_->push<DrawRecordOp>(record);
+}
+
+bool RecordPaintCanvas::isClipEmpty() const {
+  return canvas_.isClipEmpty();
+}
+
+bool RecordPaintCanvas::isClipRect() const {
+  return canvas_.isClipRect();
+}
+
+const SkMatrix& RecordPaintCanvas::getTotalMatrix() const {
+  return canvas_.getTotalMatrix();
+}
+
+void RecordPaintCanvas::temporary_internal_describeTopLayer(
+    SkMatrix* matrix,
+    SkIRect* clip_bounds) {
+  return canvas_.temporary_internal_describeTopLayer(matrix, clip_bounds);
+}
+
+bool RecordPaintCanvas::ToPixmap(SkPixmap* output) {
+  // TODO(enne): It'd be nice to make this NOTREACHED() or remove this from
+  // RecordPaintCanvas, but this is used by GraphicsContextCanvas for knowing
+  // whether or not it can raster directly into pixels with Cg.
+  return false;
+}
+
+void RecordPaintCanvas::Annotate(AnnotationType type,
+                                 const SkRect& rect,
+                                 sk_sp<SkData> data) {
+  buffer_->push<AnnotateOp>(type, rect, data);
+}
+
+void RecordPaintCanvas::PlaybackPaintRecord(sk_sp<const PaintRecord> record) {
+  drawPicture(record);
+}
+
+}  // namespace cc
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h
new file mode 100644
index 0000000..15f0102
--- /dev/null
+++ b/cc/paint/record_paint_canvas.h
@@ -0,0 +1,160 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PAINT_RECORD_PAINT_CANVAS_H_
+#define CC_PAINT_RECORD_PAINT_CANVAS_H_
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "cc/paint/paint_canvas.h"
+#include "cc/paint/paint_flags.h"
+#include "cc/paint/paint_record.h"
+#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
+
+namespace cc {
+
+class PaintOpBuffer;
+class PaintFlags;
+
+class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas {
+ public:
+  explicit RecordPaintCanvas(PaintOpBuffer* buffer, const SkRect& cull_rect);
+  ~RecordPaintCanvas() override;
+
+  SkMetaData& getMetaData() override;
+  SkImageInfo imageInfo() const override;
+
+  void flush() override;
+
+  SkISize getBaseLayerSize() const override;
+  bool writePixels(const SkImageInfo& info,
+                   const void* pixels,
+                   size_t row_bytes,
+                   int x,
+                   int y) override;
+  int save() override;
+  int saveLayer(const SkRect* bounds, const PaintFlags* flags) override;
+  int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override;
+
+  void restore() override;
+  int getSaveCount() const override;
+  void restoreToCount(int save_count) override;
+  void translate(SkScalar dx, SkScalar dy) override;
+  void scale(SkScalar sx, SkScalar sy) override;
+  void rotate(SkScalar degrees) override;
+  void concat(const SkMatrix& matrix) override;
+  void setMatrix(const SkMatrix& matrix) override;
+
+  void clipRect(const SkRect& rect, SkClipOp op, bool antialias) override;
+  void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) override;
+  void clipPath(const SkPath& path, SkClipOp op, bool antialias) override;
+  bool quickReject(const SkRect& rect) const override;
+  bool quickReject(const SkPath& path) const override;
+  SkRect getLocalClipBounds() const override;
+  bool getLocalClipBounds(SkRect* bounds) const override;
+  SkIRect getDeviceClipBounds() const override;
+  bool getDeviceClipBounds(SkIRect* bounds) const override;
+  void drawColor(SkColor color, SkBlendMode mode) override;
+  void clear(SkColor color) override;
+
+  void drawLine(SkScalar x0,
+                SkScalar y0,
+                SkScalar x1,
+                SkScalar y1,
+                const PaintFlags& flags) override;
+  void drawRect(const SkRect& rect, const PaintFlags& flags) override;
+  void drawIRect(const SkIRect& rect, const PaintFlags& flags) override;
+  void drawOval(const SkRect& oval, const PaintFlags& flags) override;
+  void drawRRect(const SkRRect& rrect, const PaintFlags& flags) override;
+  void drawDRRect(const SkRRect& outer,
+                  const SkRRect& inner,
+                  const PaintFlags& flags) override;
+  void drawCircle(SkScalar cx,
+                  SkScalar cy,
+                  SkScalar radius,
+                  const PaintFlags& flags) override;
+  void drawArc(const SkRect& oval,
+               SkScalar start_angle,
+               SkScalar sweep_angle,
+               bool use_center,
+               const PaintFlags& flags) override;
+  void drawRoundRect(const SkRect& rect,
+                     SkScalar rx,
+                     SkScalar ry,
+                     const PaintFlags& flags) override;
+  void drawPath(const SkPath& path, const PaintFlags& flags) override;
+  void drawImage(const PaintImage& image,
+                 SkScalar left,
+                 SkScalar top,
+                 const PaintFlags* flags) override;
+  void drawImageRect(const PaintImage& image,
+                     const SkRect& src,
+                     const SkRect& dst,
+                     const PaintFlags* flags,
+                     SrcRectConstraint constraint) override;
+  void drawBitmap(const SkBitmap& bitmap,
+                  SkScalar left,
+                  SkScalar top,
+                  const PaintFlags* flags) override;
+
+  void drawText(const void* text,
+                size_t byte_length,
+                SkScalar x,
+                SkScalar y,
+                const PaintFlags& flags) override;
+  void drawPosText(const void* text,
+                   size_t byte_length,
+                   const SkPoint pos[],
+                   const PaintFlags& flags) override;
+  void drawTextBlob(sk_sp<SkTextBlob> blob,
+                    SkScalar x,
+                    SkScalar y,
+                    const PaintFlags& flags) override;
+
+  void drawDisplayItemList(
+      scoped_refptr<DisplayItemList> display_item_list) override;
+
+  void drawPicture(sk_sp<const PaintRecord> record) override;
+
+  bool isClipEmpty() const override;
+  bool isClipRect() const override;
+  const SkMatrix& getTotalMatrix() const override;
+
+  void temporary_internal_describeTopLayer(SkMatrix* matrix,
+                                           SkIRect* clip_bounds) override;
+
+  bool ToPixmap(SkPixmap* output) override;
+  void Annotate(AnnotationType type,
+                const SkRect& rect,
+                sk_sp<SkData> data) override;
+
+  void PlaybackPaintRecord(sk_sp<const PaintRecord> record) override;
+
+  // Don't shadow non-virtual helper functions.
+  using PaintCanvas::clipRect;
+  using PaintCanvas::clipRRect;
+  using PaintCanvas::clipPath;
+  using PaintCanvas::drawBitmap;
+  using PaintCanvas::drawColor;
+  using PaintCanvas::drawImage;
+  using PaintCanvas::drawPicture;
+
+ private:
+  PaintOpBuffer* buffer_;
+
+  // TODO(enne): Although RecordPaintCanvas is mostly a write-only interface
+  // where paint commands are stored, occasionally users of PaintCanvas want
+  // to ask stateful questions mid-stream of clip and transform state.
+  // To avoid duplicating all this code (for now?), just forward to an SkCanvas
+  // that's not backed by anything but can answer these questions.
+  SkNoDrawCanvas canvas_;
+};
+
+}  // namespace cc
+
+#endif  // CC_PAINT_RECORD_PAINT_CANVAS_H_
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index bfc38b6..501ccdf 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/paint/paint_canvas.h"
+#include "cc/paint/skia_paint_canvas.h"
 
 #include "base/memory/ptr_util.h"
 #include "cc/paint/display_item_list.h"
@@ -58,7 +58,7 @@
   return canvas_->saveLayer(bounds, ToSkPaint(flags));
 }
 
-int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, 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 47dba86..1bd23f0 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -46,7 +46,7 @@
                    int y) override;
   int save() override;
   int saveLayer(const SkRect* bounds, const PaintFlags* flags) override;
-  int saveLayerAlpha(const SkRect* bounds, 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/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
index 43b71b4..8007e82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
@@ -1154,7 +1154,6 @@
         mBarHeightPeeking = barHeightPx * mPxToDp;
         mBarHeightMaximized = mBarHeightPeeking;
         mBarHeightExpanded = mBarHeightPeeking;
-        mHeight = mBarHeightPeeking;
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index 965e27d..cfcfc1d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -202,10 +202,13 @@
                 removeCallbacks(mKeyboardResizeModeTask);
                 mKeyboardResizeModeTask = null;
             }
-            if (windowDelegate.getWindowSoftInputMode()
-                    != WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) {
-                windowDelegate.setWindowSoftInputMode(
-                        WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
+            // TODO(mdjones): SOFT_INPUT_ADJUST_NOTHING breaks omnibox suggestions but fixes a
+            // content jumping bug in Chrome Home. See https://crbug.com/706918
+            int softInputMode = mBottomSheet != null
+                    ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
+                    : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
+            if (windowDelegate.getWindowSoftInputMode() != softInputMode) {
+                windowDelegate.setWindowSoftInputMode(softInputMode);
             }
             UiUtils.showKeyboard(mUrlBar);
             // As the position of the navigation icon has changed, ensure the suggestions are
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
index 28a97830..59f4564 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
@@ -212,9 +212,9 @@
         if (hasFocus) {
             if (mSecurityButton.getVisibility() == VISIBLE) mSecurityButton.setVisibility(GONE);
             if (getWindowDelegate().getWindowSoftInputMode()
-                    != WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) {
+                    != WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) {
                 getWindowDelegate().setWindowSoftInputMode(
-                        WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
+                        WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
             }
             UiUtils.showKeyboard(mUrlBar);
         } else {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
index fe48f0e4..1d003270 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -108,7 +108,7 @@
 
         OmniboxTestUtils.toggleUrlBarFocus(urlBar, true);
         CriteriaHelper.pollInstrumentationThread(Criteria.equals(
-                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING, new Callable<Integer>() {
+                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN, new Callable<Integer>() {
                     @Override
                     public Integer call() {
                         return getActivity().getWindow().getAttributes().softInputMode;
diff --git a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
index c43ac5ae..2b2015211 100644
--- a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
@@ -59,6 +59,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_36:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.ParseTiming.NavigationToParseStart",
           timing.parse_timing.parse_start.value());
@@ -109,6 +110,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_36:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.PaintTiming."
           "NavigationToFirstContentfulPaint",
@@ -165,6 +167,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_36:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.Experimental.PaintTiming."
           "NavigationToFirstMeaningfulPaint",
@@ -211,6 +214,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_36:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.DocumentTiming."
           "NavigationToDOMContentLoadedEventFired",
@@ -252,6 +256,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_36:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.DocumentTiming."
           "NavigationToLoadEventFired",
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
index a455416..760db46b 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -441,9 +441,9 @@
     if (this.connectNotAllowed_(networkProperties, globalPolicy))
       return false;
     var type = networkProperties.Type;
-    if (type == CrOnc.Type.CELLULAR || type == CrOnc.Type.WI_MAX)
+    if (type == CrOnc.Type.CELLULAR)
       return false;
-    if (type == CrOnc.Type.WI_FI &&
+    if ((type == CrOnc.Type.WI_FI || type == CrOnc.Type.WI_MAX) &&
         networkProperties.ConnectionState !=
             CrOnc.ConnectionState.NOT_CONNECTED) {
       return false;
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 264ba63..7ec42c0 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -92,7 +92,7 @@
 // is created.
 void ShowHelpImpl(Browser* browser, Profile* profile, HelpSource source) {
   base::RecordAction(UserMetricsAction("ShowHelpTab"));
-#if defined(OS_CHROMEOS) && defined(OFFICIAL_BUILD)
+#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
   const extensions::Extension* extension =
       extensions::ExtensionRegistry::Get(profile)->GetExtensionById(
           genius_app::kGeniusAppId,
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h
index d98a2b9..cdbe2d1 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -65,10 +65,6 @@
 class Command;
 }
 
-namespace {
-class OmniboxPopupModelObserverBridge;
-}
-
 constexpr const gfx::Size kMinCocoaTabbedWindowSize(400, 272);
 constexpr const gfx::Size kMinCocoaPopupWindowSize(100, 122);
 
@@ -201,10 +197,6 @@
   // handle.
   std::unique_ptr<ExtensionKeybindingRegistryCocoa>
       extensionKeybindingRegistry_;
-
-  // Observes whether the omnibox popup is shown or hidden.
-  std::unique_ptr<OmniboxPopupModelObserverBridge>
-      omniboxPopupModelObserverBridge_;
 }
 
 // A convenience class method which gets the |BrowserWindowController| for a
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 13ce7a8..2fd4f20f 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -13,7 +13,6 @@
 #import "base/mac/foundation_util.h"
 #include "base/mac/mac_util.h"
 #import "base/mac/sdk_forward_declarations.h"
-#include "base/scoped_observer.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"  // IDC_*
@@ -65,7 +64,6 @@
 #import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
 #include "chrome/browser/ui/cocoa/l10n_util.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
-#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
 #include "chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa.h"
 #import "chrome/browser/ui/cocoa/profiles/avatar_base_controller.h"
 #import "chrome/browser/ui/cocoa/profiles/avatar_button_controller.h"
@@ -89,9 +87,6 @@
 #include "chrome/common/pref_names.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/managed/managed_bookmark_service.h"
-#include "components/omnibox/browser/omnibox_edit_model.h"
-#include "components/omnibox/browser/omnibox_popup_model.h"
-#include "components/omnibox/browser/omnibox_popup_model_observer.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/translate/core/browser/translate_manager.h"
 #include "components/translate/core/browser/translate_ui_delegate.h"
@@ -190,43 +185,6 @@
 
 namespace {
 
-// This class shows or hides the top arrow of the infobar in accordance with the
-// visibility of the omnibox popup. It hides the top arrow when the omnibox
-// popup is shown, and vice versa.
-class OmniboxPopupModelObserverBridge final : public OmniboxPopupModelObserver {
- public:
-  explicit OmniboxPopupModelObserverBridge(BrowserWindowController* controller)
-      : controller_(controller),
-        omnibox_popup_model_([controller_ locationBarBridge]
-                                 ->GetOmniboxView()
-                                 ->model()
-                                 ->popup_model()),
-        omnibox_popup_model_observer_(this) {
-    DCHECK(omnibox_popup_model_);
-    omnibox_popup_model_observer_.Add(omnibox_popup_model_);
-  }
-
-  void OnOmniboxPopupShownOrHidden() override {
-    int max_top_arrow_height = 0;
-    if (!omnibox_popup_model_->IsOpen()) {
-      base::scoped_nsobject<BrowserWindowLayout> layout(
-          [[BrowserWindowLayout alloc] init]);
-      [controller_ updateLayoutParameters:layout];
-      max_top_arrow_height = [layout computeLayout].infoBarMaxTopArrowHeight;
-    }
-    [[controller_ infoBarContainerController]
-        setMaxTopArrowHeight:max_top_arrow_height];
-  }
-
- private:
-  BrowserWindowController* controller_;
-  OmniboxPopupModel* omnibox_popup_model_;
-  ScopedObserver<OmniboxPopupModel, OmniboxPopupModelObserver>
-      omnibox_popup_model_observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupModelObserverBridge);
-};
-
 void SetUpBrowserWindowCommandHandler(NSWindow* window) {
   // Make the window handle browser window commands.
   [base::mac::ObjCCastStrict<ChromeEventProcessingWindow>(window)
@@ -431,9 +389,6 @@
             extensions::ExtensionKeybindingRegistry::ALL_EXTENSIONS,
             windowShim_.get()));
 
-    omniboxPopupModelObserverBridge_.reset(
-        new OmniboxPopupModelObserverBridge(self));
-
     blockLayoutSubviews_ = NO;
 
     // We are done initializing now.
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.cc b/chrome/browser/ui/webui/certificate_viewer_webui.cc
index eebe9f1..eae1c60 100644
--- a/chrome/browser/ui/webui/certificate_viewer_webui.cc
+++ b/chrome/browser/ui/webui/certificate_viewer_webui.cc
@@ -11,9 +11,12 @@
 #include "base/bind_helpers.h"
 #include "base/i18n/time_formatting.h"
 #include "base/json/json_writer.h"
+#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
 #include "chrome/browser/certificate_viewer.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/browser_dialogs.h"
@@ -30,6 +33,84 @@
 using content::WebContents;
 using content::WebUIMessageHandler;
 
+namespace {
+
+// Helper class for building a Value representation of a certificate. The class
+// gathers data for a single node of the representation tree and builds a
+// DictionaryValue out of that.
+class CertNodeBuilder {
+ public:
+  // Starts the node with "label" set to |label|.
+  explicit CertNodeBuilder(base::StringPiece label);
+
+  // Convenience version: Converts |label_id| to the corresponding resource
+  // string, then delegates to the other constructor.
+  explicit CertNodeBuilder(int label_id);
+
+  // Builder methods all return |*this| so that they can be chained in single
+  // expressions.
+
+  // Sets the "payload.val" field. Call this at most once.
+  CertNodeBuilder& Payload(base::StringPiece payload);
+
+  // Adds |child| in the list keyed "children". Can be called multiple times.
+  CertNodeBuilder& Child(std::unique_ptr<base::DictionaryValue> child);
+
+  // Similar to Child, but if the argument is null, then this does not add
+  // anything.
+  CertNodeBuilder& ChildIfNotNull(std::unique_ptr<base::DictionaryValue> child);
+
+  // Creates a DictionaryValue representation of the collected information. Only
+  // call this once.
+  std::unique_ptr<base::DictionaryValue> Build();
+
+ private:
+  base::DictionaryValue node_;
+  base::ListValue children_;
+  // |built_| is false until Build() is called. Once it is |true|, |node_| and
+  // |children_| are no longer valid for use.
+  bool built_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(CertNodeBuilder);
+};
+
+CertNodeBuilder::CertNodeBuilder(base::StringPiece label) {
+  node_.SetString("label", label);
+}
+
+CertNodeBuilder::CertNodeBuilder(int label_id)
+    : CertNodeBuilder(l10n_util::GetStringUTF8(label_id)) {}
+
+CertNodeBuilder& CertNodeBuilder::Payload(base::StringPiece payload) {
+  DCHECK(!node_.HasKey("payload.val"));
+  node_.SetString("payload.val", payload);
+  return *this;
+}
+
+CertNodeBuilder& CertNodeBuilder::Child(
+    std::unique_ptr<base::DictionaryValue> child) {
+  children_.Append(std::move(child));
+  return *this;
+}
+
+CertNodeBuilder& CertNodeBuilder::ChildIfNotNull(
+    std::unique_ptr<base::DictionaryValue> child) {
+  if (child)
+    return Child(std::move(child));
+  return *this;
+}
+
+std::unique_ptr<base::DictionaryValue> CertNodeBuilder::Build() {
+  DCHECK(!built_);
+  if (!children_.empty()) {
+    node_.Set("children", base::MakeUnique<base::Value>(std::move(children_)));
+  }
+  built_ = true;
+  return base::MakeUnique<base::DictionaryValue>(std::move(node_));
+}
+
+}  // namespace
+
 // Shows a certificate using the WebUI certificate viewer.
 void ShowCertificateViewer(WebContents* web_contents,
                            gfx::NativeWindow parent,
@@ -169,7 +250,7 @@
       x509_certificate_model::HashCertSHA1(cert_hnd));
 
   // Certificate hierarchy is constructed from bottom up.
-  base::ListValue* children = NULL;
+  std::unique_ptr<base::ListValue> children;
   int index = 0;
   for (net::X509Certificate::OSCertHandles::const_iterator i =
       cert_chain.begin(); i != cert_chain.end(); ++i, ++index) {
@@ -180,14 +261,14 @@
     cert_node->SetDouble("payload.index", index);
     // Add the child from the previous iteration.
     if (children)
-      cert_node->Set("children", children);
+      cert_node->Set("children", std::move(children));
 
     // Add this node to the children list for the next iteration.
-    children = new base::ListValue();
+    children = base::MakeUnique<base::ListValue>();
     children->Append(std::move(cert_node));
   }
   // Set the last node as the top of the certificate hierarchy.
-  cert_info.Set("hierarchy", children);
+  cert_info.Set("hierarchy", std::move(children));
 
   base::JSONWriter::Write(cert_info, &data);
 
@@ -291,181 +372,115 @@
 
   net::X509Certificate::OSCertHandle cert = cert_chain_[cert_index];
 
-  // Main certificate fields.
-  auto cert_fields = base::MakeUnique<base::ListValue>();
-  auto node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VERSION));
+  CertNodeBuilder version_node(IDS_CERT_DETAILS_VERSION);
   std::string version = x509_certificate_model::GetVersion(cert);
   if (!version.empty()) {
-    node_details->SetString("payload.val",
-        l10n_util::GetStringFUTF8(IDS_CERT_DETAILS_VERSION_FORMAT,
-                                  base::UTF8ToUTF16(version)));
+    version_node.Payload(l10n_util::GetStringFUTF8(
+        IDS_CERT_DETAILS_VERSION_FORMAT, base::UTF8ToUTF16(version)));
   }
-  cert_fields->Append(std::move(node_details));
 
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SERIAL_NUMBER));
-  node_details->SetString("payload.val",
-      x509_certificate_model::GetSerialNumberHexified(cert,
-          l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT)));
-  cert_fields->Append(std::move(node_details));
-
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG));
-  node_details->SetString("payload.val",
-      x509_certificate_model::ProcessSecAlgorithmSignature(cert));
-  cert_fields->Append(std::move(node_details));
-
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_ISSUER));
-  node_details->SetString("payload.val",
-      x509_certificate_model::GetIssuerName(cert));
-  cert_fields->Append(std::move(node_details));
-
-  // Validity period.
-  auto cert_sub_fields = base::MakeUnique<base::ListValue>();
-
-  auto sub_node_details = base::MakeUnique<base::DictionaryValue>();
-  sub_node_details->SetString(
-      "label", l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_BEFORE));
-
-  auto alt_node_details = base::MakeUnique<base::DictionaryValue>();
-  alt_node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_AFTER));
-
+  CertNodeBuilder issued_node_builder(IDS_CERT_DETAILS_NOT_BEFORE);
+  CertNodeBuilder expires_node_builder(IDS_CERT_DETAILS_NOT_AFTER);
   base::Time issued, expires;
   if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
-    sub_node_details->SetString(
-        "payload.val",
-        base::UTF16ToUTF8(
-            base::TimeFormatShortDateAndTimeWithTimeZone(issued)));
-    alt_node_details->SetString(
-        "payload.val",
-        base::UTF16ToUTF8(
-            base::TimeFormatShortDateAndTimeWithTimeZone(expires)));
+    issued_node_builder.Payload(base::UTF16ToUTF8(
+        base::TimeFormatShortDateAndTimeWithTimeZone(issued)));
+    expires_node_builder.Payload(base::UTF16ToUTF8(
+        base::TimeFormatShortDateAndTimeWithTimeZone(expires)));
   }
-  cert_sub_fields->Append(std::move(sub_node_details));
-  cert_sub_fields->Append(std::move(alt_node_details));
 
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-                          l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VALIDITY));
-  node_details->Set("children", std::move(cert_sub_fields));
-  cert_fields->Append(std::move(node_details));
-
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT));
-  node_details->SetString("payload.val",
-      x509_certificate_model::GetSubjectName(cert));
-  cert_fields->Append(std::move(node_details));
-
-  // Subject key information.
-  cert_sub_fields = base::MakeUnique<base::ListValue>();
-
-  sub_node_details = base::MakeUnique<base::DictionaryValue>();
-  sub_node_details->SetString(
-      "label", l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_ALG));
-  sub_node_details->SetString(
-      "payload.val",
-      x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(cert));
-  cert_sub_fields->Append(std::move(sub_node_details));
-
-  sub_node_details = base::MakeUnique<base::DictionaryValue>();
-  sub_node_details->SetString(
-      "label", l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY));
-  sub_node_details->SetString(
-      "payload.val", x509_certificate_model::ProcessSubjectPublicKeyInfo(cert));
-  cert_sub_fields->Append(std::move(sub_node_details));
-
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString(
-      "label", l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_INFO));
-  node_details->Set("children", std::move(cert_sub_fields));
-  cert_fields->Append(std::move(node_details));
-
-  // Extensions.
   x509_certificate_model::Extensions extensions;
   x509_certificate_model::GetExtensions(
       l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_CRITICAL),
       l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_NON_CRITICAL),
       cert, &extensions);
 
+  std::unique_ptr<base::DictionaryValue> details_extensions;
   if (!extensions.empty()) {
-    cert_sub_fields = base::MakeUnique<base::ListValue>();
-
-    for (x509_certificate_model::Extensions::const_iterator i =
-         extensions.begin(); i != extensions.end(); ++i) {
-      sub_node_details = base::MakeUnique<base::DictionaryValue>();
-      sub_node_details->SetString("label", i->name);
-      sub_node_details->SetString("payload.val", i->value);
-      cert_sub_fields->Append(std::move(sub_node_details));
+    CertNodeBuilder details_extensions_builder(IDS_CERT_DETAILS_EXTENSIONS);
+    for (const x509_certificate_model::Extension& extension : extensions) {
+      details_extensions_builder.Child(
+          CertNodeBuilder(extension.name).Payload(extension.value).Build());
     }
-
-    node_details = base::MakeUnique<base::DictionaryValue>();
-    node_details->SetString(
-        "label", l10n_util::GetStringUTF8(IDS_CERT_DETAILS_EXTENSIONS));
-    node_details->Set("children", std::move(cert_sub_fields));
-    cert_fields->Append(std::move(node_details));
+    details_extensions = details_extensions_builder.Build();
   }
 
-  // Details certificate information.
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG));
-  node_details->SetString("payload.val",
-      x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert));
-  cert_fields->Append(std::move(node_details));
-
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label",
-      l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE));
-  node_details->SetString("payload.val",
-      x509_certificate_model::ProcessRawBitsSignatureWrap(cert));
-  cert_fields->Append(std::move(node_details));
-
-  // Fingerprint information.
-  cert_sub_fields = base::MakeUnique<base::ListValue>();
-
-  sub_node_details = base::MakeUnique<base::DictionaryValue>();
-  sub_node_details->SetString(
-      "label",
-      l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL));
-  sub_node_details->SetString("payload.val",
-                              x509_certificate_model::HashCertSHA256(cert));
-  cert_sub_fields->Append(std::move(sub_node_details));
-
-  sub_node_details = base::MakeUnique<base::DictionaryValue>();
-  sub_node_details->SetString(
-      "label", l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL));
-  sub_node_details->SetString("payload.val",
-                              x509_certificate_model::HashCertSHA1(cert));
-  cert_sub_fields->Append(std::move(sub_node_details));
-
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString(
-      "label", l10n_util::GetStringUTF8(IDS_CERT_INFO_FINGERPRINTS_GROUP));
-  node_details->Set("children", std::move(cert_sub_fields));
-  cert_fields->Append(std::move(node_details));
-
-  // Certificate information.
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString(
-      "label", l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE));
-  node_details->Set("children", std::move(cert_fields));
-  cert_fields = base::MakeUnique<base::ListValue>();
-  cert_fields->Append(std::move(node_details));
-
-  // Top level information.
   base::ListValue root_list;
-  node_details = base::MakeUnique<base::DictionaryValue>();
-  node_details->SetString("label", x509_certificate_model::GetTitle(cert));
-  node_details->Set("children", std::move(cert_fields));
-  root_list.Append(std::move(node_details));
+  root_list.Append(
+      CertNodeBuilder(x509_certificate_model::GetTitle(cert))
+          .Child(
+              CertNodeBuilder(
+                  l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE))
+                  // Main certificate fields.
+                  .Child(version_node.Build())
+                  .Child(
+                      CertNodeBuilder(IDS_CERT_DETAILS_SERIAL_NUMBER)
+                          .Payload(
+                              x509_certificate_model::GetSerialNumberHexified(
+                                  cert, l10n_util::GetStringUTF8(
+                                            IDS_CERT_INFO_FIELD_NOT_PRESENT)))
+                          .Build())
+                  .Child(CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG)
+                             .Payload(x509_certificate_model::
+                                          ProcessSecAlgorithmSignature(cert))
+                             .Build())
+                  .Child(
+                      CertNodeBuilder(IDS_CERT_DETAILS_ISSUER)
+                          .Payload(x509_certificate_model::GetIssuerName(cert))
+                          .Build())
+                  // Validity period.
+                  .Child(CertNodeBuilder(IDS_CERT_DETAILS_VALIDITY)
+                             .Child(issued_node_builder.Build())
+                             .Child(expires_node_builder.Build())
+                             .Build())
+                  .Child(
+                      CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT)
+                          .Payload(x509_certificate_model::GetSubjectName(cert))
+                          .Build())
+                  // Subject key information.
+                  .Child(
+                      CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY_INFO)
+                          .Child(
+                              CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY_ALG)
+                                  .Payload(
+                                      x509_certificate_model::
+                                          ProcessSecAlgorithmSubjectPublicKey(
+                                              cert))
+                                  .Build())
+                          .Child(CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY)
+                                     .Payload(
+                                         x509_certificate_model::
+                                             ProcessSubjectPublicKeyInfo(cert))
+                                     .Build())
+                          .Build())
+                  // Extensions.
+                  .ChildIfNotNull(std::move(details_extensions))
+                  .Child(
+                      CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG)
+                          .Payload(x509_certificate_model::
+                                       ProcessSecAlgorithmSignatureWrap(cert))
+                          .Build())
+                  .Child(CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE)
+                             .Payload(x509_certificate_model::
+                                          ProcessRawBitsSignatureWrap(cert))
+                             .Build())
+                  .Child(
+                      CertNodeBuilder(IDS_CERT_INFO_FINGERPRINTS_GROUP)
+                          .Child(CertNodeBuilder(
+                                     IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL)
+                                     .Payload(
+                                         x509_certificate_model::HashCertSHA256(
+                                             cert))
+                                     .Build())
+                          .Child(
+                              CertNodeBuilder(
+                                  IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL)
+                                  .Payload(x509_certificate_model::HashCertSHA1(
+                                      cert))
+                                  .Build())
+                          .Build())
+                  .Build())
+          .Build());
 
   // Send certificate information to javascript.
   web_ui()->CallJavascriptFunctionUnsafe("cert_viewer.getCertificateFields",
diff --git a/components/domain_reliability/quic_error_mapping.cc b/components/domain_reliability/quic_error_mapping.cc
index 56d3c76..41283a5 100644
--- a/components/domain_reliability/quic_error_mapping.cc
+++ b/components/domain_reliability/quic_error_mapping.cc
@@ -126,8 +126,6 @@
     // Disabled QUIC because of too many PUBLIC_RESETs post handshake.
     {net::QUIC_PUBLIC_RESETS_POST_HANDSHAKE,
      "quic.public_resets_post_handshake"},
-    // Disabled QUIC because of too many timeouts with streams open.
-    {net::QUIC_TIMEOUTS_WITH_OPEN_STREAMS, "quic.timeouts_with_open_streams"},
     // Closed because we failed to serialize a packet.
     {net::QUIC_FAILED_TO_SERIALIZE_PACKET, "quic.failed_to_serialize_packet"},
     // QUIC timed out after too many RTOs.
@@ -253,7 +251,7 @@
 
 // Must be updated any time a net::QuicErrorCode is deprecated in
 // net/quic/core/quic_packets.h.
-const int kDeprecatedQuicErrorCount = 4;
+const int kDeprecatedQuicErrorCount = 5;
 const int kActiveQuicErrorCount =
     net::QUIC_LAST_ERROR - kDeprecatedQuicErrorCount;
 
diff --git a/components/domain_reliability/util.cc b/components/domain_reliability/util.cc
index 517b304d..1b3431a0 100644
--- a/components/domain_reliability/util.cc
+++ b/components/domain_reliability/util.cc
@@ -126,6 +126,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_36:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
       return "QUIC";
     case net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 85a41b8..88ef494 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -1558,7 +1558,15 @@
   if (!widget_ || !surface_)
     return;
   aura::Window* window = widget_->GetNativeWindow();
-  if (!shadow_enabled_) {
+
+  bool underlay_capture_events =
+      WMHelper::GetInstance()->IsSpokenFeedbackEnabled() && widget_->IsActive();
+  bool black_background_enabled =
+      ((widget_->IsFullscreen() || widget_->IsMaximized()) ||
+       underlay_capture_events) &&
+      ash::wm::GetWindowState(window)->allow_set_bounds_direct() &&
+      window->layer()->GetTargetTransform().IsIdentity();
+  if (!shadow_enabled_ && !black_background_enabled) {
     wm::SetShadowElevation(window, wm::ShadowElevation::NONE);
     if (shadow_underlay_)
       shadow_underlay_->Hide();
@@ -1626,10 +1634,6 @@
       }
     }
 
-    bool underlay_capture_events =
-        WMHelper::GetInstance()->IsSpokenFeedbackEnabled() &&
-        widget_->IsActive();
-
     float shadow_underlay_opacity = shadow_background_opacity_;
 
     // Put the black background layer behind the window if
@@ -1639,10 +1643,7 @@
     //    thus the background can be visible).
     // 3) the window has no transform (the transformed background may
     //    not cover the entire background, e.g. overview mode).
-    if ((widget_->IsFullscreen() || widget_->IsMaximized() ||
-         underlay_capture_events) &&
-        ash::wm::GetWindowState(window)->allow_set_bounds_direct() &&
-        window->layer()->GetTargetTransform().IsIdentity()) {
+    if (black_background_enabled) {
       if (shadow_underlay_in_surface_) {
         shadow_underlay_bounds = gfx::Rect(surface_->window()->bounds().size());
       } else {
@@ -1657,6 +1658,8 @@
     if (!shadow_underlay_in_surface_)
       shadow_underlay_bounds = shadow_bounds;
 
+    shadow_underlay_->SetBounds(shadow_underlay_bounds);
+
     // Constrain the underlay bounds to the client area in case shell surface
     // frame is enabled.
     if (frame_enabled_) {
@@ -1664,15 +1667,12 @@
           widget_->non_client_view()->frame_view()->GetBoundsForClientView());
     }
 
-    shadow_underlay_->SetBounds(shadow_underlay_bounds);
-
     // TODO(oshima): Setting to the same value should be no-op.
     // crbug.com/642223.
     if (shadow_underlay_opacity !=
         shadow_underlay_->layer()->GetTargetOpacity()) {
       shadow_underlay_->layer()->SetOpacity(shadow_underlay_opacity);
     }
-
     shadow_underlay_->Show();
 
     wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window);
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc
index d590cbb..d88d546 100644
--- a/components/exo/shell_surface_unittest.cc
+++ b/components/exo/shell_surface_unittest.cc
@@ -832,6 +832,20 @@
   ASSERT_TRUE(shell_surface->shadow_underlay());
   EXPECT_TRUE(shell_surface->shadow_underlay()->IsVisible());
 
+  shell_surface->SetRectangularSurfaceShadow(gfx::Rect(0, 0, 0, 0));
+  // Underlay should be created even without shadow.
+  ASSERT_TRUE(shell_surface->shadow_underlay());
+  EXPECT_TRUE(shell_surface->shadow_underlay()->IsVisible());
+  shell_surface->SetRectangularShadowEnabled(false);
+  surface->Commit();
+  // Underlay should be created even without shadow.
+  ASSERT_TRUE(shell_surface->shadow_underlay());
+  EXPECT_TRUE(shell_surface->shadow_underlay()->IsVisible());
+
+  shell_surface->SetRectangularShadowEnabled(true);
+  shell_surface->SetRectangularSurfaceShadow(gfx::Rect(10, 10, 100, 100));
+  surface->Commit();
+
   // Restore the window and make sure the shadow is created, visible and
   // has the latest bounds.
   widget->Restore();
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index b4d13ee..f572bb6 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -169,7 +169,7 @@
 
   if (has_transparent_background) {
     attributes.alpha_size = 8;
-  } else if (base::SysInfo::IsLowEndDevice()) {
+  } else if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) {
     // In this case we prefer to use RGB565 format instead of RGBA8888 if
     // possible.
     // TODO(danakj): GpuCommandBufferStub constructor checks for alpha == 0 in
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index ed8514c2..7bffa0d 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -418,7 +418,8 @@
 
     // RGBA_4444 textures are only enabled by default for low end devices
     // and are disabled for Android WebView as it doesn't support the format.
-    if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures))
+    if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures) &&
+        base::SysInfo::AmountOfPhysicalMemoryMB() <= 512)
       settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
   } else {
     // On other devices we have increased memory excessively to avoid
@@ -550,21 +551,20 @@
   if (actual.bytes_limit_when_visible == 0) {
     // NOTE: Non-low-end devices use only 50% of these limits,
     // except during 'emergencies' where 100% can be used.
-    if (!base::SysInfo::IsLowEndDevice()) {
-      if (physical_memory_mb >= 1536)
-        actual.bytes_limit_when_visible = physical_memory_mb / 8;  // >192MB
-      else if (physical_memory_mb >= 1152)
-        actual.bytes_limit_when_visible = physical_memory_mb / 8;  // >144MB
-      else if (physical_memory_mb >= 768)
-        actual.bytes_limit_when_visible = physical_memory_mb / 10;  // >76MB
-      else
-        actual.bytes_limit_when_visible = physical_memory_mb / 12;  // <64MB
-    } else {
-      // Low-end devices have 512MB or less memory by definition
-      // so we hard code the limit rather than relying on the heuristics
-      // above. Low-end devices use 4444 textures so we can use a lower limit.
+    if (physical_memory_mb >= 1536)
+      actual.bytes_limit_when_visible = physical_memory_mb / 8;  // >192MB
+    else if (physical_memory_mb >= 1152)
+      actual.bytes_limit_when_visible = physical_memory_mb / 8;  // >144MB
+    else if (physical_memory_mb >= 768)
+      actual.bytes_limit_when_visible = physical_memory_mb / 10;  // >76MB
+    else if (physical_memory_mb >= 513)
+      actual.bytes_limit_when_visible = physical_memory_mb / 12;  // <64MB
+    else
+      // Devices with this little RAM have very little headroom so we hardcode
+      // the limit rather than relying on the heuristics above.  (They also use
+      // 4444 textures so we can use a lower limit.)
       actual.bytes_limit_when_visible = 8;
-    }
+
     actual.bytes_limit_when_visible =
         actual.bytes_limit_when_visible * 1024 * 1024;
     // Clamp the observed value to a specific range on Android.
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.cc b/content/renderer/media/renderer_webmediaplayer_delegate.cc
index 08b4e70..99d76f6 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -38,14 +38,12 @@
   idle_cleanup_interval_ = base::TimeDelta::FromSeconds(5);
   idle_timeout_ = base::TimeDelta::FromSeconds(15);
 
-  // Idle players time out more aggressively on low end devices.
-  is_low_end_device_ = base::SysInfo::IsLowEndDevice();
+  is_jelly_bean_ = false;
 
 #if defined(OS_ANDROID)
   // On Android, due to the instability of the OS level media components, we
-  // consider all pre-KitKat devices to be low end.
-  is_low_end_device_ |=
-      base::android::BuildInfo::GetInstance()->sdk_int() <= 18;
+  // consider all pre-KitKat devices to be potentially buggy.
+  is_jelly_bean_ |= base::android::BuildInfo::GetInstance()->sdk_int() <= 18;
 #endif
 }
 
@@ -209,11 +207,11 @@
 void RendererWebMediaPlayerDelegate::SetIdleCleanupParamsForTesting(
     base::TimeDelta idle_timeout,
     base::TickClock* tick_clock,
-    bool is_low_end_device) {
+    bool is_jelly_bean) {
   idle_cleanup_interval_ = base::TimeDelta();
   idle_timeout_ = idle_timeout;
   tick_clock_ = tick_clock;
-  is_low_end_device_ = is_low_end_device;
+  is_jelly_bean_ = is_jelly_bean;
 }
 
 bool RendererWebMediaPlayerDelegate::IsIdleCleanupTimerRunningForTesting()
@@ -311,12 +309,12 @@
   // When we reach the maximum number of idle players, clean them up
   // aggressively. Values chosen after testing on a Galaxy Nexus device for
   // http://crbug.com/612909.
-  if (idle_player_map_.size() > (is_low_end_device_ ? 2u : 8u))
+  if (idle_player_map_.size() > (is_jelly_bean_ ? 2u : 8u))
     aggressive_cleanup = true;
 
-  // When a player plays on a low-end device, clean up idle players
+  // When a player plays on a buggy old device, clean up idle players
   // aggressively.
-  if (has_played_video_since_last_update_task && is_low_end_device_)
+  if (has_played_video_since_last_update_task && is_jelly_bean_)
     aggressive_cleanup = true;
 
   CleanUpIdlePlayers(aggressive_cleanup ? base::TimeDelta() : idle_timeout_);
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.h b/content/renderer/media/renderer_webmediaplayer_delegate.h
index 46886e8..de7f7ed 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -66,11 +66,11 @@
   void OnDestruct() override;
 
   // Zeros out |idle_cleanup_interval_|, sets |idle_timeout_| to |idle_timeout|,
-  // and |is_low_end_device_| to |is_low_end_device|. A zero cleanup interval
+  // and |is_jelly_bean_| to |is_jelly_bean|. A zero cleanup interval
   // will cause the idle timer to run with each run of the message loop.
   void SetIdleCleanupParamsForTesting(base::TimeDelta idle_timeout,
                                       base::TickClock* tick_clock,
-                                      bool is_low_end_device);
+                                      bool is_jelly_bean);
   bool IsIdleCleanupTimerRunningForTesting() const;
 
   // Note: Does not call OnFrameHidden()/OnFrameShown().
@@ -145,7 +145,7 @@
 
   // Determined at construction time based on system information; determines
   // when the idle cleanup timer should be fired more aggressively.
-  bool is_low_end_device_;
+  bool is_jelly_bean_;
 
   DISALLOW_COPY_AND_ASSIGN(RendererWebMediaPlayerDelegate);
 };
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 7d6113c..b8c4c05 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1037,15 +1037,13 @@
   settings->SetPreferHiddenVolumeControls(true);
   settings->SetSpellCheckEnabledByDefault(prefs.spellcheck_enabled_by_default);
 
-  // Force preload=none and disable autoplay on older or low end Android
+  // Force preload=none and disable autoplay on older Android
   // platforms because their media pipelines are not stable enough to handle
   // concurrent elements. See http://crbug.com/612909, http://crbug.com/622826.
-  const bool is_low_end_device =
+  const bool is_jelly_bean =
       base::android::BuildInfo::GetInstance()->sdk_int() <=
-          base::android::SDK_VERSION_JELLY_BEAN_MR2 ||
-      base::SysInfo::IsLowEndDevice();
-  // TODO(mlamouri): rename this setting "isLowEndDevice".
-  settings->SetForcePreloadNoneForMediaElements(is_low_end_device);
+      base::android::SDK_VERSION_JELLY_BEAN_MR2;
+  settings->SetForcePreloadNoneForMediaElements(is_jelly_bean);
 
   WebRuntimeFeatures::EnableVideoFullscreenOrientationLock(
       prefs.video_fullscreen_orientation_lock_enabled);
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index 5d85784..6228c9a 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -495,13 +495,13 @@
       'pixel_video_mp4.html',
       base_name + '_DirectComposition_Video_MP4',
       test_rect=[0, 0, 300, 300],
-      revision=1,
+      revision=2,
       browser_args=browser_args),
 
     PixelTestPage(
       'pixel_video_vp9.html',
       base_name + '_DirectComposition_Video_VP9',
       test_rect=[0, 0, 300, 300],
-      revision=1,
+      revision=2,
       browser_args=browser_args),
   ]
diff --git a/gpu/config/BUILD.gn b/gpu/config/BUILD.gn
index f8d7af0..1a980af 100644
--- a/gpu/config/BUILD.gn
+++ b/gpu/config/BUILD.gn
@@ -55,7 +55,19 @@
     "--output-dir",
     rebase_path("$target_gen_dir", root_build_dir),
     "--skip-testing-data",
+    "--os-filter",
   ]
+  if (is_win) {
+    args += [ "win" ]
+  } else if (is_mac) {
+    args += [ "macosx" ]
+  } else if (is_android) {
+    args += [ "android" ]
+  } else if (is_chromeos) {
+    args += [ "chromeos" ]
+  } else {
+    args += [ "linux" ]
+  }
 }
 
 source_set("config_sources") {
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index fe5d306c0b..a7399a4c 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -2365,7 +2365,6 @@
     }
   ],
   "comment": [
-    "Please update the version number on top whenever you change this file",
-    "Please run gpu/config/process_json.py whenever you change this file"
+    "Please update the version number on top whenever you change this file"
   ]
 }
diff --git a/gpu/config/gpu_driver_bug_list_unittest.cc b/gpu/config/gpu_driver_bug_list_unittest.cc
index 5ed55ec..99cbe08e5 100644
--- a/gpu/config/gpu_driver_bug_list_unittest.cc
+++ b/gpu/config/gpu_driver_bug_list_unittest.cc
@@ -16,6 +16,7 @@
   ~GpuDriverBugListTest() override {}
 };
 
+#if defined(OS_ANDROID)
 TEST_F(GpuDriverBugListTest, CurrentListForARM) {
   std::unique_ptr<GpuDriverBugList> list = GpuDriverBugList::Create();
   GPUInfo gpu_info;
@@ -35,6 +36,7 @@
       GpuControlList::kOsAndroid, "4.1", gpu_info);
   EXPECT_EQ(1u, bugs.count(USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS));
 }
+#endif  // OS_ANDROID
 
 TEST_F(GpuDriverBugListTest, AppendSingleWorkaround) {
   base::CommandLine command_line(0, NULL);
diff --git a/gpu/config/process_json.py b/gpu/config/process_json.py
index 05ec4a2..648fb06 100755
--- a/gpu/config/process_json.py
+++ b/gpu/config/process_json.py
@@ -500,7 +500,7 @@
 
 
 def write_entry(entry, total_feature_set, feature_name_prefix,
-                  data_file, data_helper_file, data_exception_file):
+                data_file, data_helper_file, data_exception_file):
   data_file.write('{\n')
   # ID
   entry_id = entry['id']
@@ -582,7 +582,7 @@
                       feature_header_filename, total_features, feature_tag,
                       output_header_filepath, output_data_filepath,
                       output_helper_filepath, output_exception_filepath, path,
-                      export_tag, git_format):
+                      export_tag, git_format, os_filter):
   output_header_filename = os.path.basename(output_header_filepath)
   output_helper_filename = os.path.basename(output_helper_filepath)
   output_exception_filename = os.path.basename(output_exception_filepath)
@@ -611,20 +611,22 @@
   data_file.write('namespace gpu {\n\n')
   data_file.write('const char k%sVersion[] = "%s";\n\n' %
                   (list_tag, json_data['version']))
-  entry_count = len(json_data['entries'])
-  data_file.write('const size_t k%sEntryCount = %d;\n' %
-                  (list_tag, entry_count))
-  data_file.write('const GpuControlList::Entry k%sEntries[%d] = {\n' %
-                  (list_tag, entry_count))
+  data_file.write('const GpuControlList::Entry k%sEntries[] = {\n' % list_tag)
   ids = []
-  for index in range(entry_count):
+  entry_count = 0
+  for index in range(len(json_data['entries'])):
     entry = json_data['entries'][index]
     entry_id = entry['id']
     assert entry_id not in ids
     ids.append(entry_id)
+    if os_filter != None and 'os' in entry and entry['os']['type'] != os_filter:
+      continue
+    entry_count += 1
     write_entry(entry, total_features, feature_tag,
                 data_file, data_helper_file, data_exception_file)
   data_file.write('};\n')
+  data_file.write('const size_t k%sEntryCount = %d;\n' %
+                  (list_tag, entry_count))
   data_file.write('}  // namespace gpu\n')
   data_file.close()
   data_helper_file.write('}  // namespace gpu\n')
@@ -658,7 +660,7 @@
                   output_helper_filepath, output_exception_filepath])
 
 
-def process_software_rendering_list(script_dir, output_dir):
+def process_software_rendering_list(script_dir, output_dir, os_filter):
   total_features = load_software_rendering_list_features(
       os.path.join(script_dir, 'gpu_feature_type.h'))
   process_json_file(
@@ -674,10 +676,11 @@
       os.path.join(output_dir, 'software_rendering_list_exceptions_autogen.h'),
       'gpu/config',
       'GPU_EXPORT ',
-      False)
+      False,
+      os_filter)
 
 
-def process_gpu_driver_bug_list(script_dir, output_dir):
+def process_gpu_driver_bug_list(script_dir, output_dir, os_filter):
   total_features = load_gpu_driver_bug_workarounds(
       os.path.join(script_dir, 'gpu_driver_bug_workaround_type.h'))
   process_json_file(
@@ -693,7 +696,8 @@
       os.path.join(output_dir, 'gpu_driver_bug_list_exceptions_autogen.h'),
       'gpu/config',
       'GPU_EXPORT ',
-      False)
+      False,
+      os_filter)
 
 
 def process_gpu_control_list_testing(script_dir, output_dir):
@@ -711,7 +715,8 @@
       os.path.join(output_dir, 'gpu_control_list_testing_exceptions_autogen.h'),
       'gpu/config',
       '',
-      True)
+      True,
+      None)
 
 
 def process_gpu_data_manager_testing(script_dir, output_dir):
@@ -730,7 +735,8 @@
       os.path.join(output_dir, 'gpu_data_manager_testing_exceptions_autogen.h'),
       'content/browser/gpu',
       '',
-      True)
+      True,
+      None)
 
 
 def write_test_entry_enums(input_json_filepath, output_entry_enums_filepath,
@@ -771,13 +777,17 @@
   parser.add_option("--skip-testing-data", action="store_false",
                     dest="generate_testing_data", default=True,
                     help="skip testing data generation.")
+  parser.add_option("--os-filter",
+                    help="only output entries applied to the specified os.")
   (options, args) = parser.parse_args(args=argv)
 
   script_dir = os.path.dirname(os.path.realpath(__file__))
 
   if options.output_dir != None:
-    process_software_rendering_list(script_dir, options.output_dir)
-    process_gpu_driver_bug_list(script_dir, options.output_dir)
+    process_software_rendering_list(
+        script_dir, options.output_dir, options.os_filter)
+    process_gpu_driver_bug_list(
+        script_dir, options.output_dir, options.os_filter)
 
   if options.generate_testing_data:
     # Testing data files are generated by calling the script manually.
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json
index 43709fe..f3e6a67 100644
--- a/gpu/config/software_rendering_list.json
+++ b/gpu/config/software_rendering_list.json
@@ -1497,7 +1497,6 @@
     }
   ],
   "comment": [
-    "Please update the version number on top whenever you change this file",
-    "Please run gpu/config/process_json.py whenever you change this file"
+    "Please update the version number on top whenever you change this file"
   ]
 }
diff --git a/ios/chrome/browser/metrics/BUILD.gn b/ios/chrome/browser/metrics/BUILD.gn
index e79fa22..23a0d1d 100644
--- a/ios/chrome/browser/metrics/BUILD.gn
+++ b/ios/chrome/browser/metrics/BUILD.gn
@@ -15,8 +15,8 @@
     "ios_chrome_metrics_services_manager_client.mm",
     "ios_chrome_origins_seen_service_factory.cc",
     "ios_chrome_origins_seen_service_factory.h",
-    "ios_chrome_stability_metrics_provider.cc",
     "ios_chrome_stability_metrics_provider.h",
+    "ios_chrome_stability_metrics_provider.mm",
     "mobile_session_shutdown_metrics_provider.h",
     "mobile_session_shutdown_metrics_provider.mm",
     "previous_session_info.h",
diff --git a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h
index 155e59f8..9389c0a 100644
--- a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h
+++ b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h
@@ -29,6 +29,7 @@
 
   // web::GlobalWebStateObserver:
   void WebStateDidStartLoading(web::WebState* web_state) override;
+  void RenderProcessGone(web::WebState* web_state) override;
 
   // Records a renderer process crash.
   void LogRendererCrash();
diff --git a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.cc b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.mm
similarity index 82%
rename from ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.cc
rename to ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.mm
index c7c22b0..09db12b5 100644
--- a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.cc
+++ b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.mm
@@ -4,6 +4,8 @@
 
 #include "ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h"
 
+#import "ios/web/public/web_state/web_state.h"
+
 IOSChromeStabilityMetricsProvider::IOSChromeStabilityMetricsProvider(
     PrefService* local_state)
     : helper_(local_state), recording_enabled_(false) {}
@@ -47,3 +49,12 @@
 
   helper_.LogLoadStarted();
 }
+
+void IOSChromeStabilityMetricsProvider::RenderProcessGone(
+    web::WebState* web_state) {
+  if (!recording_enabled_)
+    return;
+  LogRendererCrash();
+  // TODO(crbug.com/685649): web_state->GetLastCommittedURL() is likely the URL
+  // that caused a renderer crash and can be logged here.
+}
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h
index 8c87b026..bd4b5aa 100644
--- a/ios/chrome/browser/tabs/tab.h
+++ b/ios/chrome/browser/tabs/tab.h
@@ -106,6 +106,12 @@
 // Do not add new calls to this method.
 @property(nonatomic, readonly) const GURL& url;
 
+// Returns the URL of the last committed NavigationItem for this Tab.
+@property(nonatomic, readonly) const GURL& lastCommittedURL;
+
+// Returns the URL of the visible NavigationItem for this Tab.
+@property(nonatomic, readonly) const GURL& visibleURL;
+
 // The Passkit Dialog provider used to show the UI to download a passkit object.
 @property(nonatomic, assign) id<PassKitDialogProvider> passKitDialogProvider;
 
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
index 7fa0dbb..f6f011d 100644
--- a/ios/chrome/browser/tabs/tab.mm
+++ b/ios/chrome/browser/tabs/tab.mm
@@ -631,7 +631,17 @@
 - (const GURL&)url {
   // See note in header; this method should be removed.
   web::NavigationItem* item =
-      [[self navigationManagerImpl]->GetSessionController() currentItem];
+      [self navigationManagerImpl]->GetSessionController().currentItem;
+  return item ? item->GetVirtualURL() : GURL::EmptyGURL();
+}
+
+- (const GURL&)lastCommittedURL {
+  web::NavigationItem* item = self.navigationManager->GetLastCommittedItem();
+  return item ? item->GetVirtualURL() : GURL::EmptyGURL();
+}
+
+- (const GURL&)visibleURL {
+  web::NavigationItem* item = self.navigationManager->GetVisibleItem();
   return item ? item->GetVirtualURL() : GURL::EmptyGURL();
 }
 
@@ -1367,9 +1377,6 @@
 }
 
 - (void)reloadWithUserAgentType:(web::UserAgentType)userAgentType {
-  // This removes the web view, which will be recreated at the end of this.
-  [self.webController requirePageReconstruction];
-
   // TODO(crbug.com/228171): A hack in session_controller -addPendingItem
   // discusses making tab responsible for distinguishing history stack
   // navigation from new navigations.
@@ -1805,11 +1812,6 @@
   UIApplicationState state = [UIApplication sharedApplication].applicationState;
   BOOL applicationIsNotActive = IsApplicationStateNotActive(state);
   if (browserState_ && !browserState_->IsOffTheRecord()) {
-    // Report the crash.
-    GetApplicationContext()
-        ->GetMetricsServicesManager()
-        ->OnRendererProcessCrash();
-
     // Log the tab state for the termination.
     RendererTerminationTabState tab_state =
         visible_ ? RendererTerminationTabState::FOREGROUND_TAB_FOREGROUND_APP
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h
index b770627..0b227410 100644
--- a/ios/web/web_state/ui/crw_web_controller.h
+++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -191,14 +191,6 @@
 // Dismisses the soft keyboard.
 - (void)dismissKeyboard;
 
-// Requires that the next load rebuild the UIWebView. This is expensive, and
-// should be used only in the case where something has changed that UIWebView
-// only checks on creation, such that the whole object needs to be rebuilt.
-// TODO(stuartmorgan): Merge this and reinitializeWebViewAndReload:. They are
-// currently subtly different in terms of implementation, but are for
-// fundamentally the same purpose.
-- (void)requirePageReconstruction;
-
 - (void)reinitializeWebViewAndReload:(BOOL)reload;
 
 // Requires that the next display reload the page, using a placeholder while
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index ddd1677..a11db2c 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -135,6 +135,23 @@
 // Key of UMA IOSFix.ViewportZoomBugCount histogram.
 const char kUMAViewportZoomBugCount[] = "Renderer.ViewportZoomBugCount";
 
+// Key of the UMA Navigation.IOSWKWebViewSlowFastBackForward histogram.
+const char kUMAWKWebViewSlowFastBackForwardNavigationKey[] =
+    "Navigation.IOSWKWebViewSlowFastBackForward";
+
+// Values for the histogram that counts slow/fast back/forward navigations.
+enum class BackForwardNavigationType {
+  // Fast back navigation through WKWebView back-forward list.
+  FAST_BACK = 0,
+  // Slow back navigation when back-forward list navigation is not possible.
+  SLOW_BACK = 1,
+  // Fast forward navigation through WKWebView back-forward list.
+  FAST_FORWARD = 2,
+  // Slow forward navigation when back-forward list navigation is not possible.
+  SLOW_FORWARD = 3,
+  BACK_FORWARD_NAVIGATION_TYPE_COUNT
+};
+
 // URL scheme for messages sent from javascript for asynchronous processing.
 NSString* const kScriptMessageName = @"crwebinvoke";
 
@@ -459,8 +476,10 @@
 // Returns YES if the user interacted with the page recently.
 @property(nonatomic, readonly) BOOL userClickedRecently;
 
-// Whether or not desktop user agent is used for the currentItem.
-@property(nonatomic, readonly) BOOL usesDesktopUserAgent;
+// User agent type of the transient item if any, the pending item if a
+// navigation is in progress or the last committed item otherwise.
+// Returns MOBILE, the default type, if navigation manager is nullptr or empty.
+@property(nonatomic, readonly) web::UserAgentType userAgentType;
 
 // Facade for Mojo API.
 @property(nonatomic, readonly) web::MojoFacade* mojoFacade;
@@ -477,10 +496,18 @@
 // unless the request was a POST.
 @property(nonatomic, readonly) NSDictionary* currentHTTPHeaders;
 
-// Requires page reconstruction if |item| has a non-NONE UserAgentType and it
-// differs from that of |fromItem|.
-- (void)updateDesktopUserAgentForItem:(web::NavigationItem*)item
-                previousUserAgentType:(web::UserAgentType)userAgentType;
+// Updates web view's user agent according to |userAgentType|. It is no-op if
+// |userAgentType| is NONE.
+- (void)updateWebViewUserAgentFromUserAgentType:
+    (web::UserAgentType)userAgentType;
+
+// Requires that the next load rebuild the web view. This is expensive, and
+// should be used only in the case where something has changed that web view
+// only checks on creation, such that the whole object needs to be rebuilt.
+// TODO(stuartmorgan): Merge this and reinitializeWebViewAndReload:. They are
+// currently subtly different in terms of implementation, but are for
+// fundamentally the same purpose.
+- (void)requirePageReconstruction;
 
 // Removes the container view from the hierarchy and resets the ivar.
 - (void)resetContainerView;
@@ -786,6 +813,9 @@
 // web view, or use native web view navigation where possible (for example,
 // going back and forward through the history stack).
 - (void)loadRequestForCurrentNavigationItem;
+// Reports Navigation.IOSWKWebViewSlowFastBackForward UMA. No-op if pending
+// navigation is not back forward navigation.
+- (void)reportBackForwardNavigationTypeForFastNavigation:(BOOL)isFast;
 
 // Handlers for JavaScript messages. |message| contains a JavaScript command and
 // data relevant to the message, and |context| contains contextual information
@@ -1616,6 +1646,13 @@
 
   [self ensureWebViewCreated];
 
+  // Update web view's user agent is called for every load, which may have
+  // performance implications because update web view's user agent may
+  // potentially send a message to a separate thread. However, this is not an
+  // issue for WKWebView because WKWebView's |setCustomUserAgent| is non-op if
+  // user agent stays thesame.
+  [self updateWebViewUserAgentFromUserAgentType:self.userAgentType];
+
   [self loadRequestForCurrentNavigationItem];
 }
 
@@ -2026,15 +2063,11 @@
 
   // Update the user agent before attempting the navigation.
   web::NavigationItem* toItem = items[index].get();
-  web::NavigationItem* previousItem = sessionController.currentItem;
-  web::UserAgentType previousUserAgentType =
-      previousItem ? previousItem->GetUserAgentType()
-                   : web::UserAgentType::NONE;
-  [self updateDesktopUserAgentForItem:toItem
-                previousUserAgentType:previousUserAgentType];
+  [self updateWebViewUserAgentFromUserAgentType:toItem->GetUserAgentType()];
 
+  web::NavigationItem* fromItem = sessionController.currentItem;
   BOOL sameDocumentNavigation =
-      [sessionController isSameDocumentNavigationBetweenItem:previousItem
+      [sessionController isSameDocumentNavigationBetweenItem:fromItem
                                                      andItem:toItem];
   if (sameDocumentNavigation) {
     [sessionController goToItemAtIndex:index];
@@ -2189,9 +2222,9 @@
   return rendererInitiatedWithoutInteraction || noNavigationItems;
 }
 
-- (BOOL)usesDesktopUserAgent {
+- (web::UserAgentType)userAgentType {
   web::NavigationItem* item = self.currentNavItem;
-  return item && item->GetUserAgentType() == web::UserAgentType::DESKTOP;
+  return item ? item->GetUserAgentType() : web::UserAgentType::MOBILE;
 }
 
 - (web::MojoFacade*)mojoFacade {
@@ -2230,15 +2263,14 @@
   return _passKitDownloader.get();
 }
 
-- (void)updateDesktopUserAgentForItem:(web::NavigationItem*)item
-                previousUserAgentType:(web::UserAgentType)userAgentType {
-  if (!item)
+- (void)updateWebViewUserAgentFromUserAgentType:
+    (web::UserAgentType)userAgentType {
+  if (userAgentType == web::UserAgentType::NONE)
     return;
-  web::UserAgentType itemUserAgentType = item->GetUserAgentType();
-  if (itemUserAgentType == web::UserAgentType::NONE)
-    return;
-  if (itemUserAgentType != userAgentType)
-    [self requirePageReconstruction];
+
+  NSString* userAgent =
+      base::SysUTF8ToNSString(web::GetWebClient()->GetUserAgent(userAgentType));
+  [_webView setCustomUserAgent:userAgent];
 }
 
 #pragma mark -
@@ -4035,7 +4067,7 @@
   // delegate must be specified.
   return web::BuildWKWebView(CGRectZero, config,
                              self.webStateImpl->GetBrowserState(),
-                             self.usesDesktopUserAgent);
+                             self.userAgentType);
 }
 
 - (void)setWebView:(WKWebView*)webView {
@@ -4939,6 +4971,7 @@
                      referrer:self.currentNavItemReferrer
                    transition:self.currentTransition];
     [self loadRequest:request];
+    [self reportBackForwardNavigationTypeForFastNavigation:NO];
   };
 
   // When navigating via WKBackForwardListItem to pages created or updated by
@@ -4985,6 +5018,7 @@
           [_webView goToBackForwardListItem:holder->back_forward_list_item()];
       [_navigationStates setState:web::WKNavigationState::REQUESTED
                     forNavigation:navigation];
+      [self reportBackForwardNavigationTypeForFastNavigation:YES];
     }
   };
 
@@ -5008,6 +5042,30 @@
       }));
 }
 
+- (void)reportBackForwardNavigationTypeForFastNavigation:(BOOL)isFast {
+  // TODO(crbug.com/665189): Use NavigationManager::GetPendingItemIndex() once
+  // it returns correct result.
+  int pendingIndex = self.sessionController.pendingItemIndex;
+  if (pendingIndex == -1) {
+    // Pending navigation is not a back forward navigation.
+    return;
+  }
+
+  BOOL isBack = pendingIndex < self.sessionController.lastCommittedItemIndex;
+  BackForwardNavigationType type = BackForwardNavigationType::FAST_BACK;
+  if (isBack) {
+    type = isFast ? BackForwardNavigationType::FAST_BACK
+                  : BackForwardNavigationType::SLOW_BACK;
+  } else {
+    type = isFast ? BackForwardNavigationType::FAST_FORWARD
+                  : BackForwardNavigationType::SLOW_FORWARD;
+  }
+
+  UMA_HISTOGRAM_ENUMERATION(
+      kUMAWKWebViewSlowFastBackForwardNavigationKey, type,
+      BackForwardNavigationType::BACK_FORWARD_NAVIGATION_TYPE_COUNT);
+}
+
 #pragma mark -
 #pragma mark Testing-Only Methods
 
diff --git a/ios/web/web_state/web_view_internal_creation_util.h b/ios/web/web_state/web_view_internal_creation_util.h
index 68e8912..38226bf 100644
--- a/ios/web/web_state/web_view_internal_creation_util.h
+++ b/ios/web/web_state/web_view_internal_creation_util.h
@@ -8,6 +8,8 @@
 #import <CoreGraphics/CoreGraphics.h>
 #import <WebKit/WebKit.h>
 
+#include "ios/web/public/user_agent.h"
+
 @protocol CRWContextMenuDelegate;
 
 // This file is a collection of functions that vend web views.
@@ -26,7 +28,7 @@
 WKWebView* BuildWKWebView(CGRect frame,
                           WKWebViewConfiguration* configuration,
                           BrowserState* browser_state,
-                          BOOL use_desktop_user_agent,
+                          UserAgentType user_agent_type,
                           id<CRWContextMenuDelegate> context_menu_delegate);
 
 // Creates and returns a new WKWebView for displaying regular web content.
@@ -35,7 +37,7 @@
 WKWebView* BuildWKWebView(CGRect frame,
                           WKWebViewConfiguration* configuration,
                           BrowserState* browser_state,
-                          BOOL use_desktop_user_agent);
+                          UserAgentType user_agent_type);
 
 // Creates and returns a new WKWebView for displaying regular web content.
 // The preconditions for the creation of a WKWebView are the same as the
diff --git a/ios/web/web_state/web_view_internal_creation_util.mm b/ios/web/web_state/web_view_internal_creation_util.mm
index c13b8b7..7c9fc45 100644
--- a/ios/web/web_state/web_view_internal_creation_util.mm
+++ b/ios/web/web_state/web_view_internal_creation_util.mm
@@ -36,7 +36,7 @@
 WKWebView* BuildWKWebView(CGRect frame,
                           WKWebViewConfiguration* configuration,
                           BrowserState* browser_state,
-                          BOOL use_desktop_user_agent,
+                          UserAgentType user_agent_type,
                           id<CRWContextMenuDelegate> context_menu_delegate) {
   VerifyWKWebViewCreationPreConditions(browser_state, configuration);
 
@@ -44,9 +44,6 @@
   WKWebView* web_view =
       [[WKWebView alloc] initWithFrame:frame configuration:configuration];
 
-  // Set the user agent.
-  UserAgentType user_agent_type =
-      use_desktop_user_agent ? UserAgentType::DESKTOP : UserAgentType::MOBILE;
   web_view.customUserAgent = base::SysUTF8ToNSString(
       web::GetWebClient()->GetUserAgent(user_agent_type));
 
@@ -77,17 +74,16 @@
 WKWebView* BuildWKWebView(CGRect frame,
                           WKWebViewConfiguration* configuration,
                           BrowserState* browser_state,
-                          BOOL use_desktop_user_agent) {
-  return BuildWKWebView(frame, configuration, browser_state,
-                        use_desktop_user_agent, nil);
+                          UserAgentType user_agent_type) {
+  return BuildWKWebView(frame, configuration, browser_state, user_agent_type,
+                        nil);
 }
 
 WKWebView* BuildWKWebView(CGRect frame,
                           WKWebViewConfiguration* configuration,
                           BrowserState* browser_state) {
-  BOOL use_desktop_user_agent = NO;
   return BuildWKWebView(frame, configuration, browser_state,
-                        use_desktop_user_agent);
+                        UserAgentType::MOBILE);
 }
 
 }  // namespace web
diff --git a/ios/web/web_view_creation_util.mm b/ios/web/web_view_creation_util.mm
index d3023e06..0edd5c4 100644
--- a/ios/web/web_view_creation_util.mm
+++ b/ios/web/web_view_creation_util.mm
@@ -5,6 +5,7 @@
 #import "ios/web/public/web_view_creation_util.h"
 
 #include "base/logging.h"
+#include "ios/web/public/user_agent.h"
 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
 #import "ios/web/web_state/web_view_internal_creation_util.h"
 
@@ -27,7 +28,8 @@
   WKWebViewConfigurationProvider& config_provider =
       WKWebViewConfigurationProvider::FromBrowserState(browser_state);
   return BuildWKWebView(frame, config_provider.GetWebViewConfiguration(),
-                        browser_state, NO, context_menu_delegate);
+                        browser_state, UserAgentType::MOBILE,
+                        context_menu_delegate);
 }
 
 }  // namespace web
diff --git a/media/blink/watch_time_reporter.cc b/media/blink/watch_time_reporter.cc
index f279e9c..b0127d7 100644
--- a/media/blink/watch_time_reporter.cc
+++ b/media/blink/watch_time_reporter.cc
@@ -162,6 +162,11 @@
   MaybeFinalizeWatchTime(FinalizeTime::ON_NEXT_UPDATE);
 }
 
+bool WatchTimeReporter::IsSizeLargeEnoughToReportWatchTime() const {
+  return initial_video_size_.height() >= kMinimumVideoSize.height() &&
+         initial_video_size_.width() >= kMinimumVideoSize.width();
+}
+
 void WatchTimeReporter::OnPowerStateChange(bool on_battery_power) {
   if (!reporting_timer_.IsRunning())
     return;
@@ -184,9 +189,7 @@
   // Report listen time or watch time only for tracks that are audio-only or
   // have both an audio and video track of sufficient size.
   return (!has_video_ && has_audio_) ||
-         (has_video_ && has_audio_ &&
-          initial_video_size_.height() >= kMinimumVideoSize.height() &&
-          initial_video_size_.width() >= kMinimumVideoSize.width());
+         (has_video_ && has_audio_ && IsSizeLargeEnoughToReportWatchTime());
 }
 
 void WatchTimeReporter::MaybeStartReportingTimer(
diff --git a/media/blink/watch_time_reporter.h b/media/blink/watch_time_reporter.h
index 8290bdc..9b3b93b 100644
--- a/media/blink/watch_time_reporter.h
+++ b/media/blink/watch_time_reporter.h
@@ -103,6 +103,10 @@
   void OnShown();
   void OnHidden();
 
+  // Returns true if the current size is large enough that watch time will be
+  // recorded for playback.
+  bool IsSizeLargeEnoughToReportWatchTime() const;
+
   // Setup the reporting interval to be immediate to avoid spinning real time
   // within the unit test.
   void set_reporting_interval_for_testing() {
diff --git a/media/blink/watch_time_reporter_unittest.cc b/media/blink/watch_time_reporter_unittest.cc
index 3bdad7a2..2aa2635a 100644
--- a/media/blink/watch_time_reporter_unittest.cc
+++ b/media/blink/watch_time_reporter_unittest.cc
@@ -279,39 +279,48 @@
   Initialize(!has_video_, true, true, gfx::Size());
   wtr_->OnPlaying();
   EXPECT_EQ(!has_video_, IsMonitoring());
+  EXPECT_FALSE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   Initialize(true, true, true, gfx::Size());
   wtr_->OnPlaying();
   EXPECT_EQ(!has_video_, IsMonitoring());
+  EXPECT_FALSE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   constexpr gfx::Size kSizeTooSmall = gfx::Size(100, 100);
   Initialize(!has_video_, true, true, kSizeTooSmall);
   wtr_->OnPlaying();
   EXPECT_EQ(!has_video_, IsMonitoring());
+  EXPECT_FALSE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   Initialize(true, true, true, kSizeJustRight);
   wtr_->OnPlaying();
   EXPECT_TRUE(IsMonitoring());
+  EXPECT_TRUE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   Initialize(true, false, false, kSizeJustRight);
   wtr_->OnPlaying();
   EXPECT_TRUE(IsMonitoring());
+  EXPECT_TRUE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   Initialize(true, true, false, kSizeJustRight);
   wtr_->OnPlaying();
   EXPECT_TRUE(IsMonitoring());
+  EXPECT_TRUE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   Initialize(true, true, true, gfx::Size());
   wtr_->OnPlaying();
   EXPECT_EQ(!has_video_, IsMonitoring());
+  EXPECT_FALSE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   Initialize(true, false, false, gfx::Size());
   wtr_->OnPlaying();
   EXPECT_EQ(!has_video_, IsMonitoring());
+  EXPECT_FALSE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   Initialize(true, true, false, gfx::Size());
   wtr_->OnPlaying();
   EXPECT_EQ(!has_video_, IsMonitoring());
+  EXPECT_FALSE(wtr_->IsSizeLargeEnoughToReportWatchTime());
 
   if (!has_video_)
     EXPECT_WATCH_TIME_FINALIZED();
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 20796d3..172541b 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1421,13 +1421,13 @@
   if (overlay_enabled_ && surface_manager_)
     surface_manager_->NaturalSizeChanged(rotated_size);
 
-  gfx::Size old_size = pipeline_metadata_.natural_size;
   pipeline_metadata_.natural_size = rotated_size;
-  if (old_size.IsEmpty()) {
-    // WatchTimeReporter doesn't report metrics for empty videos. Re-create
-    // |watch_time_reporter_| if we didn't originally know the video size.
+
+  // Re-create |watch_time_reporter_| if we didn't originally know the video
+  // size or the previous size was too small for reporting.
+  if (!watch_time_reporter_->IsSizeLargeEnoughToReportWatchTime())
     CreateWatchTimeReporter();
-  }
+
   client_->SizeChanged();
 
   if (observer_)
diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc
index 773b09e5..a3a358a 100644
--- a/media/gpu/android_video_decode_accelerator.cc
+++ b/media/gpu/android_video_decode_accelerator.cc
@@ -114,8 +114,7 @@
                                 VideoCodec codec) {
   return surface_id == SurfaceManager::kNoSurfaceID && codec == kCodecH264 &&
          codec_allocator->IsAnyRegisteredAVDA() &&
-         (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 ||
-          base::SysInfo::IsLowEndDevice());
+         base::android::BuildInfo::GetInstance()->sdk_int() <= 18;
 }
 
 }  // namespace
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 361156b..162255b2 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -164,7 +164,7 @@
       enable_token_binding(false),
       http_09_on_non_default_ports_enabled(false),
       restrict_to_one_preconnect_for_proxies(false) {
-  quic_supported_versions.push_back(QUIC_VERSION_35);
+  quic_supported_versions.push_back(QUIC_VERSION_37);
 }
 
 HttpNetworkSession::Params::Params(const Params& other) = default;
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index ff94a6de..3bc6c3af 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -437,6 +437,7 @@
     case CONNECTION_INFO_QUIC_36:
     case CONNECTION_INFO_QUIC_37:
     case CONNECTION_INFO_QUIC_38:
+    case CONNECTION_INFO_QUIC_39:
       return true;
     case NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
@@ -483,6 +484,8 @@
       return "http/2+quic/37";
     case CONNECTION_INFO_QUIC_38:
       return "http/2+quic/38";
+    case CONNECTION_INFO_QUIC_39:
+      return "http/2+quic/39";
     case CONNECTION_INFO_HTTP0_9:
       return "http/0.9";
     case CONNECTION_INFO_HTTP1_0:
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h
index 22b3d07..89366f4 100644
--- a/net/http/http_response_info.h
+++ b/net/http/http_response_info.h
@@ -50,6 +50,7 @@
     CONNECTION_INFO_QUIC_36 = 14,
     CONNECTION_INFO_QUIC_37 = 15,
     CONNECTION_INFO_QUIC_38 = 16,
+    CONNECTION_INFO_QUIC_39 = 17,
     NUM_OF_CONNECTION_INFOS,
   };
 
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index 9c38e69..111ebaf 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -376,6 +376,10 @@
   for (const auto& job_controller : job_controller_set_) {
     DCHECK(job_controller->HasPendingAltJob() ||
            job_controller->HasPendingMainJob());
+    // Additionally logs the states of the jobs if there are at least 500
+    // controllers, which suggests that there might be a leak.
+    if (job_controller_set_.size() >= 500)
+      job_controller->LogHistograms();
     // For a preconnect controller, it should have exactly the main job.
     if (job_controller->is_preconnect()) {
       preconnect_controller_count++;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 398f84e1..1c12a9e7 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -208,6 +208,7 @@
       io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))),
       connection_(new ClientSocketHandle),
       session_(session),
+      state_(STATE_NONE),
       next_state_(STATE_NONE),
       pac_request_(NULL),
       destination_(destination),
@@ -383,6 +384,20 @@
   return proxy_info_;
 }
 
+void HttpStreamFactoryImpl::Job::LogHistograms() const {
+  if (job_type_ == MAIN) {
+    UMA_HISTOGRAM_ENUMERATION("Net.HttpStreamFactoryJob.Main.NextState",
+                              next_state_, STATE_MAX);
+    UMA_HISTOGRAM_ENUMERATION("Net.HttpStreamFactoryJob.Main.State", state_,
+                              STATE_MAX);
+  } else if (job_type_ == ALTERNATIVE) {
+    UMA_HISTOGRAM_ENUMERATION("Net.HttpStreamFactoryJob.Alt.NextState",
+                              next_state_, STATE_MAX);
+    UMA_HISTOGRAM_ENUMERATION("Net.HttpStreamFactoryJob.Alt.State", state_,
+                              STATE_MAX);
+  }
+}
+
 void HttpStreamFactoryImpl::Job::GetSSLInfo() {
   DCHECK(using_ssl_);
   DCHECK(!establishing_tunnel_);
@@ -659,6 +674,8 @@
   int rv = result;
   do {
     State state = next_state_;
+    // Added to investigate crbug.com/711721.
+    state_ = state;
     next_state_ = STATE_NONE;
     switch (state) {
       case STATE_START:
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h
index f73587a..b1c2b66 100644
--- a/net/http/http_stream_factory_impl_job.h
+++ b/net/http/http_stream_factory_impl_job.h
@@ -251,6 +251,10 @@
     return using_existing_quic_session_;
   }
 
+  // TODO(xunjieli): Added to investigate crbug.com/711721. Remove when no
+  // longer needed.
+  void LogHistograms() const;
+
  private:
   friend class HttpStreamFactoryImplJobPeer;
 
@@ -285,7 +289,9 @@
     STATE_DRAIN_BODY_FOR_AUTH_RESTART,
     STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE,
     STATE_DONE,
-    STATE_NONE
+    STATE_NONE,
+    // Used for UMA.
+    STATE_MAX,
   };
 
   void OnStreamReadyCallback();
@@ -405,6 +411,10 @@
   CompletionCallback io_callback_;
   std::unique_ptr<ClientSocketHandle> connection_;
   HttpNetworkSession* const session_;
+
+  // |state_| is only used for LogHistograms().
+  State state_;
+
   State next_state_;
   ProxyService::PacRequest* pac_request_;
   SSLInfo ssl_info_;
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc
index ec382771..0bbca3c 100644
--- a/net/http/http_stream_factory_impl_job_controller.cc
+++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -681,6 +681,13 @@
   return alternative_job_.get() != nullptr;
 }
 
+void HttpStreamFactoryImpl::JobController::LogHistograms() const {
+  if (main_job_)
+    main_job_->LogHistograms();
+  if (alternative_job_)
+    alternative_job_->LogHistograms();
+}
+
 size_t HttpStreamFactoryImpl::JobController::EstimateMemoryUsage() const {
   return base::trace_event::EstimateMemoryUsage(main_job_) +
          base::trace_event::EstimateMemoryUsage(alternative_job_);
diff --git a/net/http/http_stream_factory_impl_job_controller.h b/net/http/http_stream_factory_impl_job_controller.h
index 9a43bfb..8aaaaad 100644
--- a/net/http/http_stream_factory_impl_job_controller.h
+++ b/net/http/http_stream_factory_impl_job_controller.h
@@ -178,6 +178,10 @@
   // Returns true if |this| has a pending alternative job that is not completed.
   bool HasPendingAltJob() const;
 
+  // TODO(xunjieli): Added to investigate crbug.com/711721. Remove when no
+  // longer needed.
+  void LogHistograms() const;
+
   // Returns the estimated memory usage in bytes.
   size_t EstimateMemoryUsage() const;
 
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc
index b634dea..56672ba5 100644
--- a/net/quic/chromium/quic_http_stream.cc
+++ b/net/quic/chromium/quic_http_stream.cc
@@ -151,6 +151,8 @@
       return HttpResponseInfo::CONNECTION_INFO_QUIC_37;
     case QUIC_VERSION_38:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_38;
+    case QUIC_VERSION_39:
+      return HttpResponseInfo::CONNECTION_INFO_QUIC_39;
   }
   NOTREACHED();
   return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc
index 4480504..b0813e0 100644
--- a/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -82,12 +82,12 @@
                   "Receiver",
                   "BBR sender",
                   Perspective::IS_SERVER,
-                  /*connection_id=*/42),
+                  /*connection_id=*/GetPeerInMemoryConnectionId(42)),
         competing_receiver_(&simulator_,
                             "Competing receiver",
                             "Competing sender",
                             Perspective::IS_SERVER,
-                            /*connection_id=*/43),
+                            /*connection_id=*/GetPeerInMemoryConnectionId(43)),
         receiver_multiplexer_("Receiver multiplexer",
                               {&receiver_, &competing_receiver_}) {
     rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats();
diff --git a/net/quic/core/congestion_control/general_loss_algorithm.cc b/net/quic/core/congestion_control/general_loss_algorithm.cc
index 722134c0..97f0c98 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/net/quic/core/congestion_control/general_loss_algorithm.cc
@@ -8,6 +8,7 @@
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
 
 namespace net {
 
@@ -134,10 +135,6 @@
   if (loss_type_ != kAdaptiveTime || reordering_shift_ == 0) {
     return;
   }
-  if (spurious_retransmission <= largest_sent_on_spurious_retransmit_) {
-    return;
-  }
-  largest_sent_on_spurious_retransmit_ = unacked_packets.largest_sent_packet();
   // Calculate the extra time needed so this wouldn't have been declared lost.
   // Extra time needed is based on how long it's been since the spurious
   // retransmission was sent, because the SRTT and latest RTT may have changed.
@@ -147,6 +144,19 @@
   // Increase the reordering fraction until enough time would be allowed.
   QuicTime::Delta max_rtt =
       std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
+  if (FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss) {
+    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_fix_adaptive_time_loss);
+    while ((max_rtt >> reordering_shift_) <= extra_time_needed &&
+           reordering_shift_ > 0) {
+      --reordering_shift_;
+    }
+    return;
+  }
+
+  if (spurious_retransmission <= largest_sent_on_spurious_retransmit_) {
+    return;
+  }
+  largest_sent_on_spurious_retransmit_ = unacked_packets.largest_sent_packet();
   QuicTime::Delta proposed_extra_time(QuicTime::Delta::Zero());
   do {
     proposed_extra_time = max_rtt >> reordering_shift_;
diff --git a/net/quic/core/congestion_control/general_loss_algorithm.h b/net/quic/core/congestion_control/general_loss_algorithm.h
index d2557e56..281a139 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm.h
+++ b/net/quic/core/congestion_control/general_loss_algorithm.h
@@ -59,6 +59,8 @@
   QuicTime loss_detection_timeout_;
   // Largest sent packet when a spurious retransmit is detected.
   // Prevents increasing the reordering threshold multiple times per epoch.
+  // TODO(ianswett): Deprecate when
+  // quic_reloadable_flag_quic_fix_adaptive_time_loss is deprecated.
   QuicPacketNumber largest_sent_on_spurious_retransmit_;
   LossDetectionType loss_type_;
   // Fraction of a max(SRTT, latest_rtt) to permit reordering before declaring
diff --git a/net/quic/core/congestion_control/general_loss_algorithm_test.cc b/net/quic/core/congestion_control/general_loss_algorithm_test.cc
index 6fa96d7..1bfb2d9 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/net/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -50,16 +50,15 @@
   }
 
   void VerifyLosses(QuicPacketNumber largest_newly_acked,
-                    QuicPacketNumber* losses_expected,
-                    size_t num_losses) {
+                    const std::vector<QuicPacketNumber>& losses_expected) {
     if (largest_newly_acked > unacked_packets_.largest_observed()) {
       unacked_packets_.IncreaseLargestObserved(largest_newly_acked);
     }
     SendAlgorithmInterface::CongestionVector lost_packets;
     loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_,
                                  largest_newly_acked, &lost_packets);
-    EXPECT_EQ(num_losses, lost_packets.size());
-    for (size_t i = 0; i < num_losses; ++i) {
+    ASSERT_EQ(losses_expected.size(), lost_packets.size());
+    for (size_t i = 0; i < losses_expected.size(); ++i) {
       EXPECT_EQ(lost_packets[i].first, losses_expected[i]);
     }
   }
@@ -79,14 +78,13 @@
   }
   // No loss on one ack.
   unacked_packets_.RemoveFromInFlight(2);
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   // No loss on two acks.
   unacked_packets_.RemoveFromInFlight(3);
-  VerifyLosses(3, nullptr, 0);
+  VerifyLosses(3, std::vector<QuicPacketNumber>{});
   // Loss on three acks.
   unacked_packets_.RemoveFromInFlight(4);
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(4, lost, arraysize(lost));
+  VerifyLosses(4, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -103,8 +101,7 @@
   unacked_packets_.RemoveFromInFlight(2);
   unacked_packets_.RemoveFromInFlight(3);
   unacked_packets_.RemoveFromInFlight(4);
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(4, lost, arraysize(lost));
+  VerifyLosses(4, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -118,8 +115,7 @@
 
   // Nack the first packet 3 times in an AckFrame with three missing packets.
   unacked_packets_.RemoveFromInFlight(4);
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(4, lost, arraysize(lost));
+  VerifyLosses(4, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -131,13 +127,12 @@
   }
   // Early retransmit when the final packet gets acked and the first is nacked.
   unacked_packets_.RemoveFromInFlight(2);
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout());
 
   clock_.AdvanceTime(1.25 * rtt_stats_.latest_rtt());
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(2, lost, arraysize(lost));
+  VerifyLosses(2, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -155,21 +150,18 @@
   // elapsed since the packets were sent.
   unacked_packets_.RemoveFromInFlight(kNumSentPackets);
   // This simulates a single ack following multiple missing packets with FACK.
-  QuicPacketNumber lost[] = {1, 2};
-  VerifyLosses(kNumSentPackets, lost, arraysize(lost));
+  VerifyLosses(kNumSentPackets, {1, 2});
   // The time has already advanced 1/4 an RTT, so ensure the timeout is set
   // 1.25 RTTs after the earliest pending packet(3), not the last(4).
   EXPECT_EQ(clock_.Now() + rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout());
 
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
-  QuicPacketNumber lost2[] = {1, 2, 3};
-  VerifyLosses(kNumSentPackets, lost2, arraysize(lost2));
+  VerifyLosses(kNumSentPackets, {1, 2, 3});
   EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout());
   clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
-  QuicPacketNumber lost3[] = {1, 2, 3, 4};
-  VerifyLosses(kNumSentPackets, lost3, arraysize(lost3));
+  VerifyLosses(kNumSentPackets, {1, 2, 3, 4});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -185,7 +177,7 @@
   // Early retransmit when the final packet gets acked and the first is nacked.
   unacked_packets_.IncreaseLargestObserved(2);
   unacked_packets_.RemoveFromInFlight(2);
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -199,14 +191,13 @@
   // Early retransmit when the final packet gets acked and the first is nacked.
   unacked_packets_.IncreaseLargestObserved(2);
   unacked_packets_.RemoveFromInFlight(2);
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout());
 
   // The packet should be lost once the loss timeout is reached.
   clock_.AdvanceTime(0.25 * rtt_stats_.latest_rtt());
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(2, lost, arraysize(lost));
+  VerifyLosses(2, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -224,8 +215,7 @@
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
   unacked_packets_.IncreaseLargestObserved(2);
   unacked_packets_.RemoveFromInFlight(2);
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(2, lost, arraysize(lost));
+  VerifyLosses(2, {1});
 }
 
 // NoFack loss detection tests.
@@ -238,14 +228,13 @@
   }
   // No loss on one ack.
   unacked_packets_.RemoveFromInFlight(2);
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   // No loss on two acks.
   unacked_packets_.RemoveFromInFlight(3);
-  VerifyLosses(3, nullptr, 0);
+  VerifyLosses(3, std::vector<QuicPacketNumber>{});
   // Loss on three acks.
   unacked_packets_.RemoveFromInFlight(4);
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(4, lost, arraysize(lost));
+  VerifyLosses(4, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -264,13 +253,12 @@
   unacked_packets_.RemoveFromInFlight(2);
   unacked_packets_.RemoveFromInFlight(3);
   unacked_packets_.RemoveFromInFlight(4);
-  VerifyLosses(4, nullptr, 0);
+  VerifyLosses(4, std::vector<QuicPacketNumber>{});
   // The timer isn't set because we expect more acks.
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   // Process another ack and then packet 1 will be lost.
   unacked_packets_.RemoveFromInFlight(5);
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(5, lost, arraysize(lost));
+  VerifyLosses(5, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -285,13 +273,12 @@
 
   // Nack the first packet 3 times in an AckFrame with three missing packets.
   unacked_packets_.RemoveFromInFlight(4);
-  VerifyLosses(4, nullptr, 0);
+  VerifyLosses(4, std::vector<QuicPacketNumber>{});
   // The timer isn't set because we expect more acks.
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   // Process another ack and then packet 1 and 2 will be lost.
   unacked_packets_.RemoveFromInFlight(5);
-  QuicPacketNumber lost[] = {1, 2};
-  VerifyLosses(5, lost, arraysize(lost));
+  VerifyLosses(5, {1, 2});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -305,7 +292,7 @@
   }
   unacked_packets_.RemoveFromInFlight(2);
   for (size_t i = 1; i < 500; ++i) {
-    VerifyLosses(2, nullptr, 0);
+    VerifyLosses(2, std::vector<QuicPacketNumber>{});
   }
   EXPECT_EQ(1.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout() - clock_.Now());
@@ -323,14 +310,13 @@
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   // The packet should not be lost until 1.25 RTTs pass.
   unacked_packets_.RemoveFromInFlight(2);
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   // Expect the timer to be set to 0.25 RTT's in the future.
   EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout() - clock_.Now());
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(2, lost, arraysize(lost));
+  VerifyLosses(2, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -346,13 +332,13 @@
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   // The packet should not be lost without a nack.
   unacked_packets_.RemoveFromInFlight(1);
-  VerifyLosses(1, nullptr, 0);
+  VerifyLosses(1, std::vector<QuicPacketNumber>{});
   // The timer should still not be set.
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
-  VerifyLosses(1, nullptr, 0);
+  VerifyLosses(1, std::vector<QuicPacketNumber>{});
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
-  VerifyLosses(1, nullptr, 0);
+  VerifyLosses(1, std::vector<QuicPacketNumber>{});
 
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
@@ -369,13 +355,12 @@
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   // The packet should not be lost until 1.25 RTTs pass.
   unacked_packets_.RemoveFromInFlight(10);
-  VerifyLosses(10, nullptr, 0);
+  VerifyLosses(10, std::vector<QuicPacketNumber>{});
   // Expect the timer to be set to 0.25 RTT's in the future.
   EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout() - clock_.Now());
   clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
-  QuicPacketNumber lost[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
-  VerifyLosses(10, lost, arraysize(lost));
+  VerifyLosses(10, {1, 2, 3, 4, 5, 6, 7, 8, 9});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
@@ -392,7 +377,7 @@
   // The packet should not be lost until 1.25 RTTs pass.
 
   unacked_packets_.RemoveFromInFlight(10);
-  VerifyLosses(10, nullptr, 0);
+  VerifyLosses(10, std::vector<QuicPacketNumber>{});
   // Expect the timer to be set to 0.25 RTT's in the future.
   EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout() - clock_.Now());
@@ -401,7 +386,7 @@
   // are lost.
   for (QuicPacketNumber i = 1; i <= 9; ++i) {
     unacked_packets_.RemoveFromInFlight(i);
-    VerifyLosses(i, nullptr, 0);
+    VerifyLosses(i, std::vector<QuicPacketNumber>{});
     EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   }
 }
@@ -421,14 +406,13 @@
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   // Packet 1 should not be lost until 1/16 RTTs pass.
   unacked_packets_.RemoveFromInFlight(2);
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   // Expect the timer to be set to 1/16 RTT's in the future.
   EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 16),
             loss_algorithm_.GetLossTimeout() - clock_.Now());
-  VerifyLosses(2, nullptr, 0);
+  VerifyLosses(2, std::vector<QuicPacketNumber>{});
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 16));
-  QuicPacketNumber lost[] = {1};
-  VerifyLosses(2, lost, arraysize(lost));
+  VerifyLosses(2, {1});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
   // Retransmit packet 1 as 11 and 2 as 12.
   SendDataPacket(11);
@@ -437,6 +421,11 @@
   // Advance the time 1/4 RTT and indicate the loss was spurious.
   // The new threshold should be 1/2 RTT.
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4));
+  if (FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss) {
+    // The flag fixes an issue where adaptive time loss would increase the
+    // reordering threshold by an extra factor of two.
+    clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+  }
   loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(),
                                              rtt_stats_, 11);
   EXPECT_EQ(1, loss_algorithm_.reordering_shift());
diff --git a/net/quic/core/congestion_control/pacing_sender.cc b/net/quic/core/congestion_control/pacing_sender.cc
index 976c408..c645b8a 100644
--- a/net/quic/core/congestion_control/pacing_sender.cc
+++ b/net/quic/core/congestion_control/pacing_sender.cc
@@ -109,9 +109,8 @@
   return in_flight;
 }
 
-QuicTime::Delta PacingSender::TimeUntilSend(
-    QuicTime now,
-    QuicByteCount bytes_in_flight) const {
+QuicTime::Delta PacingSender::TimeUntilSend(QuicTime now,
+                                            QuicByteCount bytes_in_flight) {
   DCHECK(sender_ != nullptr);
   QuicTime::Delta time_until_send =
       sender_->TimeUntilSend(now, bytes_in_flight);
diff --git a/net/quic/core/congestion_control/pacing_sender.h b/net/quic/core/congestion_control/pacing_sender.h
index b297b8f8..65047210 100644
--- a/net/quic/core/congestion_control/pacing_sender.h
+++ b/net/quic/core/congestion_control/pacing_sender.h
@@ -45,13 +45,15 @@
       QuicTime event_time,
       const SendAlgorithmInterface::CongestionVector& acked_packets,
       const SendAlgorithmInterface::CongestionVector& lost_packets);
+
   bool OnPacketSent(QuicTime sent_time,
                     QuicByteCount bytes_in_flight,
                     QuicPacketNumber packet_number,
                     QuicByteCount bytes,
                     HasRetransmittableData is_retransmittable);
-  QuicTime::Delta TimeUntilSend(QuicTime now,
-                                QuicByteCount bytes_in_flight) const;
+
+  QuicTime::Delta TimeUntilSend(QuicTime now, QuicByteCount bytes_in_flight);
+
   QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const;
 
  private:
@@ -65,7 +67,7 @@
   // Send time of the last packet considered delayed.
   QuicTime last_delayed_packet_sent_time_;
   QuicTime ideal_next_packet_send_time_;  // When can the next packet be sent.
-  mutable bool was_last_send_delayed_;  // True when the last send was delayed.
+  bool was_last_send_delayed_;  // True when the last send was delayed.
 
   DISALLOW_COPY_AND_ASSIGN(PacingSender);
 };
diff --git a/net/quic/core/congestion_control/send_algorithm_test.cc b/net/quic/core/congestion_control/send_algorithm_test.cc
index 4078944..f9afe7c5 100644
--- a/net/quic/core/congestion_control/send_algorithm_test.cc
+++ b/net/quic/core/congestion_control/send_algorithm_test.cc
@@ -217,7 +217,7 @@
                   "Receiver",
                   "QUIC sender",
                   Perspective::IS_SERVER,
-                  42) {
+                  net::test::GetPeerInMemoryConnectionId(42)) {
     rtt_stats_ = quic_sender_.connection()->sent_packet_manager().GetRttStats();
     sender_ = SendAlgorithmInterface::Create(
         simulator_.GetClock(), rtt_stats_,
diff --git a/net/quic/core/crypto/crypto_handshake_message.cc b/net/quic/core/crypto/crypto_handshake_message.cc
index 4e03d4e..220c46a 100644
--- a/net/quic/core/crypto/crypto_handshake_message.cc
+++ b/net/quic/core/crypto/crypto_handshake_message.cc
@@ -11,6 +11,7 @@
 #include "net/quic/core/crypto/crypto_utils.h"
 #include "net/quic/core/quic_socket_address_coder.h"
 #include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_map_util.h"
 #include "net/quic/platform/api/quic_str_cat.h"
 #include "net/quic/platform/api/quic_text_utils.h"
@@ -246,6 +247,9 @@
         if (it->second.size() == 8) {
           uint64_t value;
           memcpy(&value, it->second.data(), sizeof(value));
+          if (QuicUtils::IsConnectionIdWireFormatBigEndian(perspective)) {
+            value = QuicEndian::NetToHost64(value);
+          }
           ret += QuicTextUtils::Uint64ToString(value);
           done = true;
         }
diff --git a/net/quic/core/crypto/crypto_server_test.cc b/net/quic/core/crypto/crypto_server_test.cc
index 85f0752..65cdc12c 100644
--- a/net/quic/core/crypto/crypto_server_test.cc
+++ b/net/quic/core/crypto/crypto_server_test.cc
@@ -19,6 +19,7 @@
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_socket_address_coder.h"
 #include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_string_piece.h"
 #include "net/quic/platform/api/quic_text_utils.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
@@ -363,6 +364,11 @@
     } else {
       ASSERT_EQ(QUIC_NO_ERROR,
                 out_.GetUint64(kRCID, &server_designated_connection_id));
+      if (QuicUtils::IsConnectionIdWireFormatBigEndian(
+              Perspective::IS_SERVER)) {
+        server_designated_connection_id =
+            QuicEndian::NetToHost64(server_designated_connection_id);
+      }
       EXPECT_EQ(rand_for_id_generation_.RandUint64(),
                 server_designated_connection_id);
     }
diff --git a/net/quic/core/crypto/quic_crypto_client_config.cc b/net/quic/core/crypto/quic_crypto_client_config.cc
index 35b44e9..d70f79aa5 100644
--- a/net/quic/core/crypto/quic_crypto_client_config.cc
+++ b/net/quic/core/crypto/quic_crypto_client_config.cc
@@ -22,6 +22,7 @@
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_hostname_utils.h"
 #include "net/quic/platform/api/quic_logging.h"
 #include "net/quic/platform/api/quic_map_util.h"
@@ -192,6 +193,7 @@
   scfg_.reset();
   SetProofInvalid();
   std::queue<QuicConnectionId> empty_queue;
+  using std::swap;
   swap(server_designated_connection_ids_, empty_queue);
 }
 
@@ -236,6 +238,7 @@
   scfg_.reset();
   ++generation_counter_;
   std::queue<QuicConnectionId> empty_queue;
+  using std::swap;
   swap(server_designated_connection_ids_, empty_queue);
 }
 
@@ -499,6 +502,9 @@
     CryptoHandshakeMessage* out,
     string* error_details) const {
   DCHECK(error_details != nullptr);
+  if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_CLIENT)) {
+    connection_id = QuicEndian::HostToNet64(connection_id);
+  }
 
   FillInchoateClientHello(server_id, preferred_version, cached, rand,
                           /* demand_x509_proof= */ true, out_params, out);
@@ -819,6 +825,9 @@
       *error_details = "Missing kRCID";
       return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
     }
+    if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_CLIENT)) {
+      connection_id = QuicEndian::NetToHost64(connection_id);
+    }
     cached->add_server_designated_connection_id(connection_id);
     if (!nonce.empty()) {
       cached->add_server_nonce(nonce.as_string());
diff --git a/net/quic/core/crypto/quic_crypto_client_config_test.cc b/net/quic/core/crypto/quic_crypto_client_config_test.cc
index 694767f..c38d8058 100644
--- a/net/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/net/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -6,6 +6,8 @@
 
 #include "net/quic/core/crypto/proof_verifier.h"
 #include "net/quic/core/quic_server_id.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/quic/test_tools/mock_random.h"
 #include "net/quic/test_tools/quic_test_utils.h"
@@ -525,7 +527,10 @@
                                     AllSupportedVersions().front(), "", &cached,
                                     out_params, &error));
   EXPECT_TRUE(cached.has_server_designated_connection_id());
-  EXPECT_EQ(kConnectionId, cached.GetNextServerDesignatedConnectionId());
+  EXPECT_EQ(QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_CLIENT)
+                ? QuicEndian::NetToHost64(kConnectionId)
+                : kConnectionId,
+            cached.GetNextServerDesignatedConnectionId());
   EXPECT_EQ(server_nonce, cached.GetNextServerNonce());
 }
 
diff --git a/net/quic/core/crypto/quic_crypto_server_config.cc b/net/quic/core/crypto/quic_crypto_server_config.cc
index b7a44bd..b807d46 100644
--- a/net/quic/core/crypto/quic_crypto_server_config.cc
+++ b/net/quic/core/crypto/quic_crypto_server_config.cc
@@ -35,6 +35,7 @@
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/platform/api/quic_bug_tracker.h"
 #include "net/quic/platform/api/quic_clock.h"
+#include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_hostname_utils.h"
 #include "net/quic/platform/api/quic_logging.h"
 #include "net/quic/platform/api/quic_reference_counted.h"
@@ -745,6 +746,10 @@
     const QuicReferenceCountedPointer<Config>& requested_config,
     const QuicReferenceCountedPointer<Config>& primary_config,
     std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
+  if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_SERVER)) {
+    connection_id = QuicEndian::HostToNet64(connection_id);
+  }
+
   ProcessClientHelloHelper helper(&done_cb);
 
   if (found_error) {
@@ -1479,6 +1484,10 @@
                   << "with server-designated connection ID "
                   << server_designated_connection_id;
     out->set_tag(kSREJ);
+    if (QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective::IS_SERVER)) {
+      server_designated_connection_id =
+          QuicEndian::HostToNet64(server_designated_connection_id);
+    }
     out->SetValue(kRCID, server_designated_connection_id);
   } else {
     out->set_tag(kREJ);
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc
index 99daacf..66f5be6 100644
--- a/net/quic/core/quic_connection.cc
+++ b/net/quic/core/quic_connection.cc
@@ -346,6 +346,7 @@
     close_connection_after_five_rtos_ = true;
   }
   if (packet_generator_.latched_flag_no_stop_waiting_frames() &&
+      version() > QUIC_VERSION_37 &&
       config.HasClientSentConnectionOption(kNSTP, perspective_)) {
     QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_stop_waiting_frames, 2, 2);
     no_stop_waiting_frames_ = true;
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc
index 92b57be..144f674 100644
--- a/net/quic/core/quic_connection_test.cc
+++ b/net/quic/core/quic_connection_test.cc
@@ -690,7 +690,7 @@
         peer_framer_(SupportedVersions(version()),
                      QuicTime::Zero(),
                      Perspective::IS_SERVER),
-        peer_creator_(connection_id_,
+        peer_creator_(GetPeerInMemoryConnectionId(connection_id_),
                       &peer_framer_,
                       &buffer_allocator_,
                       /*delegate=*/nullptr),
@@ -832,7 +832,8 @@
                                    QuicFrame frame,
                                    EncryptionLevel level) {
     QuicPacketHeader header;
-    header.public_header.connection_id = connection_id_;
+    header.public_header.connection_id =
+        GetPeerInMemoryConnectionId(connection_id_);
     header.public_header.packet_number_length = packet_number_length_;
     header.public_header.connection_id_length = connection_id_length_;
     header.public_header.multipath_flag = false;
@@ -942,7 +943,10 @@
   QuicPacket* ConstructDataPacket(QuicPacketNumber number,
                                   bool has_stop_waiting) {
     QuicPacketHeader header;
-    header.public_header.connection_id = connection_id_;
+    // Set connection_id to peer's in memory representation as this data packet
+    // is created by peer_framer.
+    header.public_header.connection_id =
+        GetPeerInMemoryConnectionId(connection_id_);
     header.public_header.packet_number_length = packet_number_length_;
     header.public_header.connection_id_length = connection_id_length_;
     header.public_header.multipath_flag = false;
@@ -958,7 +962,10 @@
 
   QuicPacket* ConstructClosePacket(QuicPacketNumber number) {
     QuicPacketHeader header;
-    header.public_header.connection_id = connection_id_;
+    // Set connection_id to peer's in memory representation as this connection
+    // close packet is created by peer_framer.
+    header.public_header.connection_id =
+        GetPeerInMemoryConnectionId(connection_id_);
     header.packet_number = number;
 
     QuicConnectionCloseFrame qccf;
@@ -1199,7 +1206,8 @@
   connection_.SetMaxPacketLength(1000);
 
   QuicPacketHeader header;
-  header.public_header.connection_id = connection_id_;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.public_header.version_flag = true;
   header.packet_number = 1;
 
@@ -1232,7 +1240,8 @@
   EXPECT_EQ(1000u, connection_.max_packet_length());
 
   QuicPacketHeader header;
-  header.public_header.connection_id = connection_id_;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.public_header.version_flag = true;
   header.packet_number = 1;
 
@@ -4323,7 +4332,9 @@
 
 TEST_P(QuicConnectionTest, PublicReset) {
   QuicPublicResetPacket header;
-  header.public_header.connection_id = connection_id_;
+  // Public reset packet in only built by server.
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.public_header.reset_flag = true;
   header.public_header.version_flag = false;
   header.rejected_packet_number = 10101;
@@ -4390,7 +4401,8 @@
   peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
 
   QuicPacketHeader header;
-  header.public_header.connection_id = connection_id_;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.public_header.version_flag = true;
   header.packet_number = 12;
 
@@ -4425,7 +4437,8 @@
   peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
 
   QuicPacketHeader header;
-  header.public_header.connection_id = connection_id_;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.public_header.version_flag = true;
   header.packet_number = 12;
 
@@ -4467,7 +4480,8 @@
   peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
 
   QuicPacketHeader header;
-  header.public_header.connection_id = connection_id_;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.public_header.version_flag = true;
   header.packet_number = 12;
 
@@ -4496,8 +4510,8 @@
 
   // Send a version negotiation packet.
   std::unique_ptr<QuicEncryptedPacket> encrypted(
-      peer_framer_.BuildVersionNegotiationPacket(connection_id_,
-                                                 AllSupportedVersions()));
+      peer_framer_.BuildVersionNegotiationPacket(
+          GetPeerInMemoryConnectionId(connection_id_), AllSupportedVersions()));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
   connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
@@ -4505,7 +4519,8 @@
   // Now force another packet.  The connection should transition into
   // NEGOTIATED_VERSION state and tell the packet creator to StopSendingVersion.
   QuicPacketHeader header;
-  header.public_header.connection_id = connection_id_;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.packet_number = 12;
   header.public_header.version_flag = false;
   QuicFrames frames;
@@ -4531,8 +4546,8 @@
               OnConnectionClosed(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, _,
                                  ConnectionCloseSource::FROM_SELF));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
-      framer_.BuildVersionNegotiationPacket(connection_id_,
-                                            AllSupportedVersions()));
+      framer_.BuildVersionNegotiationPacket(
+          GetPeerInMemoryConnectionId(connection_id_), AllSupportedVersions()));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
   connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
@@ -4588,7 +4603,8 @@
 TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
   // Construct a packet with stream frame and connection close frame.
   QuicPacketHeader header;
-  header.public_header.connection_id = connection_id_;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id_);
   header.packet_number = 1;
   header.public_header.version_flag = false;
 
diff --git a/net/quic/core/quic_crypto_client_stream_test.cc b/net/quic/core/quic_crypto_client_stream_test.cc
index e0b9983..d69c7c9 100644
--- a/net/quic/core/quic_crypto_client_stream_test.cc
+++ b/net/quic/core/quic_crypto_client_stream_test.cc
@@ -445,7 +445,7 @@
       client_state->GetNextServerDesignatedConnectionId();
   QuicConnectionId expected_id =
       server_session_->connection()->random_generator()->RandUint64();
-  EXPECT_EQ(expected_id, server_designated_id);
+  EXPECT_EQ(GetPeerInMemoryConnectionId(expected_id), server_designated_id);
   EXPECT_FALSE(client_state->has_server_designated_connection_id());
 }
 
diff --git a/net/quic/core/quic_crypto_server_stream_test.cc b/net/quic/core/quic_crypto_server_stream_test.cc
index ad3c54e..d6e845c6 100644
--- a/net/quic/core/quic_crypto_server_stream_test.cc
+++ b/net/quic/core/quic_crypto_server_stream_test.cc
@@ -257,7 +257,8 @@
       client_state->GetNextServerDesignatedConnectionId();
   const QuicConnectionId expected_id =
       server_connection_->random_generator()->RandUint64();
-  EXPECT_EQ(expected_id, server_designated_connection_id);
+  EXPECT_EQ(GetPeerInMemoryConnectionId(expected_id),
+            server_designated_connection_id);
   EXPECT_FALSE(client_state->has_server_designated_connection_id());
   ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
 }
@@ -284,7 +285,8 @@
       client_state->GetNextServerDesignatedConnectionId();
   const QuicConnectionId expected_id =
       server_connection_->random_generator()->RandUint64();
-  EXPECT_EQ(expected_id, server_designated_connection_id);
+  EXPECT_EQ(GetPeerInMemoryConnectionId(expected_id),
+            server_designated_connection_id);
   EXPECT_FALSE(client_state->has_server_designated_connection_id());
   ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
 
diff --git a/net/quic/core/quic_data_reader.cc b/net/quic/core/quic_data_reader.cc
index 5f2c483..0f728c9 100644
--- a/net/quic/core/quic_data_reader.cc
+++ b/net/quic/core/quic_data_reader.cc
@@ -7,6 +7,8 @@
 #include "net/base/int128.h"
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
 #include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_logging.h"
 
@@ -99,7 +101,7 @@
     return false;
   }
 
-  if (FLAGS_quic_restart_flag_quic_big_endian_connection_id) {
+  if (QuicUtils::IsConnectionIdWireFormatBigEndian(perspective_)) {
     *connection_id = QuicEndian::NetToHost64(*connection_id);
   }
 
@@ -154,4 +156,13 @@
   pos_ = len_;
 }
 
+uint8_t QuicDataReader::PeekByte() const {
+  if (pos_ >= len_) {
+    QUIC_BUG << "Reading is done, cannot peek next byte. Tried to read pos = "
+             << pos_ << " buffer length = " << len_;
+    return 0;
+  }
+  return data_[pos_];
+}
+
 }  // namespace net
diff --git a/net/quic/core/quic_data_reader.h b/net/quic/core/quic_data_reader.h
index 9507ec1..ffce87f 100644
--- a/net/quic/core/quic_data_reader.h
+++ b/net/quic/core/quic_data_reader.h
@@ -118,6 +118,12 @@
   // Returns the number of bytes remaining to be read.
   size_t BytesRemaining() const;
 
+  // Returns the next byte that to be read. Must not be called when there are no
+  // bytes to be read.
+  //
+  // DOES NOT forward the internal iterator.
+  uint8_t PeekByte() const;
+
  private:
   // Returns true if the underlying buffer has enough room to read the given
   // amount of bytes.
diff --git a/net/quic/core/quic_data_writer.cc b/net/quic/core/quic_data_writer.cc
index 3ac6450b..28791917 100644
--- a/net/quic/core/quic_data_writer.cc
+++ b/net/quic/core/quic_data_writer.cc
@@ -8,6 +8,7 @@
 #include <limits>
 
 #include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_utils.h"
 #include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_logging.h"
 
@@ -149,8 +150,12 @@
   length_ = capacity_;
 }
 
+bool QuicDataWriter::WritePaddingBytes(size_t count) {
+  return WriteRepeatedByte(0x00, count);
+}
+
 bool QuicDataWriter::WriteConnectionId(uint64_t connection_id) {
-  if (FLAGS_quic_restart_flag_quic_big_endian_connection_id) {
+  if (QuicUtils::IsConnectionIdWireFormatBigEndian(perspective_)) {
     connection_id = QuicEndian::HostToNet64(connection_id);
   }
 
diff --git a/net/quic/core/quic_data_writer.h b/net/quic/core/quic_data_writer.h
index a7faca2..ca4b4a2 100644
--- a/net/quic/core/quic_data_writer.h
+++ b/net/quic/core/quic_data_writer.h
@@ -52,6 +52,8 @@
   bool WriteRepeatedByte(uint8_t byte, size_t count);
   // Fills the remaining buffer with null characters.
   void WritePadding();
+  // Write padding of |count| bytes.
+  bool WritePaddingBytes(size_t count);
 
   // Write connection ID as a 64-bit unsigned integer to the payload.
   // TODO(fayang): Remove this method and use WriteUInt64() once deprecating
diff --git a/net/quic/core/quic_data_writer_test.cc b/net/quic/core/quic_data_writer_test.cc
index bc1d0ad..893ff42c 100644
--- a/net/quic/core/quic_data_writer_test.cc
+++ b/net/quic/core/quic_data_writer_test.cc
@@ -8,6 +8,7 @@
 
 #include "net/quic/core/quic_data_reader.h"
 #include "net/quic/core/quic_flags.h"
+#include "net/quic/core/quic_utils.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -215,8 +216,8 @@
   writer.WriteConnectionId(connection_id);
   test::CompareCharArraysWithHexError(
       "connection_id", buffer, kBufferLength,
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id ? big_endian
-                                                            : little_endian,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(GetParam()) ? big_endian
+                                                               : little_endian,
       kBufferLength);
 
   uint64_t read_connection_id;
diff --git a/net/quic/core/quic_error_codes.cc b/net/quic/core/quic_error_codes.cc
index ca87175..2f734e5 100644
--- a/net/quic/core/quic_error_codes.cc
+++ b/net/quic/core/quic_error_codes.cc
@@ -113,7 +113,6 @@
     RETURN_STRING_LITERAL(QUIC_CONNECTION_CANCELLED);
     RETURN_STRING_LITERAL(QUIC_BAD_PACKET_LOSS_RATE);
     RETURN_STRING_LITERAL(QUIC_PUBLIC_RESETS_POST_HANDSHAKE);
-    RETURN_STRING_LITERAL(QUIC_TIMEOUTS_WITH_OPEN_STREAMS);
     RETURN_STRING_LITERAL(QUIC_FAILED_TO_SERIALIZE_PACKET);
     RETURN_STRING_LITERAL(QUIC_TOO_MANY_AVAILABLE_STREAMS);
     RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_FEC_DATA);
diff --git a/net/quic/core/quic_error_codes.h b/net/quic/core/quic_error_codes.h
index 38750a5..2a6f335 100644
--- a/net/quic/core/quic_error_codes.h
+++ b/net/quic/core/quic_error_codes.h
@@ -174,8 +174,6 @@
   QUIC_BAD_PACKET_LOSS_RATE = 71,
   // Disabled QUIC because of too many PUBLIC_RESETs post handshake.
   QUIC_PUBLIC_RESETS_POST_HANDSHAKE = 73,
-  // Disabled QUIC because of too many timeouts with streams open.
-  QUIC_TIMEOUTS_WITH_OPEN_STREAMS = 74,
   // Closed because we failed to serialize a packet.
   QUIC_FAILED_TO_SERIALIZE_PACKET = 75,
   // QUIC timed out after too many RTOs.
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index 3924bc8..947186d 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -93,7 +93,7 @@
 QUIC_FLAG(
     bool,
     FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset,
-    false)
+    true)
 
 // If true, v33 QUIC client uses 1 bit to specify 8-byte connection id in
 // public flag.
@@ -132,13 +132,6 @@
 // If true, disables QUIC v34.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_34, true)
 
-// If true, enable quic version 38
-QUIC_FLAG(bool, FLAGS_quic_enable_version_38, false)
-
-// When true, ensures the session's flow control window is always at least 1.5x
-// larger than the largest stream flow control window.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_flow_control_invariant, true)
-
 // If greater than zero, mean RTT variation is multiplied by the specified
 // factor and added to the congestion window limit.
 QUIC_FLAG(double, FLAGS_quic_bbr_rtt_variation_weight, 0.0f)
@@ -149,7 +142,7 @@
 // If true, bidi streaming is always enabled in QUIC.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming,
-          false)
+          true)
 
 // If true, allows the 1RTT and 2RTT connection options to reduce the time
 // in BBR STARTUP to 1 or 2 RTTs with no bandwidth increase from 3.
@@ -172,16 +165,12 @@
 // quickly for the first adjustment as in subsequent ones.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune,
-          false)
+          true)
 
 // Only consider using the ack spacing in QUIC BBR if 2 packets are acked at
 // once.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2, false)
 
-// If true, 8-byte connection ID in public header is read and written in big
-// endian.
-QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_big_endian_connection_id, false)
-
 // If true, QUIC BBR stores a max filtered number of bytes delivered at a rate
 // faster than the sending rate.
 QUIC_FLAG(bool,
@@ -203,3 +192,26 @@
 // Fix a crash that occurs when a client sends multiple CHLOs close together on
 // the same connection.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_fix_quic_callback_crash, true)
+
+// If true, enable version 38 which supports new PADDING frame and respects NSTP
+// connection option.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_38, false)
+
+// If true, enable QUIC v39.
+QUIC_FLAG(bool, FLAGS_quic_enable_version_39, false)
+
+// If true, on client side, 8-byte connection ID in public header is read and
+// written in big endian.
+QUIC_FLAG(bool,
+          FLAGS_quic_restart_flag_quic_big_endian_connection_id_client,
+          false)
+
+// If true, on server side, 8-byte connection ID in public header is read and
+// written in big endian.
+QUIC_FLAG(bool,
+          FLAGS_quic_restart_flag_quic_big_endian_connection_id_server,
+          false)
+
+// Simplify QUIC\'s adaptive time loss detection to measure the necessary
+// reordering window for every spurious retransmit.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss, false)
diff --git a/net/quic/core/quic_flow_controller.h b/net/quic/core/quic_flow_controller.h
index b955da15..6f9acb3b 100644
--- a/net/quic/core/quic_flow_controller.h
+++ b/net/quic/core/quic_flow_controller.h
@@ -176,8 +176,7 @@
   // Used to dynamically enable receive window auto-tuning.
   bool auto_tune_receive_window_;
 
-  // The session's flow controller.  null if this is stream id 0 or
-  // FLAGS_quic_reloadable_flag_quic_flow_control_invariant is false.
+  // The session's flow controller.  null if this is stream id 0.
   // Not owned.
   QuicFlowControllerInterface* session_flow_controller_;
 
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc
index fc8e239..18102be 100644
--- a/net/quic/core/quic_framer.cc
+++ b/net/quic/core/quic_framer.cc
@@ -336,7 +336,11 @@
 
     switch (frame.type) {
       case PADDING_FRAME:
-        writer.WritePadding();
+        if (!AppendPaddingFrame(frame.padding_frame, &writer)) {
+          QUIC_BUG << "AppendPaddingFrame of "
+                   << frame.padding_frame.num_padding_bytes << " failed";
+          return 0;
+        }
         break;
       case STREAM_FRAME:
         if (!AppendStreamFrame(*frame.stream_frame, no_stream_frame_length,
@@ -1013,12 +1017,14 @@
 
     switch (frame_type) {
       case PADDING_FRAME: {
-        QuicPaddingFrame frame(reader->BytesRemaining());
+        QuicPaddingFrame frame;
+        ProcessPaddingFrame(reader, &frame);
         if (!visitor_->OnPaddingFrame(frame)) {
           QUIC_DVLOG(1) << "Visitor asked to stop further processing.";
+          // Returning true since there was no parsing error.
+          return true;
         }
-        // We're done with the packet.
-        return true;
+        continue;
       }
 
       case RST_STREAM_FRAME: {
@@ -1438,6 +1444,23 @@
   return true;
 }
 
+void QuicFramer::ProcessPaddingFrame(QuicDataReader* reader,
+                                     QuicPaddingFrame* frame) {
+  if (quic_version_ <= QUIC_VERSION_37) {
+    frame->num_padding_bytes = reader->BytesRemaining() + 1;
+    reader->ReadRemainingPayload();
+    return;
+  }
+  // Type byte has been read.
+  frame->num_padding_bytes = 1;
+  uint8_t next_byte;
+  while (!reader->IsDoneReading() && reader->PeekByte() == 0x00) {
+    reader->ReadBytes(&next_byte, 1);
+    DCHECK_EQ(0x00, next_byte);
+    ++frame->num_padding_bytes;
+  }
+}
+
 // static
 QuicStringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
     QuicVersion version,
@@ -2111,6 +2134,25 @@
   return true;
 }
 
+bool QuicFramer::AppendPaddingFrame(const QuicPaddingFrame& frame,
+                                    QuicDataWriter* writer) {
+  if (quic_version_ <= QUIC_VERSION_37) {
+    writer->WritePadding();
+    return true;
+  }
+
+  if (frame.num_padding_bytes == 0) {
+    return false;
+  }
+  if (frame.num_padding_bytes < 0) {
+    QUIC_BUG_IF(frame.num_padding_bytes != -1);
+    writer->WritePadding();
+    return true;
+  }
+  // Please note, num_padding_bytes includes type byte which has been written.
+  return writer->WritePaddingBytes(frame.num_padding_bytes - 1);
+}
+
 bool QuicFramer::RaiseError(QuicErrorCode error) {
   QUIC_DLOG(INFO) << ENDPOINT << "Error: " << QuicErrorCodeToString(error)
                   << " detail: " << detailed_error_;
diff --git a/net/quic/core/quic_framer.h b/net/quic/core/quic_framer.h
index 2ca8ea1..6cb8522 100644
--- a/net/quic/core/quic_framer.h
+++ b/net/quic/core/quic_framer.h
@@ -386,6 +386,7 @@
   bool ProcessWindowUpdateFrame(QuicDataReader* reader,
                                 QuicWindowUpdateFrame* frame);
   bool ProcessBlockedFrame(QuicDataReader* reader, QuicBlockedFrame* frame);
+  void ProcessPaddingFrame(QuicDataReader* reader, QuicPaddingFrame* frame);
 
   bool DecryptPayload(QuicDataReader* encrypted_reader,
                       const QuicPacketHeader& header,
@@ -460,6 +461,8 @@
                                QuicDataWriter* writer);
   bool AppendBlockedFrame(const QuicBlockedFrame& frame,
                           QuicDataWriter* writer);
+  bool AppendPaddingFrame(const QuicPaddingFrame& frame,
+                          QuicDataWriter* writer);
 
   bool RaiseError(QuicErrorCode error);
 
diff --git a/net/quic/core/quic_framer_test.cc b/net/quic/core/quic_framer_test.cc
index cf757fa..916127c 100644
--- a/net/quic/core/quic_framer_test.cc
+++ b/net/quic/core/quic_framer_test.cc
@@ -591,10 +591,11 @@
   memset(packet + header_size, 0, kMaxPacketSize - header_size);
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -629,10 +630,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -659,10 +661,11 @@
     } else {
       expected_error = "Unable to read packet number.";
     }
-    CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                             ? packet_cid_be
-                             : packet,
-                         i, expected_error, QUIC_INVALID_PACKET_HEADER);
+    CheckProcessingFails(
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
+        i, expected_error, QUIC_INVALID_PACKET_HEADER);
   }
 }
 
@@ -735,10 +738,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -768,10 +772,11 @@
     } else {
       expected_error = "Unable to read packet number.";
     }
-    CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                             ? packet_cid_be
-                             : packet,
-                         i, expected_error, QUIC_INVALID_PACKET_HEADER);
+    CheckProcessingFails(
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
+        i, expected_error, QUIC_INVALID_PACKET_HEADER);
   }
 }
 
@@ -799,10 +804,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -829,10 +835,11 @@
     } else {
       expected_error = "Unable to read packet number.";
     }
-    CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                             ? packet_cid_be
-                             : packet,
-                         i, expected_error, QUIC_INVALID_PACKET_HEADER);
+    CheckProcessingFails(
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
+        i, expected_error, QUIC_INVALID_PACKET_HEADER);
   }
 }
 
@@ -860,10 +867,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -892,10 +900,11 @@
     } else {
       expected_error = "Unable to read packet number.";
     }
-    CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                             ? packet_cid_be
-                             : packet,
-                         i, expected_error, QUIC_INVALID_PACKET_HEADER);
+    CheckProcessingFails(
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
+        i, expected_error, QUIC_INVALID_PACKET_HEADER);
   }
 }
 
@@ -923,10 +932,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -955,10 +965,11 @@
     } else {
       expected_error = "Unable to read packet number.";
     }
-    CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                             ? packet_cid_be
-                             : packet,
-                         i, expected_error, QUIC_INVALID_PACKET_HEADER);
+    CheckProcessingFails(
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
+        i, expected_error, QUIC_INVALID_PACKET_HEADER);
   }
 }
 
@@ -1062,10 +1073,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1075,6 +1087,8 @@
   for (char i = 0; i < 32; ++i) {
     EXPECT_EQ(i, (*visitor_.public_header_->nonce)[static_cast<size_t>(i)]);
   }
+  EXPECT_EQ(1u, visitor_.padding_frames_.size());
+  EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
 };
 
 TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
@@ -1115,10 +1129,11 @@
   };
   // clang-format on
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1127,6 +1142,8 @@
   ASSERT_TRUE(visitor_.header_.get());
   EXPECT_EQ(0, visitor_.frame_count_);
   EXPECT_EQ(1, visitor_.version_mismatch_);
+  EXPECT_EQ(1u, visitor_.padding_frames_.size());
+  EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
 };
 
 TEST_P(QuicFramerTest, PaddingFrame) {
@@ -1187,11 +1204,16 @@
   };
   // clang-format on
 
+  if (framer_.version() > QUIC_VERSION_37) {
+    return;
+  }
+
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1203,16 +1225,109 @@
 
   ASSERT_EQ(0u, visitor_.stream_frames_.size());
   EXPECT_EQ(0u, visitor_.ack_frames_.size());
+  EXPECT_EQ(1u, visitor_.padding_frames_.size());
+  EXPECT_EQ(28, visitor_.padding_frames_[0]->num_padding_bytes);
   // A packet with no frames is not acceptable.
   CheckProcessingFails(
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                            : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
       GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                           !kIncludeVersion, !kIncludeDiversificationNonce,
                           PACKET_6BYTE_PACKET_NUMBER),
       "Packet has no frames.", QUIC_MISSING_PAYLOAD);
 }
 
+TEST_P(QuicFramerTest, NewPaddingFrame) {
+  // clang-format off
+  unsigned char packet[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0x10, 0x32, 0x54, 0x76,
+    0x98, 0xBA, 0xDC, 0xFE,
+    // packet number
+    0xBC, 0x9A, 0x78, 0x56,
+    0x34, 0x12,
+
+    // paddings
+    0x00, 0x00,
+    // frame type (stream frame with fin)
+    0xFF,
+    // stream id
+    0x04, 0x03, 0x02, 0x01,
+    // offset
+    0x54, 0x76, 0x10, 0x32,
+    0xDC, 0xFE, 0x98, 0xBA,
+    // data length
+    0x0c, 0x00,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+    // paddings
+    0x00, 0x00,
+  };
+
+  unsigned char packet_cid_be[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0xBC, 0x9A, 0x78, 0x56,
+    0x34, 0x12,
+
+    // paddings
+    0x00, 0x00,
+    // frame type (stream frame with fin)
+    0xFF,
+    // stream id
+    0x04, 0x03, 0x02, 0x01,
+    // offset
+    0x54, 0x76, 0x10, 0x32,
+    0xDC, 0xFE, 0x98, 0xBA,
+    // data length
+    0x0c, 0x00,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+    // paddings
+    0x00, 0x00,
+  };
+  // clang-format on
+
+  if (framer_.version() <= QUIC_VERSION_37) {
+    return;
+  }
+
+  QuicEncryptedPacket encrypted(
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? arraysize(packet_cid_be)
+          : arraysize(packet),
+      false);
+  EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+  EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+  ASSERT_TRUE(visitor_.header_.get());
+  EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion,
+                              !kIncludeDiversificationNonce));
+
+  ASSERT_EQ(1u, visitor_.stream_frames_.size());
+  EXPECT_EQ(0u, visitor_.ack_frames_.size());
+  EXPECT_EQ(2u, visitor_.padding_frames_.size());
+  EXPECT_EQ(2, visitor_.padding_frames_[0]->num_padding_bytes);
+  EXPECT_EQ(2, visitor_.padding_frames_[1]->num_padding_bytes);
+  EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
+  EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
+  EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
+  CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
+}
+
 TEST_P(QuicFramerTest, StreamFrame) {
   // clang-format off
   unsigned char packet[] = {
@@ -1266,10 +1381,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1289,8 +1405,9 @@
 
   // Now test framing boundaries.
   CheckStreamFrameBoundaries(
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                            : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
       kQuicMaxStreamIdSize, !kIncludeVersion);
 }
 
@@ -1353,10 +1470,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1417,10 +1535,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1442,8 +1561,9 @@
   // Now test framing boundaries.
   const size_t stream_id_size = 3;
   CheckStreamFrameBoundaries(
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                            : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
       stream_id_size, !kIncludeVersion);
 }
 
@@ -1500,10 +1620,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1525,8 +1646,9 @@
   // Now test framing boundaries.
   const size_t stream_id_size = 2;
   CheckStreamFrameBoundaries(
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                            : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
       stream_id_size, !kIncludeVersion);
 }
 
@@ -1583,10 +1705,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1608,8 +1731,9 @@
   // Now test framing boundaries.
   const size_t stream_id_size = 1;
   CheckStreamFrameBoundaries(
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                            : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
       stream_id_size, !kIncludeVersion);
 }
 
@@ -1670,10 +1794,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1695,8 +1820,9 @@
 
   // Now test framing boundaries.
   CheckStreamFrameBoundaries(
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                            : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
       kQuicMaxStreamIdSize, kIncludeVersion);
 }
 
@@ -1755,10 +1881,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1793,10 +1920,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1853,10 +1981,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -1895,8 +2024,9 @@
       expected_error = "Unable to read num received packets.";
     }
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2002,10 +2132,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2095,8 +2226,9 @@
     }
 
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2139,10 +2271,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2163,8 +2296,9 @@
     string expected_error;
     expected_error = "Unable to read least unacked delta.";
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2221,10 +2355,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2253,8 +2388,9 @@
       expected_error = "Unable to read rst stream error code.";
     }
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2313,10 +2449,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2344,8 +2481,9 @@
       expected_error = "Unable to read connection close error details.";
     }
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2406,10 +2544,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2438,8 +2577,9 @@
       expected_error = "Unable to read goaway reason.";
     }
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2488,10 +2628,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2515,8 +2656,9 @@
       expected_error = "Unable to read window byte_offset.";
     }
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2559,10 +2701,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2580,8 +2723,9 @@
        ++i) {
     string expected_error = "Unable to read stream_id.";
     CheckProcessingFails(
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                              : packet,
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2620,10 +2764,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2694,10 +2839,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2715,7 +2861,7 @@
       visitor_.public_reset_packet_->client_address.host().address_family());
 
   // Now test framing boundaries.
-  if (!FLAGS_quic_restart_flag_quic_big_endian_connection_id) {
+  if (!QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())) {
     for (size_t i = 0; i < arraysize(packet); ++i) {
       string expected_error;
       QUIC_DLOG(INFO) << "iteration: " << i;
@@ -2812,10 +2958,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -2833,7 +2980,7 @@
       visitor_.public_reset_packet_->client_address.host().address_family());
 
   // Now test framing boundaries.
-  if (!FLAGS_quic_restart_flag_quic_big_endian_connection_id) {
+  if (!QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())) {
     for (size_t i = 0; i < arraysize(packet); ++i) {
       string expected_error;
       QUIC_DLOG(INFO) << "iteration: " << i;
@@ -2932,13 +3079,14 @@
   // clang-format on
 
   string expected_error = "Unable to read reset message.";
-  CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                           ? packet_cid_be
-                           : packet,
-                       FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                           ? arraysize(packet_cid_be)
-                           : arraysize(packet),
-                       expected_error, QUIC_INVALID_PUBLIC_RST_PACKET);
+  CheckProcessingFails(
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? arraysize(packet_cid_be)
+          : arraysize(packet),
+      expected_error, QUIC_INVALID_PUBLIC_RST_PACKET);
 }
 
 TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) {
@@ -3012,10 +3160,11 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -3033,7 +3182,7 @@
   EXPECT_EQ(443, visitor_.public_reset_packet_->client_address.port());
 
   // Now test framing boundaries.
-  if (!FLAGS_quic_restart_flag_quic_big_endian_connection_id) {
+  if (!QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())) {
     for (size_t i = 0; i < arraysize(packet); ++i) {
       string expected_error;
       QUIC_DLOG(INFO) << "iteration: " << i;
@@ -3100,10 +3249,11 @@
   QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -3124,10 +3274,11 @@
       expected_error = "Unable to read supported version in negotiation.";
       error_code = QUIC_INVALID_VERSION_NEGOTIATION_PACKET;
     }
-    CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                             ? packet_cid_be
-                             : packet,
-                         i, expected_error, error_code);
+    CheckProcessingFails(
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
+        i, expected_error, error_code);
   }
 }
 
@@ -3158,10 +3309,11 @@
   QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -3182,10 +3334,11 @@
       expected_error = "Unable to read supported version in negotiation.";
       error_code = QUIC_INVALID_VERSION_NEGOTIATION_PACKET;
     }
-    CheckProcessingFails(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                             ? packet_cid_be
-                             : packet,
-                         i, expected_error, error_code);
+    CheckProcessingFails(
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+            ? packet_cid_be
+            : packet,
+        i, expected_error, error_code);
   }
 }
 
@@ -3232,8 +3385,9 @@
   uint64_t header_size = GetPacketHeaderSize(
       framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER);
-  memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                                : packet) +
+  memset((QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet) +
              header_size + 1,
          0x00, kMaxPacketSize - header_size - 1);
 
@@ -3242,10 +3396,100 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? arraysize(packet_cid_be)
+          : arraysize(packet));
+}
+
+TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
+  if (framer_.version() <= QUIC_VERSION_37) {
+    return;
+  }
+  QuicPacketHeader header;
+  header.public_header.connection_id = kConnectionId;
+  header.public_header.reset_flag = false;
+  header.public_header.version_flag = false;
+  header.packet_number = kPacketNumber;
+
+  QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
+                               QuicStringPiece("hello world!"));
+  QuicPaddingFrame padding_frame(2);
+  QuicFrames frames = {QuicFrame(padding_frame), QuicFrame(&stream_frame),
+                       QuicFrame(padding_frame)};
+
+  // clang-format off
+  unsigned char packet[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0x10, 0x32, 0x54, 0x76,
+    0x98, 0xBA, 0xDC, 0xFE,
+    // packet number
+    0xBC, 0x9A, 0x78, 0x56,
+    0x34, 0x12,
+
+    // paddings
+    0x00, 0x00,
+    // frame type (stream frame with fin)
+    0xFF,
+    // stream id
+    0x04, 0x03, 0x02, 0x01,
+    // offset
+    0x54, 0x76, 0x10, 0x32,
+    0xDC, 0xFE, 0x98, 0xBA,
+    // data length
+    0x0c, 0x00,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+    // paddings
+    0x00, 0x00,
+  };
+
+  unsigned char packet_cid_be[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0xBC, 0x9A, 0x78, 0x56,
+    0x34, 0x12,
+
+    // paddings
+    0x00, 0x00,
+    // frame type (stream frame with fin)
+    0xFF,
+    // stream id
+    0x04, 0x03, 0x02, 0x01,
+    // offset
+    0x54, 0x76, 0x10, 0x32,
+    0xDC, 0xFE, 0x98, 0xBA,
+    // data length
+    0x0c, 0x00,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+    // paddings
+    0x00, 0x00,
+  };
+  // clang-format on
+
+  std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
+  ASSERT_TRUE(data != nullptr);
+
+  test::CompareCharArraysWithHexError(
+      "constructed packet", data->data(), data->length(),
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3292,8 +3536,9 @@
   uint64_t header_size = GetPacketHeaderSize(
       framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER);
-  memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                                : packet) +
+  memset((QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet) +
              header_size + 1,
          0x00, kMaxPacketSize - header_size - 1);
 
@@ -3302,10 +3547,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3352,8 +3598,9 @@
   uint64_t header_size = GetPacketHeaderSize(
       framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_2BYTE_PACKET_NUMBER);
-  memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                                : packet) +
+  memset((QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet) +
              header_size + 1,
          0x00, kMaxPacketSize - header_size - 1);
 
@@ -3362,10 +3609,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3412,8 +3660,9 @@
   uint64_t header_size = GetPacketHeaderSize(
       framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_1BYTE_PACKET_NUMBER);
-  memset((FLAGS_quic_restart_flag_quic_big_endian_connection_id ? packet_cid_be
-                                                                : packet) +
+  memset((QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet) +
              header_size + 1,
          0x00, kMaxPacketSize - header_size - 1);
 
@@ -3422,10 +3671,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3494,10 +3744,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3563,10 +3814,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3598,10 +3850,11 @@
                                             SupportedVersions(GetParam())));
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3670,10 +3923,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -3781,10 +4035,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4001,10 +4256,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4059,10 +4315,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4129,10 +4386,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4202,10 +4460,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4280,10 +4539,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4345,10 +4605,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4403,10 +4664,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4454,10 +4716,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4506,10 +4769,11 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet));
 }
@@ -4619,19 +4883,21 @@
   if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) {
     test::CompareCharArraysWithHexError(
         "constructed packet", data->data(), data->length(),
-        AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                    ? packet_no_rejected_packet_number_cid_be
-                    : packet_no_rejected_packet_number),
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id
+        AsChars(
+            QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+                ? packet_no_rejected_packet_number_cid_be
+                : packet_no_rejected_packet_number),
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
             ? arraysize(packet_no_rejected_packet_number_cid_be)
             : arraysize(packet_no_rejected_packet_number));
   } else {
     test::CompareCharArraysWithHexError(
         "constructed packet", data->data(), data->length(),
-        AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                    ? packet_cid_be
-                    : packet),
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id
+        AsChars(
+            QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+                ? packet_cid_be
+                : packet),
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
             ? arraysize(packet_cid_be)
             : arraysize(packet));
   }
@@ -4743,19 +5009,21 @@
   if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) {
     test::CompareCharArraysWithHexError(
         "constructed packet", data->data(), data->length(),
-        AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                    ? packet_no_rejected_packet_number_cid_be
-                    : packet_no_rejected_packet_number),
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id
+        AsChars(
+            QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+                ? packet_no_rejected_packet_number_cid_be
+                : packet_no_rejected_packet_number),
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
             ? arraysize(packet_no_rejected_packet_number_cid_be)
             : arraysize(packet_no_rejected_packet_number));
   } else {
     test::CompareCharArraysWithHexError(
         "constructed packet", data->data(), data->length(),
-        AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                    ? packet_cid_be
-                    : packet),
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id
+        AsChars(
+            QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+                ? packet_cid_be
+                : packet),
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
             ? arraysize(packet_cid_be)
             : arraysize(packet));
   }
@@ -4901,21 +5169,23 @@
   if (FLAGS_quic_reloadable_flag_quic_remove_packet_number_from_public_reset) {
     test::CompareCharArraysWithHexError(
         "constructed packet", data->data(), data->length(),
-        AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                    ? packet_no_rejected_packet_number_cid_be
-                    : packet_no_rejected_packet_number),
+        AsChars(
+            QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+                ? packet_no_rejected_packet_number_cid_be
+                : packet_no_rejected_packet_number),
 
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
             ? arraysize(packet_no_rejected_packet_number_cid_be)
             : arraysize(packet_no_rejected_packet_number));
   } else {
     test::CompareCharArraysWithHexError(
         "constructed packet", data->data(), data->length(),
-        AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                    ? packet_cid_be
-                    : packet),
+        AsChars(
+            QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+                ? packet_cid_be
+                : packet),
 
-        FLAGS_quic_restart_flag_quic_big_endian_connection_id
+        QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
             ? arraysize(packet_cid_be)
             : arraysize(packet));
   }
@@ -4959,10 +5229,11 @@
   // clang-format on
 
   std::unique_ptr<QuicPacket> raw(new QuicPacket(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false, PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
@@ -5017,10 +5288,11 @@
   // clang-format on
 
   std::unique_ptr<QuicPacket> raw(new QuicPacket(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false, PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
@@ -5227,10 +5499,11 @@
   EXPECT_CALL(visitor, OnDecryptedPacket(_));
 
   QuicEncryptedPacket encrypted(
-      AsChars(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                  ? packet_cid_be
-                  : packet),
-      FLAGS_quic_restart_flag_quic_big_endian_connection_id
+      AsChars(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+              ? packet_cid_be
+              : packet),
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
           ? arraysize(packet_cid_be)
           : arraysize(packet),
       false);
@@ -5404,12 +5677,13 @@
   };
   // clang-format on
 
-  QuicFramerFuzzFunc(FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                         ? packet_cid_be
-                         : packet,
-                     FLAGS_quic_restart_flag_quic_big_endian_connection_id
-                         ? arraysize(packet_cid_be)
-                         : arraysize(packet));
+  QuicFramerFuzzFunc(
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? packet_cid_be
+          : packet,
+      QuicUtils::IsConnectionIdWireFormatBigEndian(framer_.perspective())
+          ? arraysize(packet_cid_be)
+          : arraysize(packet));
 }
 
 }  // namespace test
diff --git a/net/quic/core/quic_packet_generator_test.cc b/net/quic/core/quic_packet_generator_test.cc
index 9908883..b7b4c7e 100644
--- a/net/quic/core/quic_packet_generator_test.cc
+++ b/net/quic/core/quic_packet_generator_test.cc
@@ -852,7 +852,7 @@
   delegate_.SetCanWriteAnything();
   QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame();
   frame->error_code = QUIC_PACKET_WRITE_ERROR;
-  char buf[2000];
+  char buf[2000] = {};
   QuicStringPiece error_details(buf, 2000);
   frame->error_details = error_details.as_string();
   EXPECT_CALL(delegate_,
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc
index ab7c9b35..453d3b7 100644
--- a/net/quic/core/quic_session.cc
+++ b/net/quic/core/quic_session.cc
@@ -44,9 +44,7 @@
                        config_.GetInitialSessionFlowControlWindowToSend(),
                        perspective() == Perspective::IS_SERVER,
                        nullptr),
-      currently_writing_stream_id_(0),
-      flow_control_invariant_(
-          FLAGS_quic_reloadable_flag_quic_flow_control_invariant) {}
+      currently_writing_stream_id_(0) {}
 
 void QuicSession::Initialize() {
   connection_->set_visitor(this);
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h
index d3f8dda..5eaa169 100644
--- a/net/quic/core/quic_session.h
+++ b/net/quic/core/quic_session.h
@@ -248,8 +248,6 @@
   // Returns true if this stream should yield writes to another blocked stream.
   bool ShouldYield(QuicStreamId stream_id);
 
-  bool flow_control_invariant() { return flow_control_invariant_; }
-
  protected:
   using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>;
 
@@ -441,9 +439,6 @@
   // call stack of OnCanWrite.
   QuicStreamId currently_writing_stream_id_;
 
-  // Latched value of quic_reloadable_flag_quic_flow_control_invariant.
-  const bool flow_control_invariant_;
-
   DISALLOW_COPY_AND_ASSIGN(QuicSession);
 };
 
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc
index a7ab1afe..d402b4e 100644
--- a/net/quic/core/quic_stream.cc
+++ b/net/quic/core/quic_stream.cc
@@ -70,9 +70,7 @@
                        GetReceivedFlowControlWindow(session),
                        GetInitialStreamFlowControlWindowToSend(session),
                        session_->flow_controller()->auto_tune_receive_window(),
-                       session_->flow_control_invariant()
-                           ? session_->flow_controller()
-                           : nullptr),
+                       session_->flow_controller()),
       connection_flow_controller_(session_->flow_controller()),
       stream_contributes_to_connection_flow_control_(true),
       busy_counter_(0) {
diff --git a/net/quic/core/quic_utils.cc b/net/quic/core/quic_utils.cc
index d68c55f..b7f3183 100644
--- a/net/quic/core/quic_utils.cc
+++ b/net/quic/core/quic_utils.cc
@@ -208,4 +208,12 @@
   return IPV4_TO_IPV4_CHANGE;
 }
 
+// static
+bool QuicUtils::IsConnectionIdWireFormatBigEndian(Perspective perspective) {
+  return (perspective == Perspective::IS_CLIENT &&
+          FLAGS_quic_restart_flag_quic_big_endian_connection_id_client) ||
+         (perspective == Perspective::IS_SERVER &&
+          FLAGS_quic_restart_flag_quic_big_endian_connection_id_server);
+}
+
 }  // namespace net
diff --git a/net/quic/core/quic_utils.h b/net/quic/core/quic_utils.h
index 723874f..7395722 100644
--- a/net/quic/core/quic_utils.h
+++ b/net/quic/core/quic_utils.h
@@ -59,6 +59,12 @@
       const QuicSocketAddress& old_address,
       const QuicSocketAddress& new_address);
 
+  // Returns whether connection id needs to be read/write in big endian.
+  // TODO(fayang): Remove this method once deprecating
+  // FLAGS_quic_restart_flag_quic_big_endian_connection_id_client and
+  // FLAGS_quic_restart_flag_quic_big_endian_connection_id_server.
+  static bool IsConnectionIdWireFormatBigEndian(Perspective perspective);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(QuicUtils);
 };
diff --git a/net/quic/core/quic_version_manager.cc b/net/quic/core/quic_version_manager.cc
index 0273015..7b11073 100644
--- a/net/quic/core/quic_version_manager.cc
+++ b/net/quic/core/quic_version_manager.cc
@@ -10,7 +10,8 @@
 namespace net {
 
 QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
-    : enable_version_38_(FLAGS_quic_enable_version_38),
+    : enable_version_39_(base::GetFlag(FLAGS_quic_enable_version_39)),
+      enable_version_38_(FLAGS_quic_reloadable_flag_quic_enable_version_38),
       enable_version_37_(FLAGS_quic_reloadable_flag_quic_enable_version_37),
       enable_version_36_(FLAGS_quic_reloadable_flag_quic_enable_version_36_v3),
       disable_version_34_(FLAGS_quic_reloadable_flag_quic_disable_version_34),
@@ -26,13 +27,15 @@
 }
 
 void QuicVersionManager::MaybeRefilterSupportedVersions() {
-  if (enable_version_38_ != FLAGS_quic_enable_version_38 ||
+  if (enable_version_39_ != base::GetFlag(FLAGS_quic_enable_version_39) ||
+      enable_version_38_ != FLAGS_quic_reloadable_flag_quic_enable_version_38 ||
       enable_version_37_ != FLAGS_quic_reloadable_flag_quic_enable_version_37 ||
       enable_version_36_ !=
           FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 ||
       disable_version_34_ !=
           FLAGS_quic_reloadable_flag_quic_disable_version_34) {
-    enable_version_38_ = FLAGS_quic_enable_version_38;
+    enable_version_39_ = base::GetFlag(FLAGS_quic_enable_version_39);
+    enable_version_38_ = FLAGS_quic_reloadable_flag_quic_enable_version_38;
     enable_version_37_ = FLAGS_quic_reloadable_flag_quic_enable_version_37;
     enable_version_36_ = FLAGS_quic_reloadable_flag_quic_enable_version_36_v3;
     disable_version_34_ = FLAGS_quic_reloadable_flag_quic_disable_version_34;
diff --git a/net/quic/core/quic_version_manager.h b/net/quic/core/quic_version_manager.h
index c1afef5..d6664b8 100644
--- a/net/quic/core/quic_version_manager.h
+++ b/net/quic/core/quic_version_manager.h
@@ -31,7 +31,9 @@
   }
 
  private:
-  // FLAGS_quic_enable_version_38
+  // FLAGS_quic_enable_version_39
+  bool enable_version_39_;
+  // FLAGS_quic_reloadable_flag_quic_enable_version_38
   bool enable_version_38_;
   // FLAGS_quic_reloadable_flag_quic_enable_version_37
   bool enable_version_37_;
diff --git a/net/quic/core/quic_version_manager_test.cc b/net/quic/core/quic_version_manager_test.cc
index 22faf09..bd259cb 100644
--- a/net/quic/core/quic_version_manager_test.cc
+++ b/net/quic/core/quic_version_manager_test.cc
@@ -16,8 +16,8 @@
 
 TEST(QuicVersionManagerTest, QuicVersionManager) {
   QuicFlagSaver flags;
-  FLAGS_quic_enable_version_38 = false;
   FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false;
+  FLAGS_quic_reloadable_flag_quic_enable_version_38 = false;
   FLAGS_quic_reloadable_flag_quic_enable_version_37 = false;
   FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
   QuicVersionManager manager(AllSupportedVersions());
@@ -41,7 +41,7 @@
   EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[2]);
   EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[3]);
 
-  FLAGS_quic_enable_version_38 = true;
+  FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
   EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
             manager.GetSupportedVersions());
   ASSERT_EQ(5u, manager.GetSupportedVersions().size());
@@ -51,14 +51,26 @@
   EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[3]);
   EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[4]);
 
+  base::SetFlag(&FLAGS_quic_enable_version_39, true);
+  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+            manager.GetSupportedVersions());
+  ASSERT_EQ(6u, manager.GetSupportedVersions().size());
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]);
+  EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[5]);
+
   FLAGS_quic_reloadable_flag_quic_disable_version_34 = true;
   EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
             manager.GetSupportedVersions());
-  ASSERT_EQ(4u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[2]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[3]);
+  ASSERT_EQ(5u, manager.GetSupportedVersions().size());
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]);
 }
 
 }  // namespace
diff --git a/net/quic/core/quic_versions.cc b/net/quic/core/quic_versions.cc
index a26aa2dd..6873776 100644
--- a/net/quic/core/quic_versions.cc
+++ b/net/quic/core/quic_versions.cc
@@ -30,8 +30,15 @@
   QuicVersionVector filtered_versions(versions.size());
   filtered_versions.clear();  // Guaranteed by spec not to change capacity.
   for (QuicVersion version : versions) {
-    if (version == QUIC_VERSION_38) {
-      if (FLAGS_quic_enable_version_38 &&
+    if (version == QUIC_VERSION_39) {
+      if (base::GetFlag(FLAGS_quic_enable_version_39) &&
+          FLAGS_quic_reloadable_flag_quic_enable_version_38 &&
+          FLAGS_quic_reloadable_flag_quic_enable_version_37 &&
+          FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) {
+        filtered_versions.push_back(version);
+      }
+    } else if (version == QUIC_VERSION_38) {
+      if (FLAGS_quic_reloadable_flag_quic_enable_version_38 &&
           FLAGS_quic_reloadable_flag_quic_enable_version_37 &&
           FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) {
         filtered_versions.push_back(version);
@@ -79,6 +86,8 @@
       return MakeQuicTag('Q', '0', '3', '7');
     case QUIC_VERSION_38:
       return MakeQuicTag('Q', '0', '3', '8');
+    case QUIC_VERSION_39:
+      return MakeQuicTag('Q', '0', '3', '9');
     default:
       // This shold be an ERROR because we should never attempt to convert an
       // invalid QuicVersion to be written to the wire.
@@ -110,6 +119,7 @@
     RETURN_STRING_LITERAL(QUIC_VERSION_36);
     RETURN_STRING_LITERAL(QUIC_VERSION_37);
     RETURN_STRING_LITERAL(QUIC_VERSION_38);
+    RETURN_STRING_LITERAL(QUIC_VERSION_39);
     default:
       return "QUIC_VERSION_UNSUPPORTED";
   }
diff --git a/net/quic/core/quic_versions.h b/net/quic/core/quic_versions.h
index 546f16b..9d3e457c 100644
--- a/net/quic/core/quic_versions.h
+++ b/net/quic/core/quic_versions.h
@@ -29,7 +29,9 @@
   QUIC_VERSION_35 = 35,  // Allows endpoints to independently set stream limit.
   QUIC_VERSION_36 = 36,  // Add support to force HOL blocking.
   QUIC_VERSION_37 = 37,  // Add perspective into null encryption.
-  QUIC_VERSION_38 = 38,  // Experimental support for HTTP stream pairs
+  QUIC_VERSION_38 = 38,  // PADDING frame is a 1-byte frame with type 0x00.
+                         // Respect NSTP connection option.
+  QUIC_VERSION_39 = 39,  // Experimental support for HTTP stream pairs
                          // and HPACK HoL avoidance.
 
   // IMPORTANT: if you are adding to this list, follow the instructions at
@@ -44,8 +46,8 @@
 // IMPORTANT: if you are adding to this list, follow the instructions at
 // http://sites/quic/adding-and-removing-versions
 static const QuicVersion kSupportedQuicVersions[] = {
-    QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_36, QUIC_VERSION_35,
-    QUIC_VERSION_34};
+    QUIC_VERSION_39, QUIC_VERSION_38, QUIC_VERSION_37,
+    QUIC_VERSION_36, QUIC_VERSION_35, QUIC_VERSION_34};
 
 typedef std::vector<QuicVersion> QuicVersionVector;
 
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index adf9df17a..d9e3da8 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -18,6 +18,7 @@
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packet_creator.h"
 #include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_logging.h"
 #include "net/quic/platform/api/quic_ptr_util.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
@@ -127,6 +128,15 @@
   }
 }
 
+QuicConnectionId GetPeerInMemoryConnectionId(QuicConnectionId connection_id) {
+  if (FLAGS_quic_restart_flag_quic_big_endian_connection_id_client ==
+      FLAGS_quic_restart_flag_quic_big_endian_connection_id_server) {
+    // Both endpoints have same endianess.
+    return connection_id;
+  }
+  return net::QuicEndian::NetToHost64(connection_id);
+}
+
 MockFramerVisitor::MockFramerVisitor() {
   // By default, we want to accept packets.
   ON_CALL(*this, OnProtocolVersionMismatch(_))
@@ -263,23 +273,29 @@
 MockQuicConnection::MockQuicConnection(MockQuicConnectionHelper* helper,
                                        MockAlarmFactory* alarm_factory,
                                        Perspective perspective)
-    : MockQuicConnection(kTestConnectionId,
-                         QuicSocketAddress(TestPeerIPAddress(), kTestPort),
-                         helper,
-                         alarm_factory,
-                         perspective,
-                         AllSupportedVersions()) {}
+    : MockQuicConnection(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(perspective)
+              ? QuicEndian::NetToHost64(kTestConnectionId)
+              : kTestConnectionId,
+          QuicSocketAddress(TestPeerIPAddress(), kTestPort),
+          helper,
+          alarm_factory,
+          perspective,
+          AllSupportedVersions()) {}
 
 MockQuicConnection::MockQuicConnection(QuicSocketAddress address,
                                        MockQuicConnectionHelper* helper,
                                        MockAlarmFactory* alarm_factory,
                                        Perspective perspective)
-    : MockQuicConnection(kTestConnectionId,
-                         address,
-                         helper,
-                         alarm_factory,
-                         perspective,
-                         AllSupportedVersions()) {}
+    : MockQuicConnection(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(perspective)
+              ? QuicEndian::NetToHost64(kTestConnectionId)
+              : kTestConnectionId,
+          address,
+          helper,
+          alarm_factory,
+          perspective,
+          AllSupportedVersions()) {}
 
 MockQuicConnection::MockQuicConnection(QuicConnectionId connection_id,
                                        MockQuicConnectionHelper* helper,
@@ -297,12 +313,15 @@
     MockAlarmFactory* alarm_factory,
     Perspective perspective,
     const QuicVersionVector& supported_versions)
-    : MockQuicConnection(kTestConnectionId,
-                         QuicSocketAddress(TestPeerIPAddress(), kTestPort),
-                         helper,
-                         alarm_factory,
-                         perspective,
-                         supported_versions) {}
+    : MockQuicConnection(
+          QuicUtils::IsConnectionIdWireFormatBigEndian(perspective)
+              ? QuicEndian::NetToHost64(kTestConnectionId)
+              : kTestConnectionId,
+          QuicSocketAddress(TestPeerIPAddress(), kTestPort),
+          helper,
+          alarm_factory,
+          perspective,
+          supported_versions) {}
 
 MockQuicConnection::MockQuicConnection(
     QuicConnectionId connection_id,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index a53d2fb..6c046d0 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -190,6 +190,10 @@
 // Compute SHA-1 hash of the supplied std::string.
 std::string Sha1Hash(QuicStringPiece data);
 
+// Given endpoint in memory |connection_id|, returns peer's in memory connection
+// id.
+QuicConnectionId GetPeerInMemoryConnectionId(QuicConnectionId connection_id);
+
 // Simple random number generator used to compute random numbers suitable
 // for pseudo-randomly dropping packets in tests.  It works by computing
 // the sha1 hash of the current seed, and using the first 64 bits as
diff --git a/net/quic/test_tools/simulator/quic_endpoint_test.cc b/net/quic/test_tools/simulator/quic_endpoint_test.cc
index 9962b55..5a13673 100644
--- a/net/quic/test_tools/simulator/quic_endpoint_test.cc
+++ b/net/quic/test_tools/simulator/quic_endpoint_test.cc
@@ -16,6 +16,7 @@
 using ::testing::_;
 using ::testing::NiceMock;
 using ::testing::Return;
+using net::test::GetPeerInMemoryConnectionId;
 
 namespace net {
 namespace simulator {
@@ -48,7 +49,8 @@
   QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
                           Perspective::IS_CLIENT, 42);
   QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
-                          Perspective::IS_SERVER, 42);
+                          Perspective::IS_SERVER,
+                          GetPeerInMemoryConnectionId(42));
   auto link_a = Link(&endpoint_a, switch_.port(1));
   auto link_b = Link(&endpoint_b, switch_.port(2));
 
@@ -83,7 +85,8 @@
   QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
                           Perspective::IS_CLIENT, 42);
   QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
-                          Perspective::IS_SERVER, 42);
+                          Perspective::IS_SERVER,
+                          GetPeerInMemoryConnectionId(42));
   auto link_a = Link(&endpoint_a, switch_.port(1));
   auto link_b = Link(&endpoint_b, switch_.port(2));
 
@@ -123,7 +126,8 @@
   QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
                           Perspective::IS_CLIENT, 42);
   QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
-                          Perspective::IS_SERVER, 42);
+                          Perspective::IS_SERVER,
+                          GetPeerInMemoryConnectionId(42));
   auto link_a = Link(&endpoint_a, switch_.port(1));
   auto link_b = Link(&endpoint_b, switch_.port(2));
 
@@ -153,11 +157,14 @@
   auto endpoint_c = QuicMakeUnique<QuicEndpoint>(
       &simulator_, "Endpoint C", "Endpoint D (C)", Perspective::IS_CLIENT, 44);
   auto endpoint_d_a = QuicMakeUnique<QuicEndpoint>(
-      &simulator_, "Endpoint D (A)", "Endpoint A", Perspective::IS_SERVER, 42);
+      &simulator_, "Endpoint D (A)", "Endpoint A", Perspective::IS_SERVER,
+      GetPeerInMemoryConnectionId(42));
   auto endpoint_d_b = QuicMakeUnique<QuicEndpoint>(
-      &simulator_, "Endpoint D (B)", "Endpoint B", Perspective::IS_SERVER, 43);
+      &simulator_, "Endpoint D (B)", "Endpoint B", Perspective::IS_SERVER,
+      GetPeerInMemoryConnectionId(43));
   auto endpoint_d_c = QuicMakeUnique<QuicEndpoint>(
-      &simulator_, "Endpoint D (C)", "Endpoint C", Perspective::IS_SERVER, 44);
+      &simulator_, "Endpoint D (C)", "Endpoint C", Perspective::IS_SERVER,
+      GetPeerInMemoryConnectionId(44));
   QuicEndpointMultiplexer endpoint_d(
       "Endpoint D",
       {endpoint_d_a.get(), endpoint_d_b.get(), endpoint_d_c.get()});
diff --git a/net/tools/quic/chlo_extractor_test.cc b/net/tools/quic/chlo_extractor_test.cc
index f314df67..df069ca 100644
--- a/net/tools/quic/chlo_extractor_test.cc
+++ b/net/tools/quic/chlo_extractor_test.cc
@@ -94,7 +94,8 @@
     EXPECT_TRUE(ChloExtractor::Extract(*packet_, versions, &delegate_))
         << QuicVersionToString(version);
     EXPECT_EQ(version, delegate_.version());
-    EXPECT_EQ(header_.public_header.connection_id, delegate_.connection_id());
+    EXPECT_EQ(GetPeerInMemoryConnectionId(header_.public_header.connection_id),
+              delegate_.connection_id());
     EXPECT_EQ(client_hello.DebugString(Perspective::IS_SERVER),
               delegate_.chlo())
         << QuicVersionToString(version);
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index e41e8bb..08d2e43 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -86,7 +86,9 @@
              QuicTag congestion_control_tag,
              bool disable_hpack_dynamic_table,
              bool force_hol_blocking,
-             bool use_cheap_stateless_reject)
+             bool use_cheap_stateless_reject,
+             bool connection_id_big_endian_client,
+             bool connection_id_big_endian_server)
       : client_supported_versions(client_supported_versions),
         server_supported_versions(server_supported_versions),
         negotiated_version(negotiated_version),
@@ -96,7 +98,9 @@
         congestion_control_tag(congestion_control_tag),
         disable_hpack_dynamic_table(disable_hpack_dynamic_table),
         force_hol_blocking(force_hol_blocking),
-        use_cheap_stateless_reject(use_cheap_stateless_reject) {}
+        use_cheap_stateless_reject(use_cheap_stateless_reject),
+        connection_id_big_endian_client(connection_id_big_endian_client),
+        connection_id_big_endian_server(connection_id_big_endian_server) {}
 
   friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
     os << "{ server_supported_versions: "
@@ -112,8 +116,11 @@
        << QuicTagToString(p.congestion_control_tag);
     os << " disable_hpack_dynamic_table: " << p.disable_hpack_dynamic_table;
     os << " force_hol_blocking: " << p.force_hol_blocking;
-    os << " use_cheap_stateless_reject: " << p.use_cheap_stateless_reject
-       << " }";
+    os << " use_cheap_stateless_reject: " << p.use_cheap_stateless_reject;
+    os << " connection_id_big_endian_client: "
+       << p.connection_id_big_endian_client;
+    os << " connection_id_big_endian_server: "
+       << p.connection_id_big_endian_server << " }";
     return os;
   }
 
@@ -126,6 +133,8 @@
   bool disable_hpack_dynamic_table;
   bool force_hol_blocking;
   bool use_cheap_stateless_reject;
+  bool connection_id_big_endian_client;
+  bool connection_id_big_endian_server;
 };
 
 // Constructs various test permutations.
@@ -152,7 +161,7 @@
 
   // This must be kept in sync with the number of nested for-loops below as it
   // is used to prune the number of tests that are run.
-  const int kMaxEnabledOptions = 5;
+  const int kMaxEnabledOptions = 7;
   int max_enabled_options = 0;
   std::vector<TestParams> params;
   for (bool server_uses_stateless_rejects_if_peer_supported : {true, false}) {
@@ -161,79 +170,96 @@
         for (bool disable_hpack_dynamic_table : {false}) {
           for (bool force_hol_blocking : {true, false}) {
             for (bool use_cheap_stateless_reject : {true, false}) {
-              int enabled_options = 0;
-              if (force_hol_blocking) {
-                ++enabled_options;
-              }
-              if (congestion_control_tag != kQBIC) {
-                ++enabled_options;
-              }
-              if (disable_hpack_dynamic_table) {
-                ++enabled_options;
-              }
-              if (client_supports_stateless_rejects) {
-                ++enabled_options;
-              }
-              if (server_uses_stateless_rejects_if_peer_supported) {
-                ++enabled_options;
-              }
-              if (use_cheap_stateless_reject) {
-                ++enabled_options;
-              }
-              CHECK_GE(kMaxEnabledOptions, enabled_options);
-              if (enabled_options > max_enabled_options) {
-                max_enabled_options = enabled_options;
-              }
+              for (bool connection_id_big_endian_client : {true, false}) {
+                for (bool connection_id_big_endian_server : {true, false}) {
+                  int enabled_options = 0;
+                  if (force_hol_blocking) {
+                    ++enabled_options;
+                  }
+                  if (congestion_control_tag != kQBIC) {
+                    ++enabled_options;
+                  }
+                  if (disable_hpack_dynamic_table) {
+                    ++enabled_options;
+                  }
+                  if (client_supports_stateless_rejects) {
+                    ++enabled_options;
+                  }
+                  if (server_uses_stateless_rejects_if_peer_supported) {
+                    ++enabled_options;
+                  }
+                  if (use_cheap_stateless_reject) {
+                    ++enabled_options;
+                  }
+                  if (connection_id_big_endian_server) {
+                    ++enabled_options;
+                  }
+                  if (connection_id_big_endian_client) {
+                    ++enabled_options;
+                  }
+                  CHECK_GE(kMaxEnabledOptions, enabled_options);
+                  if (enabled_options > max_enabled_options) {
+                    max_enabled_options = enabled_options;
+                  }
 
-              // Run tests with no options, a single option, or all the
-              // options enabled to avoid a combinatorial explosion.
-              if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) {
-                continue;
-              }
-
-              for (const QuicVersionVector& client_versions : version_buckets) {
-                CHECK(!client_versions.empty());
-                if (FilterSupportedVersions(client_versions).empty()) {
-                  continue;
-                }
-                // Add an entry for server and client supporting all
-                // versions.
-                params.push_back(TestParams(
-                    client_versions, all_supported_versions,
-                    client_versions.front(), client_supports_stateless_rejects,
-                    server_uses_stateless_rejects_if_peer_supported,
-                    congestion_control_tag, disable_hpack_dynamic_table,
-                    force_hol_blocking, use_cheap_stateless_reject));
-
-                // Run version negotiation tests tests with no options, or
-                // all the options enabled to avoid a combinatorial
-                // explosion.
-                if (enabled_options > 1 &&
-                    enabled_options < kMaxEnabledOptions) {
-                  continue;
-                }
-
-                // Test client supporting all versions and server supporting
-                // 1 version. Simulate an old server and exercise version
-                // downgrade in the client. Protocol negotiation should
-                // occur.  Skip the i = 0 case because it is essentially the
-                // same as the default case.
-                for (size_t i = 1; i < client_versions.size(); ++i) {
-                  QuicVersionVector server_supported_versions;
-                  server_supported_versions.push_back(client_versions[i]);
-                  if (FilterSupportedVersions(server_supported_versions)
-                          .empty()) {
+                  // Run tests with no options, a single option, or all the
+                  // options enabled to avoid a combinatorial explosion.
+                  if (enabled_options > 1 &&
+                      enabled_options < kMaxEnabledOptions) {
                     continue;
                   }
-                  params.push_back(TestParams(
-                      client_versions, server_supported_versions,
-                      server_supported_versions.front(),
-                      client_supports_stateless_rejects,
-                      server_uses_stateless_rejects_if_peer_supported,
-                      congestion_control_tag, disable_hpack_dynamic_table,
-                      force_hol_blocking, use_cheap_stateless_reject));
-                  }    // End of version for loop.
-                }      // End of 2nd version for loop.
+
+                  for (const QuicVersionVector& client_versions :
+                       version_buckets) {
+                    CHECK(!client_versions.empty());
+                    if (FilterSupportedVersions(client_versions).empty()) {
+                      continue;
+                    }
+                    // Add an entry for server and client supporting all
+                    // versions.
+                    params.push_back(TestParams(
+                        client_versions, all_supported_versions,
+                        client_versions.front(),
+                        client_supports_stateless_rejects,
+                        server_uses_stateless_rejects_if_peer_supported,
+                        congestion_control_tag, disable_hpack_dynamic_table,
+                        force_hol_blocking, use_cheap_stateless_reject,
+                        connection_id_big_endian_client,
+                        connection_id_big_endian_server));
+
+                    // Run version negotiation tests tests with no options, or
+                    // all the options enabled to avoid a combinatorial
+                    // explosion.
+                    if (enabled_options > 1 &&
+                        enabled_options < kMaxEnabledOptions) {
+                      continue;
+                    }
+
+                    // Test client supporting all versions and server supporting
+                    // 1 version. Simulate an old server and exercise version
+                    // downgrade in the client. Protocol negotiation should
+                    // occur.  Skip the i = 0 case because it is essentially the
+                    // same as the default case.
+                    for (size_t i = 1; i < client_versions.size(); ++i) {
+                      QuicVersionVector server_supported_versions;
+                      server_supported_versions.push_back(client_versions[i]);
+                      if (FilterSupportedVersions(server_supported_versions)
+                              .empty()) {
+                        continue;
+                      }
+                      params.push_back(TestParams(
+                          client_versions, server_supported_versions,
+                          server_supported_versions.front(),
+                          client_supports_stateless_rejects,
+                          server_uses_stateless_rejects_if_peer_supported,
+                          congestion_control_tag, disable_hpack_dynamic_table,
+                          force_hol_blocking, use_cheap_stateless_reject,
+                          connection_id_big_endian_client,
+                          connection_id_big_endian_server));
+                    }  // End of version for loop.
+                  }    // End of 2nd version for loop.
+                }      // End of connection_id_big_endian_server
+              }        // End of connection_id_big_endian_client
             }          // End of use_cheap_stateless_reject for loop.
           }            // End of force_hol_blocking loop.
         }              // End of disable_hpack_dynamic_table for loop.
@@ -306,6 +332,11 @@
 
     AddToCache("/foo", 200, kFooResponseBody);
     AddToCache("/bar", 200, kBarResponseBody);
+
+    FLAGS_quic_restart_flag_quic_big_endian_connection_id_client =
+        GetParam().connection_id_big_endian_client;
+    FLAGS_quic_restart_flag_quic_big_endian_connection_id_server =
+        GetParam().connection_id_big_endian_server;
   }
 
   ~EndToEndTest() override {
@@ -2030,7 +2061,8 @@
   QuicConnectionId connection_id =
       client_->client()->session()->connection()->connection_id();
   QuicPublicResetPacket header;
-  header.public_header.connection_id = connection_id;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(connection_id);
   header.public_header.reset_flag = true;
   header.public_header.version_flag = false;
   header.rejected_packet_number = 10101;
@@ -2063,7 +2095,8 @@
   QuicConnectionId incorrect_connection_id =
       client_->client()->session()->connection()->connection_id() + 1;
   QuicPublicResetPacket header;
-  header.public_header.connection_id = incorrect_connection_id;
+  header.public_header.connection_id =
+      GetPeerInMemoryConnectionId(incorrect_connection_id);
   header.public_header.reset_flag = true;
   header.public_header.version_flag = false;
   header.rejected_packet_number = 10101;
@@ -2128,8 +2161,9 @@
   QuicConnectionId incorrect_connection_id =
       client_->client()->session()->connection()->connection_id() + 1;
   std::unique_ptr<QuicEncryptedPacket> packet(
-      QuicFramer::BuildVersionNegotiationPacket(incorrect_connection_id,
-                                                server_supported_versions_));
+      QuicFramer::BuildVersionNegotiationPacket(
+          GetPeerInMemoryConnectionId(incorrect_connection_id),
+          server_supported_versions_));
   testing::NiceMock<MockQuicConnectionDebugVisitor> visitor;
   client_->client()->session()->connection()->set_debug_visitor(&visitor);
   EXPECT_CALL(visitor, OnIncorrectConnectionId(incorrect_connection_id))
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
index 1909450c..82c20e60 100644
--- a/net/tools/quic/quic_client_session_test.cc
+++ b/net/tools/quic/quic_client_session_test.cc
@@ -267,8 +267,9 @@
   // Verify that a non-decryptable packet doesn't close the connection.
   QuicConnectionId connection_id = session_->connection()->connection_id();
   std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
-      connection_id, false, false, 100, "data", PACKET_8BYTE_CONNECTION_ID,
-      PACKET_6BYTE_PACKET_NUMBER, nullptr, Perspective::IS_SERVER));
+      GetPeerInMemoryConnectionId(connection_id), false, false, 100, "data",
+      PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, nullptr,
+      Perspective::IS_SERVER));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*packet, QuicTime::Zero()));
   // Change the last byte of the encrypted data.
@@ -292,8 +293,9 @@
   QuicConnectionId connection_id = session_->connection()->connection_id();
   QuicVersionVector versions = {GetParam()};
   std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
-      connection_id, false, false, 100, "data", PACKET_8BYTE_CONNECTION_ID,
-      PACKET_6BYTE_PACKET_NUMBER, &versions, Perspective::IS_SERVER));
+      GetPeerInMemoryConnectionId(connection_id), false, false, 100, "data",
+      PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, &versions,
+      Perspective::IS_SERVER));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*packet, QuicTime::Zero()));
   EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index 7731031e..38a4445 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -211,7 +211,8 @@
               /*unused*/ QuicTime::Zero(),
               Perspective::IS_SERVER),
       last_error_(QUIC_NO_ERROR),
-      new_sessions_allowed_per_event_loop_(0u) {
+      new_sessions_allowed_per_event_loop_(0u),
+      accept_new_connections_(true) {
   framer_.set_visitor(this);
 }
 
@@ -363,7 +364,7 @@
     QuicPacketNumber packet_number) {
   switch (fate) {
     case kFateProcess: {
-      ProcessChlo();
+      ProcessChlo(packet_number);
       break;
     }
     case kFateTimeWait:
@@ -449,6 +450,10 @@
   session_map_.erase(it);
 }
 
+void QuicDispatcher::StopAcceptingNewConnections() {
+  accept_new_connections_ = false;
+}
+
 void QuicDispatcher::DeleteSessions() {
   closed_session_list_.clear();
 }
@@ -712,7 +717,19 @@
   }
 }
 
-void QuicDispatcher::ProcessChlo() {
+void QuicDispatcher::ProcessChlo(QuicPacketNumber packet_number) {
+  if (!accept_new_connections_) {
+    // Don't any create new connection.
+    time_wait_list_manager()->AddConnectionIdToTimeWait(
+        current_connection_id(), framer()->version(),
+        /*connection_rejected_statelessly=*/false,
+        /*termination_packets=*/nullptr);
+    // This will trigger sending Public Reset packet.
+    time_wait_list_manager()->ProcessPacket(
+        current_server_address(), current_client_address(),
+        current_connection_id(), packet_number, current_packet());
+    return;
+  }
   if (FLAGS_quic_reloadable_flag_quic_create_session_after_insertion &&
       !buffered_packets_.HasBufferedPackets(current_connection_id_) &&
       !ShouldCreateOrBufferPacketForConnection(current_connection_id_)) {
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 0edcf78..132cd28 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -204,7 +204,7 @@
 
   // Called when |current_packet_| is a CHLO packet. Creates a new connection
   // and delivers any buffered packets for that connection id.
-  void ProcessChlo();
+  void ProcessChlo(QuicPacketNumber packet_number);
 
   QuicTimeWaitListManager* time_wait_list_manager() {
     return time_wait_list_manager_.get();
@@ -274,19 +274,21 @@
       QuicBufferedPacketStore::EnqueuePacketResult result,
       QuicConnectionId connection_id);
 
+  // Removes the session from the session map and write blocked list, and adds
+  // the ConnectionId to the time-wait list.  If |session_closed_statelessly| is
+  // true, any future packets for the ConnectionId will be black-holed.
+  virtual void CleanUpSession(SessionMap::iterator it,
+                              QuicConnection* connection,
+                              bool session_closed_statelessly);
+
+  void StopAcceptingNewConnections();
+
  private:
   friend class test::QuicDispatcherPeer;
   friend class StatelessRejectorProcessDoneCallback;
 
   typedef std::unordered_set<QuicConnectionId> QuicConnectionIdSet;
 
-  // Removes the session from the session map and write blocked list, and adds
-  // the ConnectionId to the time-wait list.  If |session_closed_statelessly| is
-  // true, any future packets for the ConnectionId will be black-holed.
-  void CleanUpSession(SessionMap::iterator it,
-                      QuicConnection* connection,
-                      bool session_closed_statelessly);
-
   bool HandlePacketForTimeWait(const QuicPacketPublicHeader& header);
 
   // Attempts to reject the connection statelessly, if stateless rejects are
@@ -389,6 +391,9 @@
   // event loop. When reaches 0, it means can't create sessions for now.
   int16_t new_sessions_allowed_per_event_loop_;
 
+  // True if this dispatcher is not draining.
+  bool accept_new_connections_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicDispatcher);
 };
 
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index 384236a..3c78e671 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -249,8 +249,9 @@
                      QuicPacketNumber packet_number) {
     QuicVersionVector versions(SupportedVersions(version));
     std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
-        connection_id, has_version_flag, false, packet_number, data,
-        connection_id_length, packet_number_length, &versions));
+        GetPeerInMemoryConnectionId(connection_id), has_version_flag, false,
+        packet_number, data, connection_id_length, packet_number_length,
+        &versions));
     std::unique_ptr<QuicReceivedPacket> received_packet(
         ConstructReceivedPacket(*packet, helper_.GetClock()->Now()));
 
@@ -527,12 +528,13 @@
 }
 
 TEST_F(QuicDispatcherTest, SupportedVersionsChangeInFlight) {
-  static_assert(arraysize(kSupportedQuicVersions) == 5u,
+  static_assert(arraysize(kSupportedQuicVersions) == 6u,
                 "Supported versions out of sync");
   FLAGS_quic_reloadable_flag_quic_disable_version_34 = false;
   FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true;
   FLAGS_quic_reloadable_flag_quic_enable_version_37 = true;
-  FLAGS_quic_enable_version_38 = true;
+  FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
+  base::SetFlag(&FLAGS_quic_enable_version_39, true);
   QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
   server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
   QuicConnectionId connection_id = 1;
@@ -570,6 +572,33 @@
   ProcessPacket(client_address, connection_id, true, QuicVersionMax(),
                 SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
                 PACKET_6BYTE_PACKET_NUMBER, 1);
+
+  // Turn off version 39.
+  base::SetFlag(&FLAGS_quic_enable_version_39, false);
+  ++connection_id;
+  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+      .Times(0);
+  ProcessPacket(client_address, connection_id, true, QUIC_VERSION_39,
+                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+                PACKET_6BYTE_PACKET_NUMBER, 1);
+
+  // Turn on version 39.
+  base::SetFlag(&FLAGS_quic_enable_version_39, true);
+  ++connection_id;
+  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+      .WillOnce(testing::Return(CreateSession(
+          dispatcher_.get(), config_, connection_id, client_address,
+          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+  EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+              ProcessUdpPacket(_, _, _))
+      .WillOnce(testing::WithArgs<2>(
+          Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+                               base::Unretained(this), connection_id))));
+  ProcessPacket(client_address, connection_id, true, QUIC_VERSION_39,
+                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+                PACKET_6BYTE_PACKET_NUMBER, 1);
+
   // Turn off version 36.
   FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false;
   ++connection_id;
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index 0ff4f8d..6ff7b87 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -159,7 +159,8 @@
                                   std::tr1::get<1>(packet_buffer));
     framer.ProcessPacket(encrypted);
     QuicPublicResetPacket packet = visitor.public_reset_packet();
-    return connection_id_ == packet.public_header.connection_id &&
+    return connection_id_ == GetPeerInMemoryConnectionId(
+                                 packet.public_header.connection_id) &&
            packet.public_header.reset_flag &&
            !packet.public_header.version_flag &&
            packet_number_ == packet.rejected_packet_number &&
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/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 0e013c71..8603b4d 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -229,6 +229,44 @@
         "test": "cc_unittests"
       },
       {
+        "args": [
+          "--shared-prefs-file=../../chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
+          "--additional-apk=../../third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk"
+        ],
+        "override_compile_targets": [
+          "chrome_public_test_vr_apk"
+        ],
+        "override_isolate_target": "chrome_public_test_vr_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "chrome_public_test_vr_apk"
+      },
+      {
         "override_compile_targets": [
           "chrome_sync_shell_test_apk"
         ],
@@ -2294,6 +2332,46 @@
         "test": "chrome_public_test_apk"
       },
       {
+        "args": [
+          "--shared-prefs-file=../../chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
+          "--additional-apk=../../third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk"
+        ],
+        "override_compile_targets": [
+          "chrome_public_test_vr_apk"
+        ],
+        "override_isolate_target": "chrome_public_test_vr_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "expiration": 10800,
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "chrome_public_test_vr_apk"
+      },
+      {
         "override_compile_targets": [
           "chrome_sync_shell_test_apk"
         ],
@@ -2769,6 +2847,45 @@
       },
       {
         "args": [
+          "--shared-prefs-file=../../chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
+          "--additional-apk=../../third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk"
+        ],
+        "override_compile_targets": [
+          "chrome_public_test_vr_apk"
+        ],
+        "override_isolate_target": "chrome_public_test_vr_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "chrome_public_test_vr_apk"
+      },
+      {
+        "args": [
           "--enable-browser-side-navigation"
         ],
         "name": "browser_side_navigation_chrome_public_test_apk",
diff --git a/testing/buildbot/chromium.memory.full.json b/testing/buildbot/chromium.memory.full.json
deleted file mode 100644
index aaee5cab..0000000
--- a/testing/buildbot/chromium.memory.full.json
+++ /dev/null
@@ -1,625 +0,0 @@
-{
-  "Linux ChromeOS MSan Tests": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      }
-    ]
-  },
-  "Linux MSan Tests": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      }
-    ]
-  }
-}
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index b8d65ca..1e18c5e 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -4813,36 +4813,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "id": "build245-m4--device7",
-              "os": "Android",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -16540,36 +16510,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:22b1",
-              "id": "build141-b1",
-              "os": "Windows-10-10586",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -28187,36 +28127,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "1002:9874",
-              "id": "build205-b4",
-              "os": "Windows-10-10586",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index ee533c94..747eac1 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -4920,36 +4920,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "102b:0534",
-              "id": "build149-m1",
-              "os": "Ubuntu-14.04",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -16587,36 +16557,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0166",
-              "id": "build103-b1",
-              "os": "Mac-10.11",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -28214,36 +28154,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0a2e",
-              "id": "build159-m1",
-              "os": "Mac-10.12",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -39841,36 +39751,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:1626",
-              "id": "build124-b1",
-              "os": "Mac-10.11",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -51468,36 +51348,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0a26",
-              "id": "build25-b1",
-              "os": "Mac-10.12",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -63095,36 +62945,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "1002:6821",
-              "id": "build129-b1",
-              "os": "Mac-10.11",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -74722,36 +74542,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0d26",
-              "id": "build5-b1",
-              "os": "Mac-10.11",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -86349,36 +86139,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:1616",
-              "id": "build118-b1",
-              "os": "Windows-10-10240",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -97996,36 +97756,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
-              "os": "Windows-10-10240",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -109703,36 +109433,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "1002:6613",
-              "id": "build102-m1",
-              "os": "Windows-2008ServerR2-SP1",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -121390,36 +121090,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:041a",
-              "id": "build165-m1",
-              "os": "Windows-2008ServerR2-SP1",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -133097,36 +132767,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:104a",
-              "id": "build93-m1",
-              "os": "Windows-2008ServerR2-SP1",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -144784,36 +144424,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "102b:0532",
-              "id": "build186-m1",
-              "os": "Windows-2008ServerR2-SP1",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -156451,36 +156061,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "102b:0532",
-              "id": "build139-m1",
-              "os": "Windows-2008ServerR2-SP1",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -168138,36 +167718,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "102b:0532",
-              "id": "build144-m1",
-              "os": "Windows-2012ServerR2-SP0",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
@@ -179765,36 +179315,6 @@
       },
       {
         "args": [
-          "power.idle_platform",
-          "-v",
-          "--upload-results",
-          "--output-format=chartjson",
-          "--browser=reference",
-          "--output-trace-tag=_ref"
-        ],
-        "isolate_name": "telemetry_perf_tests",
-        "name": "power.idle_platform.reference",
-        "override_compile_targets": [
-          "telemetry_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:161e",
-              "id": "build31-b1",
-              "os": "Windows-10-10240",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 7200,
-          "ignore_task_failure": true,
-          "io_timeout": 3600
-        }
-      },
-      {
-        "args": [
           "power.steady_state",
           "-v",
           "--upload-results",
diff --git a/testing/clusterfuzz/OWNERS b/testing/clusterfuzz/OWNERS
index 70d27b6..104ea60 100644
--- a/testing/clusterfuzz/OWNERS
+++ b/testing/clusterfuzz/OWNERS
@@ -1,3 +1,5 @@
 inferno@chromium.org
 mmoroz@chromium.org
 ochang@chromium.org
+
+# COMPONENT: Tools>Stability>Clusterfuzz
diff --git a/testing/libfuzzer/OWNERS b/testing/libfuzzer/OWNERS
index 62642811..db0983f92 100644
--- a/testing/libfuzzer/OWNERS
+++ b/testing/libfuzzer/OWNERS
@@ -3,3 +3,5 @@
 kcc@chromium.org
 krasin@chromium.org
 mmoroz@chromium.org
+
+# COMPONENT: Tools>Stability>Clusterfuzz
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 7f9d0b1a..10b7205 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -125,6 +125,19 @@
 
 # ====== Paint team owned tests to here ======
 
+# ====== Layout team owned tests from here ======
+
+#### external/wpt/css/CSS2/floats
+#### Passed: 37
+#### Skipped: 5
+crbug.com/711704 external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht [ Skip ]
+crbug.com/711704 external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht [ Skip ]
+crbug.com/711704 external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht [ Skip ]
+crbug.com/711704 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Skip ]
+crbug.com/711704 external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht [ Skip ]
+
+# ====== Layout team owned tests to here ======
+
 # ====== LayoutNG-only failures from here ======
 # LayoutNG - is a new layout system for Blink.
 
@@ -1546,8 +1559,8 @@
 
 crbug.com/545140 [ Mac10.10 Mac10.11 Retina Mac10.12 ] fast/encoding/denormalised-voiced-japanese-chars.html [ Failure ]
 
-crbug.com/636248 [ Mac ] http/tests/security/img-crossorigin-no-credentials-prompt.html [ Failure Pass ]
-crbug.com/636248 [ Mac ] virtual/mojo-loading/http/tests/security/img-crossorigin-no-credentials-prompt.html [ Failure Pass ]
+crbug.com/636248 http/tests/security/img-crossorigin-no-credentials-prompt.html [ Failure Pass ]
+crbug.com/636248 virtual/mojo-loading/http/tests/security/img-crossorigin-no-credentials-prompt.html [ Failure Pass ]
 
 crbug.com/509025 [ Mac10.10 ] fast/events/context-no-deselect.html [ Failure ]
 crbug.com/509025 [ Mac10.10 ] virtual/rootlayerscrolls/scrollbars/rtl/overflow-scroll-rtl.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 365a96b..b13c59f 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -82,7 +82,8 @@
 external/wpt/css/CSS2/css1 [ Skip ]
 external/wpt/css/CSS2/css21-errata [ Skip ]
 external/wpt/css/CSS2/csswg-issues [ Skip ]
-external/wpt/css/CSS2/floats [ Skip ]
+## Owners: glebl@chromium.org
+# external/wpt/css/CSS2/floats [ Pass ]
 external/wpt/css/CSS2/floats-clear [ Skip ]
 external/wpt/css/CSS2/fonts [ Skip ]
 external/wpt/css/CSS2/generate [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001-ref.xht
new file mode 100644
index 0000000..15ff213
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001-ref.xht
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for float placement rules (reference)</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+.left { float:left; }
+.right { float:right; }
+.left, .right { width:50px; height:50px; background:yellow; }
+p { overflow:auto; }
+</style>
+</head>
+<body style="width:400px;">
+<p><span class="left"></span>HelloKitty
+</p><p><span class="right"></span>HelloKitty
+</p><p dir="rtl"><span class="left"></span>HelloKitty
+</p><p dir="rtl"><span class="right"></span>HelloKitty
+</p><p style="text-align:right;"><span class="left"></span>HelloKitty
+</p><p style="text-align:right;"><span class="right"></span>HelloKitty
+
+
+</p></body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001a.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001a.xht
new file mode 100644
index 0000000..07de028
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001a.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for float placement rules</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#float-position" />
+<link rel="match" href="floats-placement-vertical-001-ref.xht"/>
+<meta name="assert" content="A floating box must be placed as high as possible. " />
+<meta name="flags" content="" />
+<style type="text/css">
+.left { float:left; }
+.right { float:right; }
+.left, .right { width:50px; height:50px; background:yellow; }
+p { overflow:auto; }
+</style>
+</head>
+<body style="width:400px;">
+<p>Hello<span class="left"></span>Kitty
+</p><p>Hello<span class="right"></span>Kitty
+</p><p dir="rtl">Hello<span class="left"></span>Kitty
+</p><p dir="rtl">Hello<span class="right"></span>Kitty
+</p><p style="text-align:right;">Hello<span class="left"></span>Kitty
+</p><p style="text-align:right;">Hello<span class="right"></span>Kitty
+
+
+</p></body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001b.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001b.xht
new file mode 100644
index 0000000..233cda23
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001b.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for float placement rules</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#float-position" />
+<link rel="match" href="floats-placement-vertical-001-ref.xht"/>
+<meta name="assert" content="A floating box must be placed as high as possible. " />
+<meta name="flags" content="" />
+<style type="text/css">
+.left { float:left; }
+.right { float:right; }
+.left, .right { width:50px; height:50px; background:yellow; }
+p { overflow:auto; }
+</style>
+</head>
+<body style="width:400px">
+<p><span>Hello<span class="left"></span></span>Kitty
+</p><p><span>Hello<span class="right"></span></span>Kitty
+</p><p dir="rtl"><span>Hello<span class="left"></span></span>Kitty
+</p><p dir="rtl"><span>Hello<span class="right"></span></span>Kitty
+</p><p style="text-align:right;"><span>Hello<span class="left"></span></span>Kitty
+</p><p style="text-align:right;"><span>Hello<span class="right"></span></span>Kitty
+
+
+</p></body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001c.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001c.xht
new file mode 100644
index 0000000..894cb01
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-001c.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for float placement rules</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#float-position" />
+<link rel="match" href="floats-placement-vertical-001-ref.xht"/>
+<meta name="assert" content="A floating box must be placed as high as possible. " />
+<meta name="flags" content="" />
+<style type="text/css">
+.left { float:left; }
+.right { float:right; }
+.left, .right { width:50px; height:50px; background:yellow; }
+p { overflow:auto; }
+</style>
+</head>
+<body style="width:400px;">
+<p>Hello<span><span class="left"></span>Kitty</span>
+</p><p>Hello<span><span class="right"></span>Kitty</span>
+</p><p dir="rtl">Hello<span><span class="left"></span>Kitty</span>
+</p><p dir="rtl">Hello<span><span class="right"></span>Kitty</span>
+</p><p style="text-align:right;">Hello<span><span class="left"></span>Kitty</span>
+</p><p style="text-align:right;">Hello<span><span class="right"></span>Kitty</span>
+
+
+</p></body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-003-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-003-ref.xht
new file mode 100644
index 0000000..f89b9e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-003-ref.xht
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: Test for float placement rules (reference)</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+</head><body style="width:100px; font-size:5px;">
+<!-- Check that we don't allow floats to reorder -->
+H
+<div style="background:blue; width:100px; height:100px;"></div>
+<div style="background:yellow; width:30px; height:30px; float:left;"></div>
+<div style="background:yellow; width:30px; height:30px; float:right;"></div>
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-003.xht
new file mode 100644
index 0000000..bad9d39b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-003.xht
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: Test for float placement rules</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#float-position" />
+<link rel="match" href="floats-placement-vertical-003-ref.xht"/>
+<meta name="assert" content="The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document." />
+<meta name="assert" content="A floating box must be placed as high as possible. " />
+<meta name="flags" content="" />
+</head><body style="width:100px; font-size:5px;">
+<!-- Check that we don't allow floats to reorder -->
+H
+<div style="background:blue; width:100px; height:100px; float:left;"></div>
+<div style="background:yellow; width:30px; height:30px; float:left;"></div>
+<div style="background:yellow; width:30px; height:30px; float:right;"></div>
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004-ref.xht
new file mode 100644
index 0000000..9e2cd46
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004-ref.xht
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: Test for float placement rules (reference)</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="match" href="floats-placement-vertical-004-ref2.xht"/>
+</head><body style="width:200px; font-size:5px;">
+<div style="background:green; width:100px; height:100px; float:left;"></div>
+H<br />
+<div style="background:blue; width:100px; height:100px; float:left;"></div>
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004-ref2.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004-ref2.xht
new file mode 100644
index 0000000..97b2630
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004-ref2.xht
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: Test for float placement rules (reference)</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="match" href="floats-placement-vertical-004-ref.xht"/>
+</head><body style="width:200px; font-size:5px;">
+<div style="position:absolute; background:green; width:100px; height:100px;"></div>
+<div style="position:relative; left:100px; width:100px; height:100px;">
+  H
+  <div style="background:blue; width:100px; height:100px;"></div>
+</div>
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004.xht
new file mode 100644
index 0000000..d629f5a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-placement-vertical-004.xht
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: Test for float placement rules</title>
+<link rel="author" title="Robert O'Callahan" href="mailto:robert@ocallahan.org" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#float-position" />
+<link rel="match" href="floats-placement-vertical-004-ref.xht"/>
+<meta name="assert" content="A floating box must be placed as high as possible. " />
+<meta name="flags" content="" />
+</head><body style="width:200px; font-size:5px;">
+<!-- Check that we're actually taking inline content already in the line into account
+     when we check whether the blue float fits -->
+<div style="background:green; width:100px; height:100px; float:left;"></div>
+H
+<div style="background:blue; width:100px; height:100px; float:left;"></div>
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-001-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-001-ref.xht
new file mode 100644
index 0000000..a401cd41
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-001-ref.xht
@@ -0,0 +1,6 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Test for float placement around other float in BFC but outside containing block</title>
+
+</head><body><div style="float: left; width: 500px; height: 500px">
+  <div style="width: 425px; height: 10px; background: blue"></div>
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-001.xht
new file mode 100644
index 0000000..8a510dd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-001.xht
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: float placement around other float in BFC but outside containing block</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-rule3-outside-left-001-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="Test for float placement around other float in BFC but outside containing block" />
+
+<!--
+  CSS2.1 9.5.1 rule 3 says:
+
+    The right outer edge of a left-floating box may not be to the right
+    of the left outer edge of any right-floating box that is to the
+    right of it. Analogous rules hold for right-floating elements.
+
+ -->
+
+<!-- the block formatting context inside which we're testing -->
+</head><body><div style="float: left; width: 500px; height: 500px">
+
+  <div style="float: right; width: 50px; height: 300px"></div>
+
+  <div style="margin-right: 100px"> <!-- 400px wide -->
+
+    <!-- we're testing the position of this float -->
+    <div style="float: left; width: 425px; height: 10px; background: blue"></div>
+
+  </div>
+
+</div>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-002-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-002-ref.xht
new file mode 100644
index 0000000..f16aba29
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-002-ref.xht
@@ -0,0 +1,5 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Test for float placement around other float in BFC but outside containing block</title>
+</head><body><div style="float: left; width: 500px; height: 500px">
+    <div style="margin-top: 300px; width: 475px; height: 10px; background: blue"></div>
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht
new file mode 100644
index 0000000..c9965f8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: float placement around other float in BFC but outside containing block</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-rule3-outside-left-002-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="Test for float placement around other float in BFC but outside containing block" />
+
+<!--
+  CSS2.1 9.5.1 rule 3 says:
+
+    The right outer edge of a left-floating box may not be to the right
+    of the left outer edge of any right-floating box that is to the
+    right of it. Analogous rules hold for right-floating elements.
+
+ -->
+
+<!-- the block formatting context inside which we're testing -->
+</head><body><div style="float: left; width: 500px; height: 500px">
+
+  <div style="float: right; width: 50px; height: 300px"></div>
+
+  <div style="margin-right: 100px"> <!-- 400px wide -->
+
+    <!-- we're testing the position of this float -->
+    <div style="float: left; width: 475px; height: 10px; background: blue"></div>
+
+  </div>
+
+</div>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-001-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-001-ref.xht
new file mode 100644
index 0000000..1495741
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-001-ref.xht
@@ -0,0 +1,5 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Test for float placement around other float in BFC but outside containing block</title>
+</head><body><div style="float: left; width: 500px; height: 500px">
+  <div style="margin-left: 75px; width: 425px; height: 10px; background: blue"></div>
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-001.xht
new file mode 100644
index 0000000..6ab45db
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-001.xht
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: float placement around other float in BFC but outside containing block</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-rule3-outside-right-001-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="Test for float placement around other float in BFC but outside containing block" />
+
+<!--
+  CSS2.1 9.5.1 rule 3 says:
+
+    The right outer edge of a left-floating box may not be to the right
+    of the left outer edge of any right-floating box that is to the
+    right of it. Analogous rules hold for right-floating elements.
+
+ -->
+
+<!-- the block formatting context inside which we're testing -->
+</head><body><div style="float: left; width: 500px; height: 500px">
+
+  <div style="float: left; width: 50px; height: 300px"></div>
+
+  <div style="margin-left: 100px"> <!-- 400px wide -->
+
+    <!-- we're testing the position of this float -->
+    <div style="float: right; width: 425px; height: 10px; background: blue"></div>
+
+  </div>
+
+</div>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-002-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-002-ref.xht
new file mode 100644
index 0000000..e95714e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-002-ref.xht
@@ -0,0 +1,5 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Test for float placement around other float in BFC but outside containing block</title>
+</head><body><div style="float: left; width: 500px; height: 500px">
+    <div style="margin-top: 300px; margin-left: 25px; width: 475px; height: 10px; background: blue"></div>
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht
new file mode 100644
index 0000000..b17fcedb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: float placement around other float in BFC but outside containing block</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-rule3-outside-right-002-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="Test for float placement around other float in BFC but outside containing block" />
+
+<!--
+  CSS2.1 9.5.1 rule 3 says:
+
+    The right outer edge of a left-floating box may not be to the right
+    of the left outer edge of any right-floating box that is to the
+    right of it. Analogous rules hold for right-floating elements.
+
+ -->
+
+<!-- the block formatting context inside which we're testing -->
+</head><body><div style="float: left; width: 500px; height: 500px">
+
+  <div style="float: left; width: 50px; height: 300px"></div>
+
+  <div style="margin-left: 100px"> <!-- 400px wide -->
+
+    <!-- we're testing the position of this float -->
+    <div style="float: right; width: 475px; height: 10px; background: blue"></div>
+
+  </div>
+
+</div>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-left-001-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-left-001-ref.xht
new file mode 100644
index 0000000..546e2ae4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-left-001-ref.xht
@@ -0,0 +1,5 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Test for float placement around other float in BFC but outside containing block</title>
+</head><body><div style="float: left; width: 500px; height: 500px">
+    <div style="margin-top: 300px; margin-left: 100px; width: 425px; height: 10px; background: blue"></div>
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht
new file mode 100644
index 0000000..a6494d2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: float placement around other float in BFC but outside containing block</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-rule7-outside-left-001-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="Test for float placement around other float in BFC but outside containing block" />
+
+<!--
+  CSS2.1 9.5.1 rule 7 says:
+
+    A left-floating box that has another left-floating box to its left
+    may not have its right outer edge to the right of its containing
+    block's right edge. (Loosely: a left float may not stick out at the
+    right edge, unless it is already as far to the left as possible.) An
+    analogous rule holds for right-floating elements.
+
+ -->
+
+<!-- the block formatting context inside which we're testing -->
+</head><body><div style="float: left; width: 500px; height: 500px">
+
+  <div style="float: left; width: 50px; height: 300px"></div>
+
+  <div style="margin-left: 100px"> <!-- 400px wide -->
+
+    <!-- we're testing the position of this float -->
+    <div style="float: left; width: 425px; height: 10px; background: blue"></div>
+
+  </div>
+
+</div>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-right-001-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-right-001-ref.xht
new file mode 100644
index 0000000..69e1a26
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-right-001-ref.xht
@@ -0,0 +1,5 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Test for float placement around other float in BFC but outside containing block</title>
+</head><body><div style="float: left; width: 500px; height: 500px">
+    <div style="margin-top: 300px; margin-left: -25px; width: 425px; height: 10px; background: blue"></div>
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht
new file mode 100644
index 0000000..0ebd9a62
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: float placement around other float in BFC but outside containing block</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-rule7-outside-right-001-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="Test for float placement around other float in BFC but outside containing block" />
+
+<!--
+  CSS2.1 9.5.1 rule 7 says:
+
+    A left-floating box that has another left-floating box to its left
+    may not have its right outer edge to the right of its containing
+    block's right edge. (Loosely: a left float may not stick out at the
+    right edge, unless it is already as far to the left as possible.) An
+    analogous rule holds for right-floating elements.
+
+ -->
+
+<!-- the block formatting context inside which we're testing -->
+</head><body><div style="float: left; width: 500px; height: 500px">
+
+  <div style="float: right; width: 50px; height: 300px"></div>
+
+  <div style="margin-right: 100px"> <!-- 400px wide -->
+
+    <!-- we're testing the position of this float -->
+    <div style="float: right; width: 425px; height: 10px; background: blue"></div>
+
+  </div>
+
+</div>
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-overflow-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-overflow-ref.xht
new file mode 100644
index 0000000..9d4c968
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-overflow-ref.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:yellow; width: 200px; height: 50px">
+    <div style="background:purple; width: 150px; height: 50px"></div>
+  </div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-overflow.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-overflow.xht
new file mode 100644
index 0000000..becaa112
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-overflow.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-001-left-overflow-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+
+  <div style="overflow: hidden; background: yellow">
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </div>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-table-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-table-ref.xht
new file mode 100644
index 0000000..4b3b439c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-table-ref.xht
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:purple; width: 150px; height: 50px"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-table.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-table.xht
new file mode 100644
index 0000000..82ebc88
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-left-table.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-001-left-table-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+
+  <table style="background: yellow"><tbody><tr><td>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </td></tr></tbody></table>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-overflow-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-overflow-ref.xht
new file mode 100644
index 0000000..00fc8fe6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-overflow-ref.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:yellow; width: 200px; height: 50px">
+    <div style="background:purple; width: 150px; height: 50px"></div>
+  </div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-overflow.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-overflow.xht
new file mode 100644
index 0000000..c9ab2da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-overflow.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-001-right-overflow-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+
+  <div style="overflow: hidden; background: yellow">
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </div>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-table-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-table-ref.xht
new file mode 100644
index 0000000..0b98fa08
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-table-ref.xht
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:purple; width: 150px; height: 50px"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-table.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-table.xht
new file mode 100644
index 0000000..0735d33
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-001-right-table.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-001-right-table-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+
+  <table style="background: yellow"><tbody><tr><td>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </td></tr></tbody></table>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-overflow.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-overflow.xht
new file mode 100644
index 0000000..0aca5326
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-overflow.xht
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-002-left-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+
+  <div style="overflow: hidden; background: yellow">
+    <span style="width: 150px; height: 50px; background: purple"></span>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </div>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-ref.xht
new file mode 100644
index 0000000..b118e94f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-ref.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:yellow; width: 200px; height: 100px">
+    <div style="background:purple; width: 150px; height: 100px"></div>
+  </div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-table.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-table.xht
new file mode 100644
index 0000000..7c69ac0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-left-table.xht
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-002-left-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+
+  <table style="background: yellow"><tbody><tr><td>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </td></tr></tbody></table>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-overflow.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-overflow.xht
new file mode 100644
index 0000000..39029f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-overflow.xht
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-002-right-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+
+  <div style="overflow: hidden; background: yellow">
+    <span style="width: 150px; height: 50px; background: purple"></span>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </div>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-ref.xht
new file mode 100644
index 0000000..bb377456
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-ref.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:yellow; width: 200px; height: 100px">
+    <div style="background:purple; width: 150px; height: 100px"></div>
+  </div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-table.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-table.xht
new file mode 100644
index 0000000..56bbf09
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-002-right-table.xht
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-002-right-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+
+  <table style="background: yellow"><tbody><tr><td>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+    <span style="width: 150px; height: 50px; background: purple"></span>
+  </td></tr></tbody></table>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-overflow-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-overflow-ref.xht
new file mode 100644
index 0000000..41ed0d3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-overflow-ref.xht
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:purple; width: 200px; height: 50px"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-overflow.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-overflow.xht
new file mode 100644
index 0000000..17702f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-overflow.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-003-left-overflow-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+
+  <div style="overflow: hidden; background: yellow">
+    <span style="width: 250px; height: 50px; background: purple"></span>
+  </div>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-table-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-table-ref.xht
new file mode 100644
index 0000000..e9ddad7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-table-ref.xht
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 150px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; clear:left; background:purple; width: 250px; height: 50px"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-table.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-table.xht
new file mode 100644
index 0000000..91e1405
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-table.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-003-left-table-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:left; background:blue; width: 100px; height: 100px"></div>
+
+  <table style="background: yellow"><tbody><tr><td>
+    <span style="width: 250px; height: 50px; background: purple"></span>
+  </td></tr></tbody></table>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-overflow-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-overflow-ref.xht
new file mode 100644
index 0000000..42c7861
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-overflow-ref.xht
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 100px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; background:purple; width: 200px; height: 50px"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-overflow.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-overflow.xht
new file mode 100644
index 0000000..08f237b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-overflow.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-003-right-overflow-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+
+  <div style="overflow: hidden; background: yellow">
+    <span style="width: 250px; height: 50px; background: purple"></span>
+  </div>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-table-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-table-ref.xht
new file mode 100644
index 0000000..768355e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-table-ref.xht
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 150px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+  <div style="float:left; clear:right; background:purple; width: 250px; height: 50px"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-table.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-table.xht
new file mode 100644
index 0000000..2cf65fc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-table.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-003-right-table-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	span { display: inline-block; vertical-align: bottom; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+
+  <div style="float:right; background:blue; width: 100px; height: 100px"></div>
+
+  <table style="background: yellow"><tbody><tr><td>
+    <span style="width: 250px; height: 50px; background: purple"></span>
+  </td></tr></tbody></table>
+
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-004-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-004-ref.xht
new file mode 100644
index 0000000..fede0e5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-004-ref.xht
@@ -0,0 +1,60 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+</head>
+<body>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 150px; height: 10px; background: purple"></div>
+</div>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 150px; height: 10px; background: purple"></div>
+</div>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 150px; height: 10px; background: purple"></div>
+</div>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 150px; height: 10px; background: purple"></div>
+</div>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 100px; height: 10px; background: purple"></div>
+</div>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 100px; height: 10px; background: purple"></div>
+</div>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 100px; height: 10px; background: purple"></div>
+</div>
+
+<div style="width: 300px; height: 20px; background: aqua">
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <div style="float:left; width: 100px; height: 10px; background: purple"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-004.xht
new file mode 100644
index 0000000..0e92613
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-004.xht
@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-004-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <table style="background: yellow"><tbody><tr><td>
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </td></tr></tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <table style="background: yellow"><tbody><tr><td>
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </td></tr></tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <table style="background: yellow"><tbody><tr><td>
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </td></tr></tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <table style="background: yellow"><tbody><tr><td>
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </td></tr></tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <div style="overflow: hidden; background: yellow">
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:left; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <div style="overflow: hidden; background: yellow">
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:left; background:silver; width: 100px; height: 6px"></div>
+  <div style="overflow: hidden; background: yellow">
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:right; background:blue; width: 100px; height: 20px"></div>
+  <div style="float:right; background:silver; width: 100px; height: 6px"></div>
+  <div style="overflow: hidden; background: yellow">
+    <div style="width: 150px; height: 10px; background: purple"></div>
+  </div>
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-005-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-005-ref.xht
new file mode 100644
index 0000000..bb3190d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-005-ref.xht
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	body { font-size: 10px; }
+
+	</style>
+</head>
+<body>
+
+<div style="width: 300px; height: 40px;background: aqua">
+  <div style="float:left; background:blue; width: 200px; height: 20px"></div>
+  <div style="float:left; clear: left; background: yellow; width: 150px; height: 20px">50%</div>
+</div>
+
+<div style="width: 300px; height: 40px;background: aqua">
+  <div style="float:right; background:blue; width: 200px; height: 20px"></div>
+  <div style="float:left; clear: right; background: yellow; width: 150px; height: 20px">50%</div>
+</div>
+
+<div style="width: 300px; height: 40px;background: aqua">
+  <div style="float:left; background:blue; width: 200px; height: 20px"></div>
+  <div style="float:left; clear: left; background: yellow; width: 150px; height: 20px">50%</div>
+</div>
+
+<div style="width: 300px; height: 40px;background: aqua">
+  <div style="float:right; background:blue; width: 200px; height: 20px"></div>
+  <div style="float:left; clear: right; background: yellow; width: 150px; height: 20px">50%</div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-005.xht
new file mode 100644
index 0000000..341c668
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-005.xht
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-005-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	body { font-size: 10px; }
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; vertical-align: top; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:left; background:blue; width: 200px; height: 20px"></div>
+  <table width="50%" style="background: yellow" height="20"><tbody><tr><td>50%</td></tr></tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:right; background:blue; width: 200px; height: 20px"></div>
+  <table width="50%" style="background: yellow" height="20"><tbody><tr><td>50%</td></tr></tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:left; background:blue; width: 200px; height: 20px"></div>
+  <div style="overflow:hidden; background: yellow; width: 50%; height: 20px;">50%</div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+  <div style="float:right; background:blue; width: 200px; height: 20px"></div>
+  <div style="overflow:hidden; background: yellow; width: 50%; height: 20px;">50%</div>
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-006-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-006-ref.xht
new file mode 100644
index 0000000..59051f8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-006-ref.xht
@@ -0,0 +1,177 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	body { font-size: 16px; }
+
+	table { margin: 0; border-spacing: 0; }
+	caption, td, th { padding: 0; vertical-align: top; text-align: left; }
+
+	.capref { background: yellow; }
+	.tabref { background: purple; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+
+    <div style="float:right; height: 30px; width: 100px; margin-right: 130px;" class="capref">Caption</div>
+
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+
+    <div style="float:right; clear: right; height: 30px; width: 230px;" class="tabref">Cell</div>
+
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+
+    <div style="float:right; height: 30px; width: 190px;" class="capref">Caption</div>
+
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+
+    <div style="float:right; clear: right; height: 30px; width: 100px; margin-right: 90px;" class="tabref">Cell</div>
+
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+
+    <div style="float:right; clear: right; height: 30px; width: 227px;margin-right:3px;" class="tabref">Cell</div>
+
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+
+    <div style="float:right; clear: right; height: 30px; width: 100px;margin-right:130px;" class="capref">Caption</div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+
+    <div style="float:right; clear: right; height: 30px; width: 100px; margin-right:95px;" class="tabref">Cell</div>
+
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+
+    <div style="float:right; clear: right; height: 30px; width: 192px; margin-right:3px;" class="capref">Caption</div>
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht
new file mode 100644
index 0000000..1ecef61
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht
@@ -0,0 +1,175 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-006-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	body { font-size: 16px; }
+
+	table { margin: 0; border-spacing: 0; }
+	caption, td, th { padding: 0; vertical-align: top; text-align: left; }
+
+	table table caption { background: yellow; }
+	table table { background: purple; }
+
+	</style>
+</head>
+<body>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+    <table>
+        <caption style="caption-side: top; height:30px; width: 100px;">Caption</caption>
+        <tbody><tr><td><div style="height: 30px; width: 230px">Cell</div></td></tr>
+    </tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+    <table>
+        <caption style="caption-side: top; height:30px; width: 190px;">Caption</caption>
+        <tbody><tr><td><div style="height: 30px; width: 100px">Cell</div></td></tr>
+    </tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+    <table>
+        <caption style="caption-side: bottom; height:30px; width: 100px;">Caption</caption>
+        <tbody><tr><td><div style="height: 30px; width: 227px">Cell</div></td></tr>
+    </tbody></table>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float:left; clear:left; background:blue; width:150px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:145px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:140px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:135px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:130px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:125px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:120px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:115px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:110px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:105px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:100px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:95px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:90px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:85px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:80px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:75px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:70px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:65px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:60px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:55px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:50px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:45px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:40px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:35px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:30px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:25px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:20px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:15px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:10px; height:1px"></div>
+    <div style="float:left; clear:left; background:blue; width:5px; height:1px"></div>
+    <table>
+        <caption style="caption-side: bottom; height:30px; width: 192px;">Caption</caption>
+        <tbody><tr><td><div style="height: 30px; width: 100px">Cell</div></td></tr>
+    </tbody></table>
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-007-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-007-ref.xht
new file mode 100644
index 0000000..f67bd79
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-007-ref.xht
@@ -0,0 +1,110 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats (reference)</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; vertical-align: top; }
+
+	</style>
+</head>
+<body>
+
+<!-- 6px margin between (from top, from bottom, from both) -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow; margin-top: 1px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow; margin-top: 1px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow; margin-top: 1px;"></div>
+</td></tr></tbody></table>
+
+<!-- 5px margin between (from both) -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<!-- 4px margin between (from both) -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<!-- negative margin between -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="float: left; clear: left; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-007.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-007.xht
new file mode 100644
index 0000000..0d023e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-007.xht
@@ -0,0 +1,114 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>
+	<title>CSS Test: Test for flow around floats</title>
+	<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+	<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+	<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+	<link rel="match" href="floats-wrap-bfc-007-ref.xht"/>
+	<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+	<meta name="flags" content="" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Style-Type" content="text/css" />
+	<style type="text/css">
+
+	table { margin: 0; border-spacing: 0; }
+	td, th { padding: 0; vertical-align: top; }
+
+	</style>
+</head>
+<body>
+
+<!-- 6px margin between (from top, from bottom, from both) -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: 6px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 6px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: 6px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 6px;"></div>
+</td></tr></tbody></table>
+
+<!-- 5px margin between (from both) -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: 5px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 5px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: 10px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: -5px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: -5px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 10px;"></div>
+</td></tr></tbody></table>
+
+<!-- 4px margin between (from both) -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: 4px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 4px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: -1px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 5px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: -1px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 5px;"></div>
+</td></tr></tbody></table>
+
+<!-- negative margin between -->
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: -4px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: 0px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: 0px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: -4px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: -4px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: -1px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: -1px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: -4px;"></div>
+</td></tr></tbody></table>
+
+<table width="300" style="background: aqua"><tbody><tr><td>
+    <div style="float: left; height: 10px; width: 150px; background: blue"></div>
+    <div style="height: 5px; background: purple; margin-bottom: -4px;"></div>
+    <div style="overflow: hidden; width: 200px; height: 5px; background: yellow; margin-top: -4px;"></div>
+</td></tr></tbody></table>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-outside-001-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-outside-001-ref.xht
new file mode 100644
index 0000000..5ea97a40
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-outside-001-ref.xht
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head>
+<title>Testcase, bug 472252</title>
+
+<style type="text/css">
+#wrap {width:600px; border:1px solid;position:relative}
+.a {background:lime; color:#fff; width:80%;}
+.b {position:absolute; right:0; width:18%; background: cyan; color: #000; height:10em;}
+textarea {width: 100%; height:10em;}
+</style>
+
+<title>test</title>
+</head>
+<body>
+<div id="wrap">
+	<div class="b"></div>
+	<div class="a"><textarea></textarea></div>
+</div>
+
+
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-outside-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-outside-001.xht
new file mode 100644
index 0000000..9ae6447f3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-bfc-outside-001.xht
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head>
+    <title>CSS Test: float</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-wrap-bfc-outside-001-ref.xht"/>
+    <meta name="flags" content="" />
+
+<style type="text/css">
+#wrap {width:600px; border:1px solid;}
+.a {background:lime; color:#fff; width:80%;}
+.b {float:right; width:18%; background: cyan; color: #000; height:10em;}
+textarea {width: 100%; height:10em;}
+</style>
+
+</head>
+<body>
+<div id="wrap">
+	<div class="b"></div>
+	<div class="a"><textarea></textarea></div>
+</div>
+
+
+</body></html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001l-notref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001l-notref.xht
new file mode 100644
index 0000000..0953df73d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001l-notref.xht
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; text-align: left; }
+div { float: left; clear: left; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 50px;"></div>
+<div style="width: 50px; height: 100px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001l-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001l-ref.xht
new file mode 100644
index 0000000..85fd23f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001l-ref.xht
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; text-align: left; }
+div { float: left; clear: left; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 50px;"></div>
+<div style="width: 100px; height: 100px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001r-notref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001r-notref.xht
new file mode 100644
index 0000000..e9aa080
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001r-notref.xht
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; text-align: right; }
+div { float: right; clear: right; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 50px;"></div>
+<div style="width: 50px; height: 100px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001r-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001r-ref.xht
new file mode 100644
index 0000000..915e5327
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-001r-ref.xht
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; text-align: right; }
+div { float: right; clear: right; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 50px;"></div>
+<div style="width: 100px; height: 100px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-002l-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-002l-ref.xht
new file mode 100644
index 0000000..1b003f4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-002l-ref.xht
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: left; width: 150px; height: 25px;"></div>
+<span></span>
+<div style="height: 100px"></div>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-002r-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-002r-ref.xht
new file mode 100644
index 0000000..847ff9a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-002r-ref.xht
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: right; width: 150px; height: 25px;"></div>
+<span></span>
+<div style="height: 100px"></div>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-003l-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-003l-ref.xht
new file mode 100644
index 0000000..028a65f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-003l-ref.xht
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 100px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: left; width: 250px; height: 25px;"></div>
+<span></span>
+<span style="margin-top: 25px; margin-right: 250px"></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-003r-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-003r-ref.xht
new file mode 100644
index 0000000..4155c67
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-003r-ref.xht
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 100px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: right; width: 250px; height: 25px;"></div>
+<span></span>
+<span style="margin-top: 25px; margin-left: 250px"></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-001l.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-001l.xht
new file mode 100644
index 0000000..a4441971
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-001l.xht
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-001l-ref.xht"/>
+<link rel="mismatch" href="floats-wrap-top-below-001l-notref.xht"/>
+<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+div { float: left; clear: left; }
+span { display: block; overflow: hidden; width: 200px; height: 50px; background: aqua; margin-right: auto; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 75px;"></div>
+<div style="width: 100px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-001r.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-001r.xht
new file mode 100644
index 0000000..1899045a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-001r.xht
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-001r-ref.xht"/>
+<link rel="mismatch" href="floats-wrap-top-below-001r-notref.xht"/>
+<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+div { float: right; clear: right; }
+span { display: block; overflow: hidden; width: 200px; height: 50px; background: aqua; margin-left: auto; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 75px;"></div>
+<div style="width: 100px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-002l.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-002l.xht
new file mode 100644
index 0000000..f4fc6e1d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-002l.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-002l-ref.xht"/>
+<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: block; overflow: hidden; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: left; width: 150px; height: 75px;"></div>
+<div style="float: right; width: 300px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht
new file mode 100644
index 0000000..a9026323
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-002r-ref.xht"/>
+<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: block; overflow: hidden; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: right; width: 150px; height: 75px;"></div>
+<div style="float: left; width: 300px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-003l.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-003l.xht
new file mode 100644
index 0000000..298ea73
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-003l.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-003l-ref.xht"/>
+<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: block; overflow: hidden; width: 100px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: left; width: 250px; height: 75px;"></div>
+<div style="float: right; width: 250px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-003r.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-003r.xht
new file mode 100644
index 0000000..46f4fceb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-bfc-003r.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-003r-ref.xht"/>
+<meta name="assert" content="The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: block; overflow: hidden; width: 100px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: right; width: 250px; height: 75px;"></div>
+<div style="float: left; width: 250px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-001l.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-001l.xht
new file mode 100644
index 0000000..42154af9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-001l.xht
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-001l-ref.xht"/>
+<link rel="mismatch" href="floats-wrap-top-below-001l-notref.xht"/>
+<meta name="assert" content="However, line boxes created next to the float are shortened to make room for the margin box of the float." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; text-align: left; }
+div { float: left; clear: left; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 75px;"></div>
+<div style="width: 100px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-001r.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-001r.xht
new file mode 100644
index 0000000..74b2445
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-001r.xht
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-001r-ref.xht"/>
+<link rel="mismatch" href="floats-wrap-top-below-001r-notref.xht"/>
+<meta name="assert" content="However, line boxes created next to the float are shortened to make room for the margin box of the float." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; text-align: right; }
+div { float: right; clear: right; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="width: 50px; height: 75px;"></div>
+<div style="width: 100px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-002l.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-002l.xht
new file mode 100644
index 0000000..7a1ca55
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-002l.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-002l-ref.xht"/>
+<meta name="assert" content="However, line boxes created next to the float are shortened to make room for the margin box of the float." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: left; width: 150px; height: 75px;"></div>
+<div style="float: right; width: 300px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-002r.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-002r.xht
new file mode 100644
index 0000000..596c51c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-002r.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-002r-ref.xht"/>
+<meta name="assert" content="However, line boxes created next to the float are shortened to make room for the margin box of the float." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 200px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: right; width: 150px; height: 75px;"></div>
+<div style="float: left; width: 300px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-003l.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-003l.xht
new file mode 100644
index 0000000..685cf9d35
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-003l.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-003l-ref.xht"/>
+<meta name="assert" content="However, line boxes created next to the float are shortened to make room for the margin box of the float." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 100px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: left; width: 250px; height: 75px;"></div>
+<div style="float: right; width: 250px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-003r.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-003r.xht
new file mode 100644
index 0000000..317e8dd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-wrap-top-below-inline-003r.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS Test: Test for wrapping around floats whose top is below the top of what must wrap around them</title>
+<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+<link rel="match" href="floats-wrap-top-below-003r-ref.xht"/>
+<meta name="assert" content="However, line boxes created next to the float are shortened to make room for the margin box of the float." />
+<meta name="flags" content="" />
+<style type="text/css">
+
+body { width: 400px; border: medium solid; }
+span { display: inline-block; vertical-align: top; width: 100px; height: 50px; background: aqua; }
+
+</style>
+</head>
+<body>
+
+<div style="float: right; width: 250px; height: 75px;"></div>
+<div style="float: left; width: 250px; height: 75px;"></div>
+<span></span>
+<span></span>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-001-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-001-ref.xht
new file mode 100644
index 0000000..68139cd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-001-ref.xht
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Test for wrapping around zero-height floats</title>
+
+</head><body><div style="width: 500px; height: 500px; float: left; font-size: 12px;">
+
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: blue; margin-left: 10px;"></span>
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: purple; margin-left: 100px;"></span>
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: fuchsia"></span>
+
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-001.xht
new file mode 100644
index 0000000..b2821267
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-001.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: wrapping around zero-height floats</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-zero-height-wrap-001-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="wrapping around zero-height floats" />
+
+</head><body><div style="width: 500px; height: 500px; float: left; font-size: 12px;">
+
+  <div style="float: left; width: 10px; height: 30px"></div>
+  <div style="float: left; clear: left; width: 100px; height: 1px"></div>
+
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: blue;"></span>
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: purple;"></span>
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: fuchsia"></span>
+
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-002.xht
new file mode 100644
index 0000000..679f5b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats/floats-zero-height-wrap-002.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CSS Test: wrapping around zero-height floats</title>
+    <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
+    <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+    <link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#floats" />
+    <link rel="match" href="floats-zero-height-wrap-001-ref.xht"/>
+    <meta name="flags" content="" />
+    <meta name="assert" content="wrapping around zero-height floats" />
+
+</head><body><div style="width: 500px; height: 500px; float: left; font-size: 12px;">
+
+  <div style="float: left; width: 10px; height: 30px"></div>
+  <div style="float: left; clear: left; width: 100px; height: 0"></div>
+
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: blue;"></span>
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: purple;"></span>
+  <span style="display:inline-block; vertical-align: bottom; height: 20px; width: 300px; background: fuchsia"></span>
+
+</div>
+</body></html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/imagecapture/MediaStreamTrack-applyConstraints.html b/third_party/WebKit/LayoutTests/fast/imagecapture/MediaStreamTrack-applyConstraints.html
index 5164d490..af1e92b 100644
--- a/third_party/WebKit/LayoutTests/fast/imagecapture/MediaStreamTrack-applyConstraints.html
+++ b/third_party/WebKit/LayoutTests/fast/imagecapture/MediaStreamTrack-applyConstraints.html
@@ -26,6 +26,26 @@
   return videoTrack.applyConstraints();
 }, 'MediaStreamTrack.applyConstraints()');
 
+// This test verifies that applyConstraints() rejects the returned Promise if
+// passed a non-supported image-capture constraint (https://crbug.com/711694).
+promise_test(function(t) {
+  var canvas = document.getElementById('canvas');
+  var context = canvas.getContext("2d");
+  context.fillStyle = "red";
+  context.fillRect(0, 0, 10, 10);
+
+  var stream = canvas.captureStream();
+  var videoTrack = stream.getVideoTracks()[0];
+
+  var expectedException =
+      new DOMException('Unsupported constraint(s)', 'NotSupportedError');
+
+  // Use e.g. |torch| as an example of unsupported constraint.
+  assert_false("torch" in videoTrack.getCapabilities());
+  return promise_rejects(
+      t, expectedException,
+      videoTrack.applyConstraints({advanced : [ {torch : true} ]}));
+}, 'MediaStreamTrack.applyConstraints() with unsupported constraint');
 
 // This test verifies that applyConstraints() rejects the returned Promise if
 // passed a non-supported constraint.
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/imagecapture/MediaStreamTrack-applyConstraints-getSettings.html b/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-applyConstraints-getSettings.html
index cfbb985..e2daf387 100644
--- a/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-applyConstraints-getSettings.html
+++ b/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-applyConstraints-getSettings.html
@@ -52,6 +52,14 @@
       var stream = canvas.captureStream();
       videoTrack = stream.getVideoTracks()[0];
 
+      // |videoTrack|'s capabilities gathering, just like the actual capture, is
+      // a process kicked off right after creation, we introduce a small delay
+      // to allow for those to be collected, since they are needed to understand
+      // which constraints are supported in applyConstraints().
+      // TODO(mcasas): this shouldn't be needed, https://crbug.com/711524.
+      return new Promise(resolve => setTimeout(resolve, 100));
+    })
+    .then(function() {
       return videoTrack.applyConstraints(constraints);
     })
     .then(function() {
diff --git a/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-applyConstraints.html b/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-applyConstraints.html
index 9db07b1..dc9da9b1 100644
--- a/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-applyConstraints.html
+++ b/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-applyConstraints.html
@@ -41,18 +41,27 @@
                                     }]};
 
   var theMock = null;
+  var videoTrack = null;
   mockImageCaptureReady
     .then(mock => {
       theMock = mock;
       var stream = canvas.captureStream();
-      var videoTrack = stream.getVideoTracks()[0];
+      videoTrack = stream.getVideoTracks()[0];
 
-      return videoTrack.applyConstraints(constraints);
+      // |videoTrack|'s capabilities gathering, just like the actual capture, is
+      // a process kicked off right after creation, we introduce a small delay
+      // to allow for those to be collected, since they are needed to understand
+      // which constraints are supported in applyConstraints().
+      // TODO(mcasas): this shouldn't be needed, https://crbug.com/711524.
+      return new Promise(resolve => setTimeout(resolve, 100));
     },
     error => {
       assert_unreached("Error creating MockImageCapture: " + error);
     })
     .then(function() {
+      return videoTrack.applyConstraints(constraints);
+    })
+    .then(function() {
       assert_equals(constraints.advanced[0].whiteBalanceMode,
                     meteringModeNames[theMock.options().white_balance_mode],
                     'whiteBalanceMode');
diff --git a/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-getCapabilities.html b/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-getCapabilities.html
index 490d3550..ec9347bf 100644
--- a/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-getCapabilities.html
+++ b/third_party/WebKit/LayoutTests/imagecapture/MediaStreamTrack-getCapabilities.html
@@ -33,9 +33,10 @@
       var videoTrack = stream.getVideoTracks()[0];
       assert_equals(typeof videoTrack.getCapabilities, 'function');
 
-      // |videoTrack|s capabilities, just like the actual capture, is a process
-      // kicked right after creation, we introduce a small delay to allow for
-      // those to be collected.
+      // |videoTrack|'s capabilities gathering, just like the actual capture, is
+      // a process kicked off right after creation, we introduce a small delay
+      // to allow for those to be collected.
+      // TODO(mcasas): this shouldn't be needed, https://crbug.com/711524.
       setTimeout(() => {
         capabilities = videoTrack.getCapabilities();
         assert_equals(typeof capabilities, 'object');
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/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/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/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
index ab426ac..31dd704 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
index 7e1243a1..98ce8c5 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index 8938c8b..556507c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
index 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/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/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/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/Source/bindings/core/v8/SerializedScriptValue.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
index 8efc23cd..4e43b3d 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
@@ -35,6 +35,7 @@
 #include "bindings/core/v8/DOMWrapperWorld.h"
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/SerializationTag.h"
 #include "bindings/core/v8/SerializedScriptValueFactory.h"
 #include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/V8ArrayBuffer.h"
@@ -54,6 +55,7 @@
 #include "platform/wtf/ByteOrder.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/Vector.h"
+#include "platform/wtf/dtoa/utils.h"
 #include "platform/wtf/text/StringBuffer.h"
 #include "platform/wtf/text/StringHash.h"
 
@@ -89,22 +91,124 @@
   return AdoptRef(new SerializedScriptValue(data));
 }
 
+// Versions 16 and below (prior to April 2017) used ntohs() to byte-swap SSV
+// data when converting it to the wire format. This was a historical accient.
+//
+// As IndexedDB stores SSVs to disk indefinitely, we still need to keep around
+// the code needed to deserialize the old format.
+inline static bool IsByteSwappedWiredData(const char* data, size_t length) {
+  // TODO(pwnall): Return false early if we're on big-endian hardware. Chromium
+  // doesn't currently support big-endian hardware, and there's no header
+  // exposing endianness to Blink yet. ARCH_CPU_LITTLE_ENDIAN seems promising,
+  // but Blink is not currently allowed to include files from build/.
+
+  // The first SSV version without byte-swapping has two envelopes (Blink, V8),
+  // each of which is at least 2 bytes long.
+  if (length < 4)
+    return true;
+
+  // This code handles the following cases:
+  //
+  // v0 (byte-swapped)    - [d,    t,    ...], t = tag byte, d = first data byte
+  // v1-16 (byte-swapped) - [v,    0xFF, ...], v = version (1 <= v <= 16)
+  // v17+                 - [0xFF, v,    ...], v = first byte of version varint
+
+  if (static_cast<uint8_t>(data[0]) == kVersionTag) {
+    // The only case where byte-swapped data can have 0xFF in byte zero is
+    // version 0. This can only happen if byte one is a tag (supported in
+    // version 0) that takes in extra data, and the first byte of extra data is
+    // 0xFF. There are 13 such tags, listed below. These tags cannot be used as
+    // version numbers in the Blink-side SSV envelope.
+    //
+    //  35 - 0x23 - # - ImageDataTag
+    //  64 - 0x40 - @ - SparseArrayTag
+    //  68 - 0x44 - D - DateTag
+    //  73 - 0x49 - I - Int32Tag
+    //  78 - 0x4E - N - NumberTag
+    //  82 - 0x52 - R - RegExpTag
+    //  83 - 0x53 - S - StringTag
+    //  85 - 0x55 - U - Uint32Tag
+    //  91 - 0x5B - [ - ArrayTag
+    //  98 - 0x62 - b - BlobTag
+    // 102 - 0x66 - f - FileTag
+    // 108 - 0x6C - l - FileListTag
+    // 123 - 0x7B - { - ObjectTag
+    //
+    // Why we care about version 0:
+    //
+    // IndexedDB stores values using the SSV format. Currently, IndexedDB does
+    // not do any sort of migration, so a value written with a SSV version will
+    // be stored with that version until it is removed via an update or delete.
+    //
+    // IndexedDB was shipped in Chrome 11, which was released on April 27, 2011.
+    // SSV version 1 was added in WebKit r91698, which was shipped in Chrome 14,
+    // which was released on September 16, 2011.
+    static_assert(
+        SerializedScriptValue::kWireFormatVersion != 35 &&
+            SerializedScriptValue::kWireFormatVersion != 64 &&
+            SerializedScriptValue::kWireFormatVersion != 68 &&
+            SerializedScriptValue::kWireFormatVersion != 73 &&
+            SerializedScriptValue::kWireFormatVersion != 78 &&
+            SerializedScriptValue::kWireFormatVersion != 82 &&
+            SerializedScriptValue::kWireFormatVersion != 83 &&
+            SerializedScriptValue::kWireFormatVersion != 85 &&
+            SerializedScriptValue::kWireFormatVersion != 91 &&
+            SerializedScriptValue::kWireFormatVersion != 98 &&
+            SerializedScriptValue::kWireFormatVersion != 102 &&
+            SerializedScriptValue::kWireFormatVersion != 108 &&
+            SerializedScriptValue::kWireFormatVersion != 123,
+        "Using a burned version will prevent us from reading SSV version 0");
+
+    // Fast path until the Blink-side SSV envelope reaches version 35.
+    if (SerializedScriptValue::kWireFormatVersion < 35) {
+      if (static_cast<uint8_t>(data[1]) < 35)
+        return false;
+
+      // TODO(pwnall): Add UMA metric here.
+      return true;
+    }
+
+    // Slower path that would kick in after version 35, assuming we don't remove
+    // support for SSV version 0 by then.
+    static constexpr uint8_t version0Tags[] = {35, 64, 68, 73,  78,  82, 83,
+                                               85, 91, 98, 102, 108, 123};
+    return std::find(std::begin(version0Tags), std::end(version0Tags),
+                     data[1]) != std::end(version0Tags);
+  }
+
+  if (static_cast<uint8_t>(data[1]) == kVersionTag) {
+    // The last SSV format that used byte-swapping was version 16. The version
+    // number is stored (before byte-swapping) after a serialization tag, which
+    // is 0xFF.
+    return static_cast<uint8_t>(data[0]) != kVersionTag;
+  }
+
+  // If kVersionTag isn't in any of the first two bytes, this is SSV version 0,
+  // which was byte-swapped.
+  return true;
+}
+
 PassRefPtr<SerializedScriptValue> SerializedScriptValue::Create(
     const char* data,
     size_t length) {
   if (!data)
     return Create();
 
-  // Decode wire data from big endian to host byte order.
   DCHECK(!(length % sizeof(UChar)));
-  size_t string_length = length / sizeof(UChar);
-  StringBuffer<UChar> buffer(string_length);
   const UChar* src = reinterpret_cast<const UChar*>(data);
-  UChar* dst = buffer.Characters();
-  for (size_t i = 0; i < string_length; i++)
-    dst[i] = ntohs(src[i]);
+  size_t string_length = length / sizeof(UChar);
 
-  return AdoptRef(new SerializedScriptValue(String::Adopt(buffer)));
+  if (IsByteSwappedWiredData(data, length)) {
+    // Decode wire data from big endian to host byte order.
+    StringBuffer<UChar> buffer(string_length);
+    UChar* dst = buffer.Characters();
+    for (size_t i = 0; i < string_length; ++i)
+      dst[i] = ntohs(src[i]);
+
+    return AdoptRef(new SerializedScriptValue(String::Adopt(buffer)));
+  }
+
+  return AdoptRef(new SerializedScriptValue(String(src, string_length)));
 }
 
 SerializedScriptValue::SerializedScriptValue()
@@ -134,8 +238,9 @@
 }
 
 PassRefPtr<SerializedScriptValue> SerializedScriptValue::NullValue() {
-  // UChar rather than uint8_t here to get host endian behavior.
-  static const UChar kNullData[] = {0xff09, 0x3000};
+  // The format here may fall a bit out of date, because we support
+  // deserializing SSVs written by old browser versions.
+  static const uint8_t kNullData[] = {0xFF, 17, 0xFF, 13, '0', 0x00};
   return Create(reinterpret_cast<const char*>(kNullData), sizeof(kNullData));
 }
 
@@ -152,22 +257,17 @@
   return wire_string;
 }
 
-// Convert serialized string to big endian wire data.
 void SerializedScriptValue::ToWireBytes(Vector<char>& result) const {
   DCHECK(result.IsEmpty());
 
-  size_t wire_size_bytes = (data_buffer_size_ + 1) & ~1;
-  result.Resize(wire_size_bytes);
+  size_t result_size = (data_buffer_size_ + 1) & ~1;
+  result.Resize(result_size);
+  memcpy(result.Data(), data_buffer_.get(), data_buffer_size_);
 
-  const UChar* src = reinterpret_cast<UChar*>(data_buffer_.get());
-  UChar* dst = reinterpret_cast<UChar*>(result.Data());
-  for (size_t i = 0; i < data_buffer_size_ / 2; i++)
-    dst[i] = htons(src[i]);
-
-  // This is equivalent to swapping the byte order of the two bytes (x, 0),
-  // depending on endianness.
-  if (data_buffer_size_ % 2)
-    dst[wire_size_bytes / 2 - 1] = data_buffer_[data_buffer_size_ - 1] << 8;
+  if (result_size > data_buffer_size_) {
+    DCHECK_EQ(result_size, data_buffer_size_ + 1);
+    result[data_buffer_size_] = 0;
+  }
 }
 
 static void AccumulateArrayBuffersForAllWorlds(
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
index 5e9912170..15d211c9 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
@@ -75,7 +75,12 @@
   // Version 9: Added Map and Set support.
   // [versions skipped]
   // Version 16: Separate versioning between V8 and Blink.
-  static const uint32_t kWireFormatVersion = 16;
+  // Version 17: Remove unnecessary byte swapping.
+  //
+  // The following versions cannot be used, in order to be able to
+  // deserialize version 0 SSVs. The class implementation has details.
+  // DO NOT USE: 35, 64, 68, 73, 78, 82, 83, 85, 91, 98, 102, 108, 123.
+  static constexpr uint32_t kWireFormatVersion = 17;
 
   struct SerializeOptions {
     STACK_ALLOCATED();
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueTest.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueTest.cpp
index 0af3d11..2c606ad 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueTest.cpp
@@ -9,12 +9,115 @@
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8BindingForTesting.h"
 #include "bindings/core/v8/V8File.h"
+#include "bindings/core/v8/V8ImageData.h"
 #include "core/fileapi/File.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
 
+TEST(SerializedScriptValueTest, WireFormatRoundTrip) {
+  V8TestingScope scope;
+
+  v8::Local<v8::Value> v8OriginalTrue = v8::True(scope.GetIsolate());
+  RefPtr<SerializedScriptValue> sourceSerializedScriptValue =
+      SerializedScriptValue::Serialize(
+          scope.GetIsolate(), v8OriginalTrue,
+          SerializedScriptValue::SerializeOptions(), ASSERT_NO_EXCEPTION);
+
+  Vector<char> wireData;
+  sourceSerializedScriptValue->ToWireBytes(wireData);
+
+  RefPtr<SerializedScriptValue> serializedScriptValue =
+      SerializedScriptValue::Create(wireData.Data(), wireData.size());
+  v8::Local<v8::Value> deserialized =
+      serializedScriptValue->Deserialize(scope.GetIsolate());
+  EXPECT_TRUE(deserialized->IsTrue());
+}
+
+TEST(SerializedScriptValueTest, WireFormatVersion17NoByteSwapping) {
+  V8TestingScope scope;
+
+  const uint8_t data[] = {0xFF, 0x11, 0xFF, 0x0D, 0x54, 0x00};
+  RefPtr<SerializedScriptValue> serializedScriptValue =
+      SerializedScriptValue::Create(reinterpret_cast<const char*>(data),
+                                    sizeof(data));
+  v8::Local<v8::Value> deserialized =
+      serializedScriptValue->Deserialize(scope.GetIsolate());
+  EXPECT_TRUE(deserialized->IsTrue());
+}
+
+TEST(SerializedScriptValueTest, WireFormatVersion16ByteSwapping) {
+  V8TestingScope scope;
+
+  // Using UChar instead of uint8_t to get ntohs() byte swapping.
+  const UChar data[] = {0xFF10, 0xFF0D, 0x5400};
+  RefPtr<SerializedScriptValue> serializedScriptValue =
+      SerializedScriptValue::Create(reinterpret_cast<const char*>(data),
+                                    sizeof(data));
+  v8::Local<v8::Value> deserialized =
+      serializedScriptValue->Deserialize(scope.GetIsolate());
+  EXPECT_TRUE(deserialized->IsTrue());
+}
+
+TEST(SerializedScriptValueTest, WireFormatVersion13ByteSwapping) {
+  V8TestingScope scope;
+
+  // Using UChar instead of uint8_t to get ntohs() byte swapping.
+  const UChar data[] = {0xFF0D, 0x5400};
+  RefPtr<SerializedScriptValue> serializedScriptValue =
+      SerializedScriptValue::Create(reinterpret_cast<const char*>(data),
+                                    sizeof(data));
+  v8::Local<v8::Value> deserialized =
+      serializedScriptValue->Deserialize(scope.GetIsolate());
+  EXPECT_TRUE(deserialized->IsTrue());
+}
+
+TEST(SerializedScriptValueTest, WireFormatVersion0ByteSwapping) {
+  V8TestingScope scope;
+
+  // Using UChar instead of uint8_t to get ntohs() byte swapping.
+  const UChar data[] = {0x5400};
+  RefPtr<SerializedScriptValue> serializedScriptValue =
+      SerializedScriptValue::Create(reinterpret_cast<const char*>(data),
+                                    sizeof(data));
+  v8::Local<v8::Value> deserialized =
+      serializedScriptValue->Deserialize(scope.GetIsolate());
+  EXPECT_TRUE(deserialized->IsTrue());
+}
+
+TEST(SerializedScriptValueTest, WireFormatVersion0ImageData) {
+  V8TestingScope scope;
+  v8::Isolate* isolate = scope.GetIsolate();
+
+  // Using UChar instead of uint8_t to get ntohs() byte swapping.
+  //
+  // This builds the smallest possible ImageData whose first data byte is 0xFF,
+  // as follows.
+  //
+  // width = 127, encoded as 0xFF 0x00 (degenerate varint)
+  // height = 1, encoded as 0x01 (varint)
+  // pixelLength = 508 (127 * 1 * 4), encoded as 0xFC 0x03 (varint)
+  // pixel data = 508 bytes, all zero
+  Vector<UChar> data;
+  data.push_back(0x23FF);
+  data.push_back(0x001);
+  data.push_back(0xFC03);
+  data.Resize(257);  // (508 pixel data + 6 header bytes) / 2
+
+  RefPtr<SerializedScriptValue> serializedScriptValue =
+      SerializedScriptValue::Create(reinterpret_cast<const char*>(data.Data()),
+                                    data.size() * sizeof(UChar));
+  v8::Local<v8::Value> deserialized =
+      serializedScriptValue->Deserialize(isolate);
+  ASSERT_TRUE(deserialized->IsObject());
+  v8::Local<v8::Object> deserializedObject = deserialized.As<v8::Object>();
+  ASSERT_TRUE(V8ImageData::hasInstance(deserializedObject, isolate));
+  ImageData* imageData = V8ImageData::toImpl(deserializedObject);
+  EXPECT_EQ(imageData->width(), 127);
+  EXPECT_EQ(imageData->height(), 1);
+}
+
 TEST(SerializedScriptValueTest, UserSelectedFile) {
   V8TestingScope scope;
   String file_path = testing::BlinkRootDir();
diff --git a/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp b/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp
index 88f104b7..cba0e74 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/V8BindingForModulesTest.cpp
@@ -132,15 +132,10 @@
 
 // SerializedScriptValue header format offsets are inferred from the Blink and
 // V8 serialization code. The code below DCHECKs that
-constexpr static size_t kSSVHeaderBlinkVersionOffset = 0;
-constexpr static size_t kSSVHeaderBlinkVersionTagOffset = 1;
-constexpr static size_t kSSVHeaderV8VersionOffset = 2;
-constexpr static size_t kSSVHeaderV8VersionTagOffset = 3;
-
-// 13 is v8::internal::kLatestVersion in v8/src/value-serializer.cc at the
-// time when this test was written. Unlike Blink, V8 does not currently export
-// its serialization version, so this number might get stale.
-constexpr static unsigned char kV8LatestKnownVersion = 13;
+constexpr static size_t kSSVHeaderBlinkVersionTagOffset = 0;
+constexpr static size_t kSSVHeaderBlinkVersionOffset = 1;
+constexpr static size_t kSSVHeaderV8VersionTagOffset = 2;
+constexpr static size_t kSSVHeaderV8VersionOffset = 3;
 
 // Follows the same steps as the IndexedDB value serialization code.
 void SerializeV8Value(v8::Local<v8::Value> value,
@@ -162,16 +157,16 @@
   // 0xFF.
   const unsigned char* wire_data =
       reinterpret_cast<unsigned char*>(wire_bytes->Data());
+  ASSERT_EQ(static_cast<unsigned char>(kVersionTag),
+            wire_data[kSSVHeaderBlinkVersionTagOffset]);
   ASSERT_EQ(
       static_cast<unsigned char>(SerializedScriptValue::kWireFormatVersion),
       wire_data[kSSVHeaderBlinkVersionOffset]);
-  ASSERT_EQ(static_cast<unsigned char>(kVersionTag),
-            wire_data[kSSVHeaderBlinkVersionTagOffset]);
 
-  ASSERT_GE(static_cast<unsigned char>(kV8LatestKnownVersion),
-            wire_data[kSSVHeaderV8VersionOffset]);
   ASSERT_EQ(static_cast<unsigned char>(kVersionTag),
             wire_data[kSSVHeaderV8VersionTagOffset]);
+  ASSERT_EQ(v8::ValueSerializer::GetCurrentDataFormatVersion(),
+            wire_data[kSSVHeaderV8VersionOffset]);
 }
 
 PassRefPtr<IDBValue> CreateIDBValue(v8::Isolate* isolate,
diff --git a/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
index d18332e0..87adbf2 100644
--- a/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
@@ -132,8 +132,8 @@
 void ModuleMapTestModulator::ResolveFetches() {
   for (const auto& test_request : test_requests_) {
     ModuleScript* module_script = ModuleScript::Create(
-        ScriptModule(), test_request->url, test_request->nonce, kParserInserted,
-        WebURLRequest::kFetchCredentialsModeOmit);
+        this, ScriptModule(), test_request->url, test_request->nonce,
+        kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
     TaskRunner()->PostTask(
         BLINK_FROM_HERE,
         WTF::Bind(&ModuleScriptLoaderClient::NotifyNewSingleModuleFinished,
diff --git a/third_party/WebKit/Source/core/dom/ModuleScript.cpp b/third_party/WebKit/Source/core/dom/ModuleScript.cpp
index 28fa847d..f175cd9 100644
--- a/third_party/WebKit/Source/core/dom/ModuleScript.cpp
+++ b/third_party/WebKit/Source/core/dom/ModuleScript.cpp
@@ -21,6 +21,7 @@
 }
 
 DEFINE_TRACE(ModuleScript) {
+  visitor->Trace(settings_object_);
   Script::Trace(visitor);
 }
 DEFINE_TRACE_WRAPPERS(ModuleScript) {
diff --git a/third_party/WebKit/Source/core/dom/ModuleScript.h b/third_party/WebKit/Source/core/dom/ModuleScript.h
index dbe6db9..17cec9d 100644
--- a/third_party/WebKit/Source/core/dom/ModuleScript.h
+++ b/third_party/WebKit/Source/core/dom/ModuleScript.h
@@ -10,6 +10,7 @@
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/TraceWrapperV8Reference.h"
 #include "core/CoreExport.h"
+#include "core/dom/Modulator.h"
 #include "core/dom/Script.h"
 #include "platform/heap/Handle.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
@@ -30,13 +31,14 @@
 class CORE_EXPORT ModuleScript final : public Script, public TraceWrapperBase {
  public:
   static ModuleScript* Create(
+      Modulator* settings_object,
       ScriptModule record,
       const KURL& base_url,
       const String& nonce,
       ParserDisposition parser_state,
       WebURLRequest::FetchCredentialsMode credentials_mode) {
-    return new ModuleScript(record, base_url, nonce, parser_state,
-                            credentials_mode);
+    return new ModuleScript(settings_object, record, base_url, nonce,
+                            parser_state, credentials_mode);
   }
   ~ModuleScript() override = default;
 
@@ -61,12 +63,14 @@
   DECLARE_TRACE_WRAPPERS();
 
  private:
-  ModuleScript(ScriptModule record,
+  ModuleScript(Modulator* settings_object,
+               ScriptModule record,
                const KURL& base_url,
                const String& nonce,
                ParserDisposition parser_state,
                WebURLRequest::FetchCredentialsMode credentials_mode)
-      : record_(record),
+      : settings_object_(settings_object),
+        record_(record),
         base_url_(base_url),
         instantiation_error_(this),
         nonce_(nonce),
@@ -80,10 +84,8 @@
   void RunScript(LocalFrame*, const SecurityOrigin*) const override;
   String InlineSourceTextForCSP() const override;
 
-  // Note: A "module script"'s "setttings object" is ommitted, as we currently
-  // always have access to the corresponding Modulator when operating on a
-  // ModuleScript instance.
   // https://html.spec.whatwg.org/multipage/webappapis.html#settings-object
+  Member<Modulator> settings_object_;
 
   // https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-module-record
   ScriptModule record_;
diff --git a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp
index a04d97f..6921f7f7 100644
--- a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp
@@ -55,26 +55,28 @@
   return module_script_.Get();
 }
 
-ModuleScript* CreateReferrerModuleScript(V8TestingScope& scope) {
+ModuleScript* CreateReferrerModuleScript(Modulator* modulator,
+                                         V8TestingScope& scope) {
   ScriptModule referrer_record = ScriptModule::Compile(
       scope.GetIsolate(), "import './target.js'; export const a = 42;",
       "referrer.js", kSharableCrossOrigin);
   KURL referrer_url(kParsedURLString, "https://example.com/referrer.js");
-  ModuleScript* referrer_module_script =
-      ModuleScript::Create(referrer_record, referrer_url, "", kParserInserted,
-                           WebURLRequest::kFetchCredentialsModeOmit);
+  ModuleScript* referrer_module_script = ModuleScript::Create(
+      modulator, referrer_record, referrer_url, "", kParserInserted,
+      WebURLRequest::kFetchCredentialsModeOmit);
   // TODO(kouhei): moduleScript->setInstantiateSuccess(); once
   // https://codereview.chromium.org/2782403002/ landed.
   return referrer_module_script;
 }
 
-ModuleScript* CreateTargetModuleScript(V8TestingScope& scope) {
+ModuleScript* CreateTargetModuleScript(Modulator* modulator,
+                                       V8TestingScope& scope) {
   ScriptModule record =
       ScriptModule::Compile(scope.GetIsolate(), "export const pi = 3.14;",
                             "target.js", kSharableCrossOrigin);
   KURL url(kParsedURLString, "https://example.com/target.js");
   ModuleScript* module_script =
-      ModuleScript::Create(record, url, "", kParserInserted,
+      ModuleScript::Create(modulator, record, url, "", kParserInserted,
                            WebURLRequest::kFetchCredentialsModeOmit);
   // TODO(kouhei): moduleScript->setInstantiateSuccess(); once
   // https://codereview.chromium.org/2782403002/ landed.
@@ -107,10 +109,12 @@
       ScriptModuleResolverImpl::Create(Modulator());
   V8TestingScope scope;
 
-  ModuleScript* referrer_module_script = CreateReferrerModuleScript(scope);
+  ModuleScript* referrer_module_script =
+      CreateReferrerModuleScript(modulator_, scope);
   resolver->RegisterModuleScript(referrer_module_script);
 
-  ModuleScript* target_module_script = CreateTargetModuleScript(scope);
+  ModuleScript* target_module_script =
+      CreateTargetModuleScript(modulator_, scope);
   Modulator()->SetModuleScript(target_module_script);
 
   ScriptModule resolved =
@@ -128,10 +132,12 @@
       ScriptModuleResolverImpl::Create(Modulator());
   V8TestingScope scope;
 
-  ModuleScript* referrer_module_script = CreateReferrerModuleScript(scope);
+  ModuleScript* referrer_module_script =
+      CreateReferrerModuleScript(modulator_, scope);
   resolver->RegisterModuleScript(referrer_module_script);
 
-  ModuleScript* target_module_script = CreateTargetModuleScript(scope);
+  ModuleScript* target_module_script =
+      CreateTargetModuleScript(modulator_, scope);
   Modulator()->SetModuleScript(target_module_script);
 
   ScriptModule resolved = resolver->Resolve(
@@ -147,10 +153,12 @@
       ScriptModuleResolverImpl::Create(Modulator());
   V8TestingScope scope;
 
-  ModuleScript* referrer_module_script = CreateReferrerModuleScript(scope);
+  ModuleScript* referrer_module_script =
+      CreateReferrerModuleScript(modulator_, scope);
   resolver->RegisterModuleScript(referrer_module_script);
 
-  ModuleScript* target_module_script = CreateTargetModuleScript(scope);
+  ModuleScript* target_module_script =
+      CreateTargetModuleScript(modulator_, scope);
   // Set Modulator::getFetchedModuleScript to return nullptr, which represents
   // that the target module failed to load.
   Modulator()->SetModuleScript(nullptr);
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
index 9c58e59..97e66fc 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
@@ -244,7 +244,7 @@
   // Step 10. Set script's parser state to the parser state.
   // Step 11. Set script's credentials mode to the credentials mode provided.
   // Step 12. Return script.
-  return ModuleScript::Create(result, url, nonce, parser_state,
+  return ModuleScript::Create(modulator, result, url, nonce, parser_state,
                               credentials_mode);
 }
 
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index 445cfe074..39564a8 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/imagecapture/ImageCapture.cpp b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
index 3473914..ca93ddc 100644
--- a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
+++ b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
@@ -261,6 +261,26 @@
   // TODO(mcasas): add support more than one single advanced constraint.
   const auto constraints = constraints_vector[0];
 
+  if ((constraints.hasWhiteBalanceMode() &&
+       !capabilities_.hasWhiteBalanceMode()) ||
+      (constraints.hasExposureMode() && !capabilities_.hasExposureMode()) ||
+      (constraints.hasFocusMode() && !capabilities_.hasFocusMode()) ||
+      (constraints.hasExposureCompensation() &&
+       !capabilities_.hasExposureCompensation()) ||
+      (constraints.hasColorTemperature() &&
+       !capabilities_.hasColorTemperature()) ||
+      (constraints.hasIso() && !capabilities_.hasIso()) ||
+      (constraints.hasBrightness() && !capabilities_.hasBrightness()) ||
+      (constraints.hasContrast() && !capabilities_.hasContrast()) ||
+      (constraints.hasSaturation() && !capabilities_.hasSaturation()) ||
+      (constraints.hasSharpness() && !capabilities_.hasSharpness()) ||
+      (constraints.hasZoom() && !capabilities_.hasZoom()) ||
+      (constraints.hasTorch() && !capabilities_.hasTorch())) {
+    resolver->Reject(
+        DOMException::Create(kNotSupportedError, "Unsupported constraint(s)"));
+    return;
+  }
+
   auto settings = media::mojom::blink::PhotoSettings::New();
 
   // TODO(mcasas): support other Mode types beyond simple string i.e. the
diff --git a/third_party/WebKit/Source/modules/webusb/USB.cpp b/third_party/WebKit/Source/modules/webusb/USB.cpp
index 236a627..cbe3e04 100644
--- a/third_party/WebKit/Source/modules/webusb/USB.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USB.cpp
@@ -26,7 +26,7 @@
 namespace blink {
 namespace {
 
-const char kNoServiceError[] = "USB service unavailable.";
+const char kNoDeviceSelected[] = "No device selected.";
 
 usb::DeviceFilterPtr ConvertDeviceFilter(const USBDeviceFilter& filter) {
   auto mojo_filter = usb::DeviceFilter::New();
@@ -172,16 +172,11 @@
   chooser_service_requests_.erase(request_entry);
 
   EnsureDeviceManagerConnection();
-  if (!device_manager_) {
-    resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
-    return;
-  }
 
-  if (device_info) {
+  if (device_manager_ && device_info) {
     resolver->Resolve(GetOrCreateDevice(std::move(device_info)));
   } else {
-    resolver->Reject(
-        DOMException::Create(kNotFoundError, "No device selected."));
+    resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected));
   }
 }
 
@@ -208,14 +203,14 @@
   device_manager_.reset();
   client_binding_.Close();
   for (ScriptPromiseResolver* resolver : device_manager_requests_)
-    resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+    resolver->Resolve(HeapVector<Member<USBDevice>>(0));
   device_manager_requests_.Clear();
 }
 
 void USB::OnChooserServiceConnectionError() {
   chooser_service_.reset();
   for (ScriptPromiseResolver* resolver : chooser_service_requests_)
-    resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+    resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected));
   chooser_service_requests_.Clear();
 }
 
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..3952c87 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 474a7d12..4fe7853 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 2a17f3d..7c14717 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 e26681df..d3b7553 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) {
@@ -535,7 +537,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();
@@ -554,8 +556,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(
@@ -593,7 +595,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 f4e0aae..5a09e2d8 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/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/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
index 86df73e..13580bb 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
@@ -412,6 +412,7 @@
                 'rebaseline-cl',
                 '--verbose',
                 '--no-trigger-jobs',
+                '--fill-missing',
             ] + tests_to_rebaseline)
         return tests_results
 
diff --git a/third_party/WebKit/public/web/WebSerializedScriptValueVersion.h b/third_party/WebKit/public/web/WebSerializedScriptValueVersion.h
index a808ae2..82774e90 100644
--- a/third_party/WebKit/public/web/WebSerializedScriptValueVersion.h
+++ b/third_party/WebKit/public/web/WebSerializedScriptValueVersion.h
@@ -38,7 +38,7 @@
 // Embedders may serialize this as out-of-band metadata along with
 // collections of serialized data so that version skew can be detected
 // before deserializing individual values.
-const unsigned kSerializedScriptValueVersion = 16;
+const unsigned kSerializedScriptValueVersion = 17;
 
 }  // namespace blink
 
diff --git a/tools/blink_rename_merge_helper/COMPONENTS b/tools/blink_rename_merge_helper/COMPONENTS
index b376ee0..3737ba94 100644
--- a/tools/blink_rename_merge_helper/COMPONENTS
+++ b/tools/blink_rename_merge_helper/COMPONENTS
@@ -4,7 +4,7 @@
   "bin-darwin": "f45f58ccbf42a26b0704f63d8740cf008b84afcc",
   "include-darwin": "7f1790ea6a3257dda2035fe885a33fbfe4078fed",
   "lib-darwin": "29baf57b55dd0ab060baf0cd6461a7e0fa0105f4",
-  "bin-linux*": "c7c76f202a6d0feb77dd946b2e605a1ba56d3046",
+  "bin-linux*": "b8f4be9eeb5ca49059f4d46ae5a1dedfb41e9acb",
   "lib-linux*": "508b0ba0de0b4191a54360330f74cea8afd5ee93",
   "bin-win32": "f8ff17a5f080cef7639140b057a0f61b4d1a4f8f",
   "lib-win32": "afb47503a4fd442c353ddaba6f17a81e6aa5a20f"
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
index d97c7ea..8b0af6a 100644
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -54,6 +54,11 @@
 const char kGMockMethodNamePrefix[] = "gmock_";
 const char kMethodBlocklistParamName[] = "method-blocklist";
 
+std::set<clang::SourceLocation>& GetRewrittenLocs() {
+  static auto& locations = *new std::set<clang::SourceLocation>();
+  return locations;
+}
+
 template <typename MatcherType, typename NodeType>
 bool IsMatching(const MatcherType& matcher,
                 const NodeType& node,
@@ -889,28 +894,8 @@
   StringRef original_name = decl.getName();
 
   // Nothing to do for unnamed parameters.
-  if (clang::isa<clang::ParmVarDecl>(decl)) {
-    if (original_name.empty())
-      return false;
-
-    // Check if |decl| and |decl.getLocation| are in sync.  We need to skip
-    // out-of-sync ParmVarDecls to avoid renaming buggy ParmVarDecls that
-    // 1) have decl.getLocation() pointing at a parameter declaration without a
-    // name, but 2) have decl.getName() retained from a template specialization
-    // of a method.  See also: https://llvm.org/bugs/show_bug.cgi?id=29145
-    clang::SourceLocation loc =
-        context.getSourceManager().getSpellingLoc(decl.getLocation());
-    auto parents = context.getParents(decl);
-    bool is_child_location_within_parent_source_range = std::all_of(
-        parents.begin(), parents.end(),
-        [&loc](const clang::ast_type_traits::DynTypedNode& parent) {
-          clang::SourceLocation begin = parent.getSourceRange().getBegin();
-          clang::SourceLocation end = parent.getSourceRange().getEnd();
-          return (begin < loc) && (loc < end);
-        });
-    if (!is_child_location_within_parent_source_range)
-      return false;
-  }
+  if (clang::isa<clang::ParmVarDecl>(decl) && original_name.empty())
+    return false;
 
   // This is a type trait that appears in consumers of WTF as well as inside
   // WTF. We want it to be named in this_style_of_case accordingly.
@@ -1149,8 +1134,16 @@
     if (actual_old_text != expected_old_text)
       return false;
 
-    if (replacement)
+    if (replacement) {
+      // If there's already a replacement for this location, don't emit any
+      // other replacements to avoid potential naming conflicts. This is
+      // primarily to avoid problems when a function and a parameter are defined
+      // by the same macro argument.
+      if (!GetRewrittenLocs().emplace(spell).second)
+        return false;
+
       *replacement = Replacement(source_manager, range, new_text);
+    }
     return true;
   }
 
diff --git a/tools/clang/rewrite_to_chrome_style/tests/bool-is-macro-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/bool-is-macro-expected.cc
new file mode 100644
index 0000000..374a094
--- /dev/null
+++ b/tools/clang/rewrite_to_chrome_style/tests/bool-is-macro-expected.cc
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace blink {
+
+// On Linux, bool can be a macro. Make sure this case is handled correctly.
+#define bool bool
+
+bool FunctionReturningBool(char* input_data) {
+  return input_data[0];
+}
+
+}  // namespace blink
diff --git a/tools/clang/rewrite_to_chrome_style/tests/bool-is-macro-original.cc b/tools/clang/rewrite_to_chrome_style/tests/bool-is-macro-original.cc
new file mode 100644
index 0000000..dcddee1
--- /dev/null
+++ b/tools/clang/rewrite_to_chrome_style/tests/bool-is-macro-original.cc
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace blink {
+
+// On Linux, bool can be a macro. Make sure this case is handled correctly.
+#define bool bool
+
+bool functionReturningBool(char* inputData) {
+  return inputData[0];
+}
+
+}  // namespace blink
diff --git a/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc
index 7136069..00ce6b21 100644
--- a/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc
+++ b/tools/clang/rewrite_to_chrome_style/tests/macros-expected.cc
@@ -19,7 +19,7 @@
 struct Base {};
 struct Derived : public Base {};
 
-DEFINE_TYPE_CASTS(Derived, Base, object, true);
+DEFINE_TYPE_CASTS(Derived, Base, the_object, true);
 
 void F() {
   Base* base_ptr = new Derived;
@@ -76,7 +76,7 @@
                                   \
  public:                          \
   int name() { return m_##name; } \
-  void Set##Name(int value) { m_##name = value; }
+  void Set##Name(int name) { m_##name = name; }
 
   DECLARE_FIELD(FooBar, FooBar)
   DECLARE_FIELD(BarBaz, BarBaz)
diff --git a/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc b/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc
index 8a924eba..78412c9 100644
--- a/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc
+++ b/tools/clang/rewrite_to_chrome_style/tests/macros-original.cc
@@ -19,7 +19,7 @@
 struct Base {};
 struct Derived : public Base {};
 
-DEFINE_TYPE_CASTS(Derived, Base, object, true);
+DEFINE_TYPE_CASTS(Derived, Base, theObject, true);
 
 void F() {
   Base* basePtr = new Derived;
@@ -76,7 +76,7 @@
                                   \
  public:                          \
   int name() { return m_##name; } \
-  void set##Name(int value) { m_##name = value; }
+  void set##Name(int name) { m_##name = name; }
 
   DECLARE_FIELD(fooBar, FooBar)
   DECLARE_FIELD(barBaz, BarBaz)
diff --git a/tools/clang/rewrite_to_chrome_style/tests/variables-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/variables-expected.cc
index 119edd6..7b8a3d8f 100644
--- a/tools/clang/rewrite_to_chrome_style/tests/variables-expected.cc
+++ b/tools/clang/rewrite_to_chrome_style/tests/variables-expected.cc
@@ -20,9 +20,9 @@
   // Static locals.
   static int a_static_local_variable = 2;
   // Make sure references to variables are also rewritten.
-  return g_frame_count +
-         g_variable_mentioning_http_and_https * interesting_number /
-             a_local_variable % a_static_local_variable;
+  return g_frame_count + g_variable_mentioning_http_and_https *
+                             interesting_number / a_local_variable %
+                             a_static_local_variable;
 }
 
 }  // namespace blink
diff --git a/tools/ipc_fuzzer/OWNERS b/tools/ipc_fuzzer/OWNERS
index 66e501b..1f569281 100644
--- a/tools/ipc_fuzzer/OWNERS
+++ b/tools/ipc_fuzzer/OWNERS
@@ -2,4 +2,4 @@
 mbarbella@chromium.org
 tsepez@chromium.org
 
-# COMPONENT: Tools
+# COMPONENT: Tools>Stability>Libfuzzer
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index bf14b47..dc2c81e 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -312,17 +312,6 @@
       'Mac ASan 64 Builder': 'asan_full_symbols_disable_nacl_release_bot_dcheck_always_on',
     },
 
-    'chromium.memory.fyi': {
-      'Chromium Linux ChromeOS MSan Builder': 'chromeos_msan_release_bot',
-      'Chromium Linux MSan Builder': 'msan_release_bot',
-    },
-
-    'chromium.memory.full': {
-      'Chromium Linux ChromeOS MSan Builder': 'chromeos_msan_release_bot',
-      'Chromium Linux MSan Builder': 'msan_release_bot',
-      'Chromium Linux TSan Builder': 'tsan_disable_nacl_release_bot',
-    },
-
     'chromium.perf': {
       'Android Builder': 'official_goma_minimal_symbols_android',
       'Android arm64 Builder': 'official_goma_minimal_symbols_android_arm64',
diff --git a/tools/metrics/histograms/extract_histograms.py b/tools/metrics/histograms/extract_histograms.py
index 61d7e864..6e53bc41 100644
--- a/tools/metrics/histograms/extract_histograms.py
+++ b/tools/metrics/histograms/extract_histograms.py
@@ -216,8 +216,7 @@
       value_dict['summary'] = _JoinChildNodes(int_tag)
       enum_dict['values'][int_value] = value_dict
 
-    enum_items = sorted(enum_dict['values'].iteritems(), key=lambda i: i[0])
-    enum_int_values = list(i[0] for i in enum_items)
+    enum_int_values = sorted(enum_dict['values'].keys())
 
     last_int_value = None
     for int_tag in enum.getElementsByTagName('int'):
@@ -230,9 +229,10 @@
         if left_item_index == 0:
           logging.warning('Insert value %d at the beginning', int_value)
         else:
-          left_int_value, left_value_dict = enum_items[left_item_index - 1]
+          left_int_value = enum_int_values[left_item_index - 1]
+          left_label = enum_dict['values'][left_int_value]['label']
           logging.warning('Insert value %d after %d ("%s")',
-                          int_value, left_int_value, left_value_dict['label'])
+                          int_value, left_int_value, left_label)
       else:
         last_int_value = int_value
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9cf7ba5..40b42f8 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -31336,6 +31336,15 @@
   </summary>
 </histogram>
 
+<histogram name="Navigation.IOSWKWebViewSlowFastBackForward"
+    enum="BackForwardNavigationType">
+  <owner>eugenebut@chromium.org</owner>
+  <summary>
+    Counts slow/fast back/forward WKWebView navigations on iOS. Fast navigation
+    is a back/forward navigation done with WKBackForwardList.
+  </summary>
+</histogram>
+
 <histogram name="Navigation.IsMobileOptimized" enum="BooleanIsMobileOptimized">
   <owner>cjhopman@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
@@ -34773,6 +34782,30 @@
   </summary>
 </histogram>
 
+<histogram name="Net.HttpStreamFactoryJob.Alt.NextState"
+    enum="HttpStreamFactoryJobState">
+  <owner>xunjieli@chromium.org</owner>
+  <summary>Reports the next state that the Alternative Job is in.</summary>
+</histogram>
+
+<histogram name="Net.HttpStreamFactoryJob.Alt.State"
+    enum="HttpStreamFactoryJobState">
+  <owner>xunjieli@chromium.org</owner>
+  <summary>Reports the state that the Alternative Job is in.</summary>
+</histogram>
+
+<histogram name="Net.HttpStreamFactoryJob.Main.NextState"
+    enum="HttpStreamFactoryJobState">
+  <owner>xunjieli@chromium.org</owner>
+  <summary>Reports the next state that the Main Job is in.</summary>
+</histogram>
+
+<histogram name="Net.HttpStreamFactoryJob.Main.State"
+    enum="HttpStreamFactoryJobState">
+  <owner>xunjieli@chromium.org</owner>
+  <summary>Reports the state that the Main Job is in.</summary>
+</histogram>
+
 <histogram name="Net.HttpStreamFactoryJob.StreamReadyCallbackTime" units="ms">
   <owner>zhongyi@chromium.org</owner>
   <summary>Time it takes for OnStreamReadyCallback to be called.</summary>
@@ -83864,6 +83897,13 @@
   <int value="2" label="Ok, got it"/>
 </enum>
 
+<enum name="BackForwardNavigationType" type="int">
+  <int value="0" label="Fast back navigation with WKBackForwardList"/>
+  <int value="1" label="Slow back navigation"/>
+  <int value="2" label="Fast forward navigation with WKBackForwardList"/>
+  <int value="3" label="Slow forward navigation"/>
+</enum>
+
 <enum name="BackgroundFetchEventDispatchResult" type="int">
   <int value="0" label="Success"/>
   <int value="1" label="Cannot find worker"/>
@@ -98560,6 +98600,29 @@
   </int>
 </enum>
 
+<enum name="HttpStreamFactoryJobState" type="int">
+  <summary>
+    State of HttpStreamFactoryJob.  See net::HttpStreamFactoryImpl::Job::State
+    for more details
+  </summary>
+  <int value="0" label="START"/>
+  <int value="1" label="RESOLVE_PROXY"/>
+  <int value="2" label="RESOLVE_PROXY_COMPLETE"/>
+  <int value="3" label="WAIT"/>
+  <int value="4" label="WAIT_COMPLETE"/>
+  <int value="5" label="INIT_CONNECTION"/>
+  <int value="6" label="INIT_CONNECTION_COMPLETE"/>
+  <int value="7" label="WAITING_USER_ACTION"/>
+  <int value="8" label="RESTART_TUNNEL_AUTH"/>
+  <int value="9" label="RESTART_TUNNEL_AUTH_COMPLETE"/>
+  <int value="10" label="CREATE_STREAM"/>
+  <int value="11" label="CREATE_STREAM_COMPLETE"/>
+  <int value="12" label="DRAIN_BODY_FOR_AUTH_RESTART"/>
+  <int value="13" label="DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE"/>
+  <int value="14" label="DONE"/>
+  <int value="15" label="NONE"/>
+</enum>
+
 <enum name="ICCProfileAnalyzeResult" type="int">
   <int value="0"
       label="Extracted primary matrix and numerical transfer function"/>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 0c8de0a..4a0565a8 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -162,7 +162,7 @@
 system_health.memory_mobile,perezju@chromium.org,
 system_health.webview_startup,"perezju@chromium.org, torne@chromium.org",
 system_health.webview_startup_multiprocess,,
-tab_switching.typical_25,,
+tab_switching.typical_25,vovoy@chromium.org,OS>Performance
 text_selection.character,mfomitchev@chromium.org,
 text_selection.direction,mfomitchev@chromium.org,
 thread_times.key_hit_test_cases,,
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 927965e..b4b42eca 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -580,8 +580,8 @@
   ]
 
 
-def generate_telemetry_tests(
-  tester_config, benchmarks, benchmark_sharding_map, use_whitelist):
+def generate_telemetry_tests(tester_config, benchmarks, benchmark_sharding_map,
+                             use_whitelist, benchmark_ref_build_blacklist):
   isolated_scripts = []
   # First determine the browser that you need based on the tester
   browser_name = ''
@@ -624,13 +624,15 @@
       swarming_dimensions, benchmark.Name(), browser_name)
     isolated_scripts.append(test)
     # Now create another executable for this benchmark on the reference browser
-    reference_test = generate_telemetry_test(
-      swarming_dimensions, benchmark.Name(),'reference')
-    isolated_scripts.append(reference_test)
-    if current_shard == (num_shards - 1):
-      current_shard = 0
-    else:
-      current_shard += 1
+    # if it is not blacklisted from running on the reference browser.
+    if benchmark.Name() not in benchmark_ref_build_blacklist:
+      reference_test = generate_telemetry_test(
+        swarming_dimensions, benchmark.Name(),'reference')
+      isolated_scripts.append(reference_test)
+      if current_shard == (num_shards - 1):
+        current_shard = 0
+      else:
+        current_shard += 1
 
   return isolated_scripts
 
@@ -668,6 +670,12 @@
   'Win 10 High-DPI Perf',
 ]
 
+# List of benchmarks that are to never be run with reference builds.
+BENCHMARK_REF_BUILD_BLACKLIST = [
+  'power.idle_platform',
+]
+
+
 def current_benchmarks(use_whitelist):
   benchmarks_dir = os.path.join(src_dir(), 'tools', 'perf', 'benchmarks')
   top_level_dir = os.path.dirname(benchmarks_dir)
@@ -768,7 +776,8 @@
       if name in LEGACY_DEVICE_AFFIINITY_ALGORITHM:
         sharding_map = None
       isolated_scripts = generate_telemetry_tests(
-          config, benchmark_list, sharding_map, use_whitelist)
+          config, benchmark_list, sharding_map, use_whitelist,
+          BENCHMARK_REF_BUILD_BLACKLIST)
       # Generate swarmed non-telemetry tests if present
       if config['swarming_dimensions'][0].get('perf_tests', False):
         isolated_scripts += generate_cplusplus_isolate_script_test(
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py
index 4aad5c30..4301ffa 100644
--- a/tools/perf/core/perf_data_generator_unittest.py
+++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -6,6 +6,8 @@
 from core import perf_data_generator
 from core.perf_data_generator import BenchmarkMetadata
 
+from telemetry import benchmark
+
 
 class PerfDataGeneratorTest(unittest.TestCase):
   def setUp(self):
@@ -111,3 +113,30 @@
         'isolate_name': 'telemetry_perf_tests',
       }
     self.assertEquals(test, expected_generated_test)
+
+  def testGenerateTelemetryTestsBlacklistedReferenceBuildTest(self):
+    class BlacklistedBenchmark(benchmark.Benchmark):
+      @classmethod
+      def Name(cls):
+        return 'blacklisted'
+
+    class NotBlacklistedBenchmark(benchmark.Benchmark):
+      @classmethod
+      def Name(cls):
+        return 'not_blacklisted'
+
+    swarming_dimensions = [
+        {'os': 'SkyNet', 'id': 'T-850', 'pool': 'T-RIP', 'device_ids': ['a']}
+    ]
+    test_config = {
+        'platform': 'android',
+        'swarming_dimensions': swarming_dimensions,
+    }
+    benchmarks = [BlacklistedBenchmark, NotBlacklistedBenchmark]
+    tests = perf_data_generator.generate_telemetry_tests(
+        test_config, benchmarks, None, False, ['blacklisted'])
+
+    generated_test_names = set(t['name'] for t in tests)
+    self.assertEquals(
+        generated_test_names,
+        {'blacklisted', 'not_blacklisted', 'not_blacklisted.reference'})
diff --git a/tools/win/subtract_time.py b/tools/win/subtract_time.py
new file mode 100644
index 0000000..4e1559b
--- /dev/null
+++ b/tools/win/subtract_time.py
@@ -0,0 +1,20 @@
+# Copyright (c) 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.
+
+"""
+This script converts to %time% compatible strings passed to it into seconds,
+subtracts them, and prints the difference. That's it. It's used by timeit.bat.
+"""
+
+import re
+import sys
+
+def ParseTime(time_string):
+  # Time looks like 15:19:30.32
+  match = re.match("(.*):(.*):(.*)\.(.*)", time_string)
+  hours, minutes, seconds, fraction = map(int, match.groups())
+  return hours * 3600 + minutes * 60 + seconds + fraction * .01
+
+print "%1.2f seconds elapsed time" % (ParseTime(sys.argv[1]) -
+                                      ParseTime(sys.argv[2]))
diff --git a/tools/win/timeit.bat b/tools/win/timeit.bat
new file mode 100755
index 0000000..af00372
--- /dev/null
+++ b/tools/win/timeit.bat
@@ -0,0 +1,13 @@
+@ECHO off
+
+REM Copyright (c) 2017 The Chromium Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+
+REM This batch file executes the commands passed to it and prints out the
+REM elapsed run time.
+
+SETLOCAL
+SET starttime=%time%
+CALL %*
+CALL python %~dp0subtract_time.py %time% %starttime%
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 3f37fc2..5a6d887 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -1083,7 +1083,7 @@
   // to use a compatible config. We expect the client to request RGB565
   // onscreen surface also for this to work (with the exception of
   // fullscreen video).
-  if (base::SysInfo::IsLowEndDevice())
+  if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512)
     format.SetRGB565();
 #endif
 
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"