diff --git a/DEPS b/DEPS
index 4a1b0d5..e9ffd66 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'e76eceac137f0a794cec9da31d63efba811e59e7',
+  'v8_revision': 'c37ce45885b240650b0a5e29ee4a8e620d790f6b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'c6fd58d69bd8895137364c4a1b0bcd08a2ce8c46',
+  'pdfium_revision': 'd3b90ac1ee24e6e79f3b852f2c61135e099e7df1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '27252354126c731d23022e1118b311bcfa0c8a3f',
+  'catapult_revision': 'deb2d7670a64dd33163f3c6e7c95b7066188e2f5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -235,7 +235,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'f75b6fa09dc229d1fac9c050c56c0943a5ff01ce', # commit position 18538
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'e65f13714155819b16eebd32a1845f25258aa13c', # commit position 18559
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/base/BUILD.gn b/base/BUILD.gn
index d8893d8..3eeede0 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -884,6 +884,8 @@
     "threading/post_task_and_reply_impl.h",
     "threading/sequence_local_storage_map.cc",
     "threading/sequence_local_storage_map.h",
+    "threading/sequence_local_storage_slot.cc",
+    "threading/sequence_local_storage_slot.h",
     "threading/sequenced_task_runner_handle.cc",
     "threading/sequenced_task_runner_handle.h",
     "threading/sequenced_worker_pool.cc",
@@ -2201,6 +2203,7 @@
     "threading/platform_thread_unittest.cc",
     "threading/post_task_and_reply_impl_unittest.cc",
     "threading/sequence_local_storage_map_unittest.cc",
+    "threading/sequence_local_storage_slot_unittest.cc",
     "threading/sequenced_task_runner_handle_unittest.cc",
     "threading/sequenced_worker_pool_unittest.cc",
     "threading/simple_thread_unittest.cc",
diff --git a/base/threading/sequence_local_storage_map.h b/base/threading/sequence_local_storage_map.h
index 1d24727..95ea2b2 100644
--- a/base/threading/sequence_local_storage_map.h
+++ b/base/threading/sequence_local_storage_map.h
@@ -18,6 +18,9 @@
 // ScopedSetSequenceMapLocalStorageForCurrentThread. When a
 // SequenceLocalStorageMap is destroyed, it invokes the destructors associated
 // with values stored within it.
+// The Get() and Set() methods should not be accessed directly.
+// Use SequenceLocalStorageSlot to Get() and Set() values in the current
+// sequence's SequenceLocalStorageMap.
 class BASE_EXPORT SequenceLocalStorageMap {
  public:
   SequenceLocalStorageMap();
diff --git a/base/threading/sequence_local_storage_slot.cc b/base/threading/sequence_local_storage_slot.cc
new file mode 100644
index 0000000..df1c131
--- /dev/null
+++ b/base/threading/sequence_local_storage_slot.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 "base/threading/sequence_local_storage_slot.h"
+
+#include <limits>
+
+#include "base/atomic_sequence_num.h"
+#include "base/logging.h"
+
+namespace base {
+namespace internal {
+
+namespace {
+StaticAtomicSequenceNumber g_sequence_local_storage_slot_generator;
+}  // namespace
+
+int GetNextSequenceLocalStorageSlotNumber() {
+  int slot_id = g_sequence_local_storage_slot_generator.GetNext();
+  DCHECK_LT(slot_id, std::numeric_limits<int>::max());
+  return slot_id;
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/threading/sequence_local_storage_slot.h b/base/threading/sequence_local_storage_slot.h
new file mode 100644
index 0000000..afb3e05
--- /dev/null
+++ b/base/threading/sequence_local_storage_slot.h
@@ -0,0 +1,108 @@
+// 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 BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
+#define BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
+
+#include <memory>
+#include <utility>
+
+#include "base/base_export.h"
+#include "base/threading/sequence_local_storage_map.h"
+
+namespace base {
+
+namespace internal {
+BASE_EXPORT int GetNextSequenceLocalStorageSlotNumber();
+}
+
+// SequenceLocalStorageSlot allows arbitrary values to be stored and retrieved
+// from a sequence. Values are deleted when the sequence is deleted.
+//
+// Example usage:
+//
+// namespace {
+// base::LazyInstance<SequenceLocalStorageSlot<int>> sls_value;
+// }
+//
+// void Read() {
+//   int value = sls_value.Get().Get();
+//   ...
+// }
+//
+// void Write() {
+//   sls_value.Get().Set(42);
+// }
+//
+// void PostTasks() {
+//   // Since Read() runs on the same sequence as Write(), it
+//   // will read the value "42". A Read() running on a different
+//   // sequence would not see that value.
+//   scoped_refptr<base::SequencedTaskRunner> task_runner = ...;
+//   task_runner->PostTask(FROM_HERE, base::BindOnce(&Write));
+//   task_runner->PostTask(FROM_HERE, base::BindOnce(&Read));
+// }
+//
+// SequenceLocalStorageSlot must be used within the scope of a
+// ScopedSetSequenceLocalStorageMapForCurrentThread object.
+//
+// TODO(jeffreyhe): Mention that TaskScheduler and MessageLoop run
+// tasks within the scope of a
+// ScopedSetSequenceLocalStorageMapForCurrentThread object once this
+// is true.
+template <typename T, typename Deleter = std::default_delete<T>>
+class SequenceLocalStorageSlot {
+ public:
+  SequenceLocalStorageSlot()
+      : slot_id_(internal::GetNextSequenceLocalStorageSlotNumber()) {}
+  ~SequenceLocalStorageSlot() = default;
+
+  // Get the sequence-local value stored in this slot. Returns a
+  // default-constructed value if no value was previously set.
+  T& Get() {
+    void* value =
+        internal::SequenceLocalStorageMap::GetForCurrentThread().Get(slot_id_);
+
+    // Sets and returns a default-constructed value if no value was previously
+    // set.
+    if (!value) {
+      Set(T());
+      return Get();
+    }
+    return *(static_cast<T*>(value));
+  }
+
+  // Set this slot's sequence-local value to |value|.
+  // Note that if T is expensive to copy, it may be more appropriate to instead
+  // store a std::unique_ptr<T>. This is enforced by the
+  // DISALLOW_COPY_AND_ASSIGN style rather than directly by this class however.
+  void Set(T value) {
+    // Allocates the |value| with new rather than MakeUnique.
+    // Since SequenceLocalStorageMap needs to store values of various types
+    // within the same map, the type of value_destructor_pair.value is void*
+    // (std::unique_ptr<void> is invalid). Memory is freed by calling
+    // |value_destructor_pair.destructor| in the destructor of
+    // ValueDestructorPair which is invoked when the value is overwritten by
+    // another call to SequenceLocalStorageMap::Set or when the
+    // SequenceLocalStorageMap is deleted.
+    T* value_ptr = new T(std::move(value));
+
+    internal::SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc*
+        destructor = [](void* ptr) { Deleter()(static_cast<T*>(ptr)); };
+
+    internal::SequenceLocalStorageMap::ValueDestructorPair
+        value_destructor_pair(value_ptr, destructor);
+
+    internal::SequenceLocalStorageMap::GetForCurrentThread().Set(
+        slot_id_, std::move(value_destructor_pair));
+  }
+
+ private:
+  // |slot_id_| is used as a key in SequenceLocalStorageMap
+  const int slot_id_;
+  DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlot);
+};
+
+}  // namespace base
+#endif  // BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
diff --git a/base/threading/sequence_local_storage_slot_unittest.cc b/base/threading/sequence_local_storage_slot_unittest.cc
new file mode 100644
index 0000000..84750f10
--- /dev/null
+++ b/base/threading/sequence_local_storage_slot_unittest.cc
@@ -0,0 +1,143 @@
+// 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 "base/threading/sequence_local_storage_slot.h"
+
+#include <utility>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/sequence_local_storage_map.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+class SequenceLocalStorageSlotTest : public testing::Test {
+ protected:
+  SequenceLocalStorageSlotTest()
+      : scoped_sequence_local_storage_(&sequence_local_storage_) {}
+
+  internal::SequenceLocalStorageMap sequence_local_storage_;
+  internal::ScopedSetSequenceLocalStorageMapForCurrentThread
+      scoped_sequence_local_storage_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlotTest);
+};
+
+}  // namespace
+
+// Verify that a value stored with Set() can be retrieved with Get().
+TEST_F(SequenceLocalStorageSlotTest, GetSet) {
+  SequenceLocalStorageSlot<int> slot;
+  slot.Set(5);
+  EXPECT_EQ(slot.Get(), 5);
+}
+
+// Verify that setting an object in a SequenceLocalStorageSlot creates a copy
+// of that object independent of the original one.
+TEST_F(SequenceLocalStorageSlotTest, SetObjectIsIndependent) {
+  bool should_be_false = false;
+
+  SequenceLocalStorageSlot<bool> slot;
+
+  slot.Set(should_be_false);
+
+  EXPECT_FALSE(slot.Get());
+  slot.Get() = true;
+  EXPECT_TRUE(slot.Get());
+
+  EXPECT_NE(should_be_false, slot.Get());
+}
+
+// Verify that multiple slots work and that calling Get after overwriting
+// a value in a slot yields the new value.
+TEST_F(SequenceLocalStorageSlotTest, GetSetMultipleSlots) {
+  SequenceLocalStorageSlot<int> slot1;
+  SequenceLocalStorageSlot<int> slot2;
+  SequenceLocalStorageSlot<int> slot3;
+
+  slot1.Set(1);
+  slot2.Set(2);
+  slot3.Set(3);
+
+  EXPECT_EQ(slot1.Get(), 1);
+  EXPECT_EQ(slot2.Get(), 2);
+  EXPECT_EQ(slot3.Get(), 3);
+
+  slot3.Set(4);
+  slot2.Set(5);
+  slot1.Set(6);
+
+  EXPECT_EQ(slot3.Get(), 4);
+  EXPECT_EQ(slot2.Get(), 5);
+  EXPECT_EQ(slot1.Get(), 6);
+}
+
+// Verify that changing the the value returned by Get() changes the value
+// in sequence local storage.
+TEST_F(SequenceLocalStorageSlotTest, GetReferenceModifiable) {
+  SequenceLocalStorageSlot<bool> slot;
+  slot.Set(false);
+  slot.Get() = true;
+  EXPECT_TRUE(slot.Get());
+}
+
+// Verify that a move-only type can be stored in sequence local storage.
+TEST_F(SequenceLocalStorageSlotTest, SetGetWithMoveOnlyType) {
+  std::unique_ptr<int> int_unique_ptr = MakeUnique<int>(5);
+
+  SequenceLocalStorageSlot<std::unique_ptr<int>> slot;
+  slot.Set(std::move(int_unique_ptr));
+
+  EXPECT_EQ(*slot.Get(), 5);
+}
+
+// Verify that a Get() without a previous Set() on a slot returns a
+// default-constructed value.
+TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructs) {
+  struct DefaultConstructable {
+    int x = 0x12345678;
+  };
+
+  SequenceLocalStorageSlot<DefaultConstructable> slot;
+
+  EXPECT_EQ(slot.Get().x, 0x12345678);
+}
+
+// Verify that a Get() without a previous Set() on a slot with a POD-type
+// returns a default-constructed value.
+// Note: this test could be flaky and give a false pass. If it's flaky, the test
+// might've "passed" because the memory for the slot happened to be zeroed.
+TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructsPOD) {
+  SequenceLocalStorageSlot<void*> slot;
+
+  EXPECT_EQ(slot.Get(), nullptr);
+}
+
+// Verify that the value of a slot is specific to a SequenceLocalStorageMap
+TEST(SequenceLocalStorageSlotMultipleMapTest, SetGetMultipleMapsOneSlot) {
+  SequenceLocalStorageSlot<unsigned int> slot;
+  internal::SequenceLocalStorageMap sequence_local_storage_maps[5];
+
+  // Set the value of the slot to be the index of the current
+  // SequenceLocalStorageMaps in the vector
+  for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
+    internal::ScopedSetSequenceLocalStorageMapForCurrentThread
+        scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
+
+    slot.Set(i);
+  }
+
+  for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
+    internal::ScopedSetSequenceLocalStorageMapForCurrentThread
+        scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
+
+    EXPECT_EQ(slot.Get(), i);
+  }
+}
+
+}  // namespace base
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index dbd70488..c886a26 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -637,6 +637,7 @@
 
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     constexpr bool disable_display_vsync = false;
@@ -646,7 +647,8 @@
     return base::MakeUnique<TestCompositorFrameSink>(
         compositor_context_provider, std::move(worker_context_provider),
         shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings,
-        ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync);
+        ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync,
+        refresh_rate);
   }
 
   void AdvanceTestCase() {
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index e8215673..de23ab3 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -3313,7 +3313,7 @@
 class GLRendererPixelTestWithOverdrawFeedback : public GLRendererPixelTest {
  protected:
   void SetUp() override {
-    settings_.renderer_settings.show_overdraw_feedback = true;
+    renderer_settings_.show_overdraw_feedback = true;
     GLRendererPixelTest::SetUp();
   }
 };
@@ -3370,7 +3370,7 @@
       public testing::WithParamInterface<ColorSpacePair> {
  public:
   ColorTransformPixelTest() {
-    settings_.renderer_settings.enable_color_correct_rendering = true;
+    renderer_settings_.enable_color_correct_rendering = true;
     // Note that this size of 17 is not random -- it is chosen to match the
     // size of LUTs that are created. If we did not match the LUT size exactly,
     // then the error for LUT based transforms is much larger.
diff --git a/cc/output/renderer_settings.h b/cc/output/renderer_settings.h
index a2576ac..47c0fc7 100644
--- a/cc/output/renderer_settings.h
+++ b/cc/output/renderer_settings.h
@@ -29,10 +29,6 @@
   bool gl_composited_texture_quad_border = false;
   bool show_overdraw_feedback = false;
   bool enable_color_correct_rendering = false;
-
-  // TODO(staraz): Move |refresh_rate| out. It's only used by
-  // TestCompositorFrameSink
-  double refresh_rate = 60.0;
   int highp_threshold_min = 0;
 
   // Determines whether we disallow non-exact matches when finding resources
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc
index 89dd3d6b..ce61a691 100644
--- a/cc/test/layer_tree_pixel_test.cc
+++ b/cc/test/layer_tree_pixel_test.cc
@@ -41,6 +41,7 @@
 std::unique_ptr<TestCompositorFrameSink>
 LayerTreePixelTest::CreateCompositorFrameSink(
     const RendererSettings& renderer_settings,
+    double refresh_rate,
     scoped_refptr<ContextProvider>,
     scoped_refptr<ContextProvider>) {
   scoped_refptr<TestInProcessContextProvider> compositor_context_provider;
@@ -57,7 +58,8 @@
   auto delegating_output_surface = base::MakeUnique<TestCompositorFrameSink>(
       compositor_context_provider, std::move(worker_context_provider),
       shared_bitmap_manager(), gpu_memory_buffer_manager(), RendererSettings(),
-      ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync);
+      ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync,
+      refresh_rate);
   delegating_output_surface->SetEnlargePassTextureAmount(
       enlarge_texture_amount_);
   return delegating_output_surface;
diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h
index 04c561a9..26f9da68f 100644
--- a/cc/test/layer_tree_pixel_test.h
+++ b/cc/test/layer_tree_pixel_test.h
@@ -38,6 +38,7 @@
   // LayerTreeTest overrides.
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override;
   std::unique_ptr<OutputSurface> CreateDisplayOutputSurfaceOnThread(
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 79538563..67b7028 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -864,11 +864,11 @@
   RendererSettings renderer_settings;
   // Spend less time waiting for BeginFrame because the output is
   // mocked out.
-  renderer_settings.refresh_rate = 200.0;
+  constexpr double refresh_rate = 200.0;
   renderer_settings.resource_settings.buffer_to_texture_target_map =
       DefaultBufferToTextureTargetMapForTesting();
   auto compositor_frame_sink = CreateCompositorFrameSink(
-      renderer_settings, std::move(shared_context_provider),
+      renderer_settings, refresh_rate, std::move(shared_context_provider),
       std::move(worker_context_provider));
   compositor_frame_sink->SetClient(compositor_frame_sink_client_.get());
   layer_tree_host_->SetCompositorFrameSink(std::move(compositor_frame_sink));
@@ -877,6 +877,7 @@
 std::unique_ptr<TestCompositorFrameSink>
 LayerTreeTest::CreateCompositorFrameSink(
     const RendererSettings& renderer_settings,
+    double refresh_rate,
     scoped_refptr<ContextProvider> compositor_context_provider,
     scoped_refptr<ContextProvider> worker_context_provider) {
   constexpr bool disable_display_vsync = false;
@@ -886,7 +887,8 @@
   return base::MakeUnique<TestCompositorFrameSink>(
       compositor_context_provider, std::move(worker_context_provider),
       shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings,
-      impl_task_runner_, synchronous_composite, disable_display_vsync);
+      impl_task_runner_, synchronous_composite, disable_display_vsync,
+      refresh_rate);
 }
 
 std::unique_ptr<OutputSurface>
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 1970a55..67f927e8 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -140,6 +140,7 @@
   // TestCompositorFrameSink to control how it is created.
   virtual std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider);
   // Override this and call the base class to change what ContextProvider will
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 59f84f8..401923d 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -178,8 +178,8 @@
       base::ThreadTaskRunnerHandle::Get());
 
   renderer_ = base::MakeUnique<GLRenderer>(
-      &settings_.renderer_settings, output_surface_.get(),
-      resource_provider_.get(), texture_mailbox_deleter_.get());
+      &renderer_settings_, output_surface_.get(), resource_provider_.get(),
+      texture_mailbox_deleter_.get());
   renderer_->Initialize();
   renderer_->SetVisible(true);
 }
@@ -202,8 +202,7 @@
       settings_.enable_color_correct_rasterization,
       settings_.resource_settings);
   auto renderer = base::MakeUnique<SoftwareRenderer>(
-      &settings_.renderer_settings, output_surface_.get(),
-      resource_provider_.get());
+      &renderer_settings_, output_surface_.get(), resource_provider_.get());
   software_renderer_ = renderer.get();
   renderer_ = std::move(renderer);
   renderer_->Initialize();
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index e7791c8..cf285e5 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -55,6 +55,7 @@
   }
 
   LayerTreeSettings settings_;
+  RendererSettings renderer_settings_;
   gfx::Size device_viewport_size_;
   bool disable_picture_quad_image_filtering_;
   std::unique_ptr<FakeOutputSurfaceClient> output_surface_client_;
diff --git a/cc/test/test_compositor_frame_sink.cc b/cc/test/test_compositor_frame_sink.cc
index 6b4a5a5..f03d709c 100644
--- a/cc/test/test_compositor_frame_sink.cc
+++ b/cc/test/test_compositor_frame_sink.cc
@@ -29,7 +29,8 @@
     const RendererSettings& renderer_settings,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     bool synchronous_composite,
-    bool disable_display_vsync)
+    bool disable_display_vsync,
+    double refresh_rate)
     : CompositorFrameSink(std::move(compositor_context_provider),
                           std::move(worker_context_provider),
                           gpu_memory_buffer_manager,
@@ -37,6 +38,7 @@
       synchronous_composite_(synchronous_composite),
       disable_display_vsync_(disable_display_vsync),
       renderer_settings_(renderer_settings),
+      refresh_rate_(refresh_rate),
       task_runner_(std::move(task_runner)),
       frame_sink_id_(kCompositorFrameSinkId),
       surface_manager_(new SurfaceManager),
@@ -75,8 +77,7 @@
       begin_frame_source_.reset(new DelayBasedBeginFrameSource(
           base::MakeUnique<DelayBasedTimeSource>(task_runner_.get())));
       begin_frame_source_->SetAuthoritativeVSyncInterval(
-          base::TimeDelta::FromMilliseconds(1000.f /
-                                            renderer_settings_.refresh_rate));
+          base::TimeDelta::FromMilliseconds(1000.f / refresh_rate_));
     }
     scheduler.reset(new DisplayScheduler(
         begin_frame_source_.get(), task_runner_.get(),
diff --git a/cc/test/test_compositor_frame_sink.h b/cc/test/test_compositor_frame_sink.h
index 0440111..7c27af4 100644
--- a/cc/test/test_compositor_frame_sink.h
+++ b/cc/test/test_compositor_frame_sink.h
@@ -58,7 +58,8 @@
       const RendererSettings& renderer_settings,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       bool synchronous_composite,
-      bool disable_display_vsync);
+      bool disable_display_vsync,
+      double refresh_rate);
   ~TestCompositorFrameSink() override;
 
   // This client must be set before BindToClient() happens.
@@ -104,6 +105,7 @@
   const bool synchronous_composite_;
   const bool disable_display_vsync_;
   const RendererSettings renderer_settings_;
+  const double refresh_rate_;
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 22661bbd..049ced41 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -8102,8 +8102,9 @@
       : LayerImpl(tree_impl, id) {}
 };
 
-// Make sure damage tracking propagates all the way to the graphics context,
-// where it should request to swap only the sub-buffer that is damaged.
+// Make sure damage tracking propagates all the way to the CompositorFrame
+// submitted to the CompositorFrameSink, where it should request to swap only
+// the sub-buffer that is damaged.
 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
   scoped_refptr<TestContextProvider> context_provider(
       TestContextProvider::Create());
@@ -8118,7 +8119,6 @@
   // This test creates its own LayerTreeHostImpl, so
   // that we can force partial swap enabled.
   LayerTreeSettings settings = DefaultSettings();
-  settings.renderer_settings.partial_swap_enabled = true;
   std::unique_ptr<LayerTreeHostImpl> layer_tree_host_impl =
       LayerTreeHostImpl::Create(
           settings, this, &task_runner_provider_, &stats_instrumentation_,
@@ -8240,138 +8240,6 @@
       : LayerImpl(tree_impl, id) {}
 };
 
-static std::unique_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
-    LayerTreeSettings settings,
-    bool partial_swap,
-    LayerTreeHostImplClient* client,
-    TaskRunnerProvider* task_runner_provider,
-    TaskGraphRunner* task_graph_runner,
-    RenderingStatsInstrumentation* stats_instrumentation,
-    CompositorFrameSink* compositor_frame_sink) {
-  settings.renderer_settings.partial_swap_enabled = partial_swap;
-  std::unique_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
-      settings, client, task_runner_provider, stats_instrumentation,
-      task_graph_runner, AnimationHost::CreateForTesting(ThreadInstance::IMPL),
-      0, nullptr);
-  my_host_impl->SetVisible(true);
-  my_host_impl->InitializeRenderer(compositor_frame_sink);
-  my_host_impl->WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2));
-  my_host_impl->SetViewportSize(gfx::Size(100, 100));
-
-  /*
-    Layers are created as follows:
-
-    +--------------------+
-    |                  1 |
-    |  +-----------+     |
-    |  |         2 |     |
-    |  | +-------------------+
-    |  | |   3               |
-    |  | +-------------------+
-    |  |           |     |
-    |  +-----------+     |
-    |                    |
-    |                    |
-    +--------------------+
-
-    Layers 1, 2 have render surfaces
-  */
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(my_host_impl->active_tree(), 1);
-  std::unique_ptr<LayerImpl> child =
-      LayerImpl::Create(my_host_impl->active_tree(), 2);
-  std::unique_ptr<LayerImpl> grand_child =
-      FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
-
-  gfx::Rect root_rect(0, 0, 100, 100);
-  gfx::Rect child_rect(10, 10, 50, 50);
-  gfx::Rect grand_child_rect(5, 5, 150, 150);
-
-  root->test_properties()->force_render_surface = true;
-  root->SetPosition(gfx::PointF(root_rect.origin()));
-  root->SetBounds(root_rect.size());
-  root->draw_properties().visible_layer_rect = root_rect;
-  root->SetDrawsContent(false);
-
-  child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
-  child->test_properties()->opacity = 0.5f;
-  child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
-  child->draw_properties().visible_layer_rect = child_rect;
-  child->SetDrawsContent(false);
-  child->test_properties()->force_render_surface = true;
-
-  grand_child->SetPosition(gfx::PointF(grand_child_rect.origin()));
-  grand_child->SetBounds(grand_child_rect.size());
-  grand_child->draw_properties().visible_layer_rect = grand_child_rect;
-  grand_child->SetDrawsContent(true);
-
-  child->test_properties()->AddChild(std::move(grand_child));
-  root->test_properties()->AddChild(std::move(child));
-
-  my_host_impl->active_tree()->SetRootLayerForTesting(std::move(root));
-  my_host_impl->active_tree()->BuildPropertyTreesForTesting();
-  return my_host_impl;
-}
-
-TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
-  TestTaskGraphRunner task_graph_runner;
-  scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
-  provider->BindToCurrentThread();
-  provider->TestContext3d()->set_have_post_sub_buffer(true);
-  std::unique_ptr<CompositorFrameSink> compositor_frame_sink(
-      FakeCompositorFrameSink::Create3d(provider));
-  std::unique_ptr<LayerTreeHostImpl> my_host_impl = SetupLayersForOpacity(
-      DefaultSettings(), true, this, &task_runner_provider_, &task_graph_runner,
-      &stats_instrumentation_, compositor_frame_sink.get());
-  {
-    TestFrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
-
-    // Verify all quads have been computed
-    ASSERT_EQ(2U, frame.render_passes.size());
-    ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
-    ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
-    EXPECT_EQ(DrawQuad::SOLID_COLOR,
-              frame.render_passes[0]->quad_list.front()->material);
-    EXPECT_EQ(DrawQuad::RENDER_PASS,
-              frame.render_passes[1]->quad_list.front()->material);
-
-    my_host_impl->DrawLayers(&frame);
-    my_host_impl->DidDrawAllLayers(frame);
-  }
-  my_host_impl->ReleaseCompositorFrameSink();
-}
-
-TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
-  TestTaskGraphRunner task_graph_runner;
-  scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
-  provider->BindToCurrentThread();
-  provider->TestContext3d()->set_have_post_sub_buffer(true);
-  std::unique_ptr<CompositorFrameSink> compositor_frame_sink(
-      FakeCompositorFrameSink::Create3d(provider));
-  std::unique_ptr<LayerTreeHostImpl> my_host_impl = SetupLayersForOpacity(
-      DefaultSettings(), false, this, &task_runner_provider_,
-      &task_graph_runner, &stats_instrumentation_, compositor_frame_sink.get());
-  {
-    TestFrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
-
-    // Verify all quads have been computed
-    ASSERT_EQ(2U, frame.render_passes.size());
-    ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
-    ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
-    EXPECT_EQ(DrawQuad::SOLID_COLOR,
-              frame.render_passes[0]->quad_list.front()->material);
-    EXPECT_EQ(DrawQuad::RENDER_PASS,
-              frame.render_passes[1]->quad_list.front()->material);
-
-    my_host_impl->DrawLayers(&frame);
-    my_host_impl->DidDrawAllLayers(frame);
-  }
-  my_host_impl->ReleaseCompositorFrameSink();
-}
-
 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
   std::unique_ptr<TestWebGraphicsContext3D> context =
       TestWebGraphicsContext3D::Create();
@@ -8986,10 +8854,11 @@
 
   constexpr bool synchronous_composite = true;
   constexpr bool disable_display_vsync = false;
+  constexpr double refresh_rate = 60.0;
   auto compositor_frame_sink = base::MakeUnique<TestCompositorFrameSink>(
       context_provider, TestContextProvider::CreateWorker(), nullptr, nullptr,
       RendererSettings(), base::ThreadTaskRunnerHandle::Get().get(),
-      synchronous_composite, disable_display_vsync);
+      synchronous_composite, disable_display_vsync, refresh_rate);
   compositor_frame_sink->SetClient(&test_client_);
 
   CreateHostImpl(DefaultSettings(), std::move(compositor_frame_sink));
diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc
index 6525a04..c18633e 100644
--- a/cc/trees/layer_tree_host_perftest.cc
+++ b/cc/trees/layer_tree_host_perftest.cc
@@ -48,6 +48,7 @@
 
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     constexpr bool disable_display_vsync = true;
@@ -57,7 +58,8 @@
     return base::MakeUnique<TestCompositorFrameSink>(
         compositor_context_provider, std::move(worker_context_provider),
         shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings,
-        ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync);
+        ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync,
+        refresh_rate);
   }
 
   void BeginTest() override {
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc
index 656d292..f8367bfb 100644
--- a/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -9,6 +9,7 @@
 #include "cc/paint/paint_image.h"
 #include "cc/test/layer_tree_pixel_resource_test.h"
 #include "cc/test/pixel_comparator.h"
+#include "cc/test/test_compositor_frame_sink.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
@@ -67,13 +68,21 @@
     pixel_comparator_.reset(new FuzzyPixelOffByOneComparator(true));
   }
 
-  void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->renderer_settings.force_antialiasing = force_antialiasing_;
-    settings->renderer_settings.force_blending_with_shaders =
+ protected:
+  std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
+      const RendererSettings& renderer_settings,
+      double refresh_rate,
+      scoped_refptr<ContextProvider> compositor_context_provider,
+      scoped_refptr<ContextProvider> worker_context_provider) override {
+    RendererSettings modified_renderer_settings = renderer_settings;
+    modified_renderer_settings.force_antialiasing = force_antialiasing_;
+    modified_renderer_settings.force_blending_with_shaders =
         force_blending_with_shaders_;
+    return LayerTreeHostPixelResourceTest::CreateCompositorFrameSink(
+        modified_renderer_settings, refresh_rate, compositor_context_provider,
+        worker_context_provider);
   }
 
- protected:
   void RunBlendingWithRootPixelTestType(PixelResourceTestCase type) {
     const int kLaneWidth = 2;
     const int kLaneHeight = kLaneWidth;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index c740cfe..4c1aace 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -443,6 +443,7 @@
  public:
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     // Create the main ContextProvider with a MockContextSupport.
@@ -466,7 +467,7 @@
                 SetAggressivelyFreeResources(false));
 
     return LayerTreeHostTest::CreateCompositorFrameSink(
-        renderer_settings, std::move(test_main_context_provider),
+        renderer_settings, refresh_rate, std::move(test_main_context_provider),
         std::move(test_worker_context_provider));
   }
 
@@ -3313,6 +3314,7 @@
       const RendererSettings& renderer_settings,
       base::SingleThreadTaskRunner* task_runner,
       bool synchronous_composite,
+      double refresh_rate,
       base::Closure invalidate_callback)
       : TestCompositorFrameSink(std::move(compositor_context_provider),
                                 std::move(worker_context_provider),
@@ -3321,7 +3323,8 @@
                                 renderer_settings,
                                 task_runner,
                                 synchronous_composite,
-                                false /* disable_display_vsync */),
+                                false /* disable_display_vsync */,
+                                refresh_rate),
         invalidate_callback_(std::move(invalidate_callback)) {}
 
   // TestCompositorFrameSink overrides.
@@ -3347,6 +3350,7 @@
 
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     auto on_draw_callback = base::Bind(
@@ -3356,7 +3360,7 @@
     auto frame_sink = base::MakeUnique<OnDrawCompositorFrameSink>(
         compositor_context_provider, std::move(worker_context_provider),
         shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings,
-        ImplThreadTaskRunner(), false /* synchronous_composite */,
+        ImplThreadTaskRunner(), false /* synchronous_composite */, refresh_rate,
         std::move(on_draw_callback));
     compositor_frame_sink_ = frame_sink.get();
     return std::move(frame_sink);
@@ -5477,13 +5481,14 @@
  protected:
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     auto context = TestWebGraphicsContext3D::Create();
     context->set_gpu_rasterization(true);
     auto context_provider = TestContextProvider::Create(std::move(context));
     return LayerTreeHostTest::CreateCompositorFrameSink(
-        renderer_settings, std::move(context_provider),
+        renderer_settings, refresh_rate, std::move(context_provider),
         std::move(worker_context_provider));
   }
 };
@@ -5561,6 +5566,7 @@
 
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     std::unique_ptr<TestWebGraphicsContext3D> context =
@@ -5569,9 +5575,9 @@
     context->set_gpu_rasterization(true);
     compositor_context_provider =
         TestContextProvider::Create(std::move(context));
-    return LayerTreeTest::CreateCompositorFrameSink(renderer_settings,
-                                                    compositor_context_provider,
-                                                    worker_context_provider);
+    return LayerTreeTest::CreateCompositorFrameSink(
+        renderer_settings, refresh_rate, compositor_context_provider,
+        worker_context_provider);
   }
 
   void SetupTree() override {
@@ -5976,6 +5982,7 @@
 
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     constexpr bool disable_display_vsync = false;
@@ -5985,7 +5992,8 @@
     return base::MakeUnique<TestCompositorFrameSink>(
         compositor_context_provider, std::move(worker_context_provider),
         shared_bitmap_manager(), gpu_memory_buffer_manager(), renderer_settings,
-        ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync);
+        ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync,
+        refresh_rate);
   }
 
   void BeginTest() override {
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 557d88e..ac83a150 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -79,6 +79,7 @@
 
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     base::AutoLock lock(context3d_lock_);
@@ -99,7 +100,7 @@
     }
 
     return LayerTreeTest::CreateCompositorFrameSink(
-        renderer_settings,
+        renderer_settings, refresh_rate,
         TestContextProvider::Create(std::move(compositor_context3d)),
         std::move(worker_context_provider));
   }
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc
index c4c48ed..e468e60 100644
--- a/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -466,10 +466,11 @@
 
   std::unique_ptr<TestCompositorFrameSink> CreateCompositorFrameSink(
       const RendererSettings& renderer_settings,
+      double refresh_rate,
       scoped_refptr<ContextProvider> compositor_context_provider,
       scoped_refptr<ContextProvider> worker_context_provider) override {
     auto frame_sink = LayerTreeHostCopyRequestTest::CreateCompositorFrameSink(
-        renderer_settings, std::move(compositor_context_provider),
+        renderer_settings, refresh_rate, std::move(compositor_context_provider),
         std::move(worker_context_provider));
     frame_sink_ = frame_sink.get();
     return frame_sink;
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 0a5a564..902d64b 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -32,7 +32,6 @@
   SchedulerSettings ToSchedulerSettings() const;
   TileManagerSettings ToTileManagerSettings() const;
 
-  RendererSettings renderer_settings;
   ResourceSettings resource_settings;
   bool single_thread_proxy_scheduler = true;
   bool main_frame_before_activation_enabled = false;
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index e0fdc42..1c6cceb 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1586,7 +1586,6 @@
     "//components/rappor:rappor_recorder",
     "//components/renderer_context_menu",
     "//components/resources",
-    "//components/safe_browsing_db",
     "//components/safe_json",
     "//components/search",
     "//components/search_engines",
@@ -2271,8 +2270,6 @@
       "safe_browsing/test_safe_browsing_service.h",
       "safe_browsing/ui_manager.cc",
       "safe_browsing/ui_manager.h",
-      "safe_browsing/v4_test_utils.cc",
-      "safe_browsing/v4_test_utils.h",
     ]
     deps += [
       "//chrome/browser/safe_browsing:chunk_proto",
@@ -2400,7 +2397,10 @@
         "safe_browsing/signature_evaluator_mac.mm",
         "safe_browsing/two_phase_uploader.cc",
         "safe_browsing/two_phase_uploader.h",
+        "safe_browsing/v4_test_utils.cc",
+        "safe_browsing/v4_test_utils.h",
       ]
+      deps += [ "//components/safe_browsing_db:safe_browsing_db" ]
       if (is_win) {
         deps += [ "//chrome/browser/safe_browsing/incident_reporting:state_store_data_proto" ]
       }
@@ -3278,7 +3278,6 @@
       "//components/payments/content/android",
       "//components/precache/content",
       "//components/resources:components_resources",
-      "//components/safe_browsing_db",
       "//components/toolbar",
       "//components/web_contents_delegate_android",
       "//rlz:rlz_utils",
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc
index 79d581b..43845ba 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -460,11 +460,17 @@
 void DecodeGenericPolicies(
     const em::ChromeDeviceSettingsProto& policy,
     PrefValueMap* new_values_cache) {
-  if (policy.has_metrics_enabled()) {
+  if (policy.has_metrics_enabled() &&
+      policy.metrics_enabled().has_metrics_enabled()) {
     new_values_cache->SetBoolean(kStatsReportingPref,
                                  policy.metrics_enabled().metrics_enabled());
   } else {
-    new_values_cache->SetBoolean(kStatsReportingPref, false);
+    // If the policy is missing, default to reporting enabled on enterprise-
+    // enrolled devices, c.f. crbug/456186.
+    policy::BrowserPolicyConnectorChromeOS* connector =
+        g_browser_process->platform_part()->browser_policy_connector_chromeos();
+    bool is_enterprise_managed = connector->IsEnterpriseManaged();
+    new_values_cache->SetBoolean(kStatsReportingPref, is_enterprise_managed);
   }
 
   if (!policy.has_release_channel() ||
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
index cf507846..9cf5aacf 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
+#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -115,12 +116,20 @@
     Mock::VerifyAndClearExpectations(this);
   }
 
+  enum MetricsOption { DISABLE_METRICS, ENABLE_METRICS, REMOVE_METRICS_POLICY };
+
   // Helper routine to enable/disable metrics report upload settings in policy.
-  void SetMetricsReportingSettings(bool enable_metrics_reporting) {
+  void SetMetricsReportingSettings(MetricsOption option) {
     EXPECT_CALL(*this, SettingChanged(_)).Times(AtLeast(1));
-    em::MetricsEnabledProto* proto =
-        device_policy_.payload().mutable_metrics_enabled();
-    proto->set_metrics_enabled(enable_metrics_reporting);
+    if (option == REMOVE_METRICS_POLICY) {
+      // Remove policy altogether
+      device_policy_.payload().clear_metrics_enabled();
+    } else {
+      // Enable or disable policy
+      em::MetricsEnabledProto* proto =
+          device_policy_.payload().mutable_metrics_enabled();
+      proto->set_metrics_enabled(option == ENABLE_METRICS);
+    }
     device_policy_.Build();
     device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob());
     ReloadDeviceSettings();
@@ -207,6 +216,18 @@
   DISALLOW_COPY_AND_ASSIGN(DeviceSettingsProviderTest);
 };
 
+// Same as above, but enrolled into an enterprise
+class DeviceSettingsProviderTestEnterprise : public DeviceSettingsProviderTest {
+ protected:
+  DeviceSettingsProviderTestEnterprise()
+      : install_attributes_(ScopedStubInstallAttributes::CreateCloudManaged(
+            policy::PolicyBuilder::kFakeDomain,
+            policy::PolicyBuilder::kFakeDeviceId)) {}
+
+ private:
+  ScopedStubInstallAttributes install_attributes_;
+};
+
 TEST_F(DeviceSettingsProviderTest, InitializationTest) {
   // Have the service load a settings blob.
   EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
@@ -257,8 +278,30 @@
   ASSERT_EQ("stable-channel", string_value);
 }
 
+TEST_F(DeviceSettingsProviderTestEnterprise, NoPolicyDefaultsOn) {
+  // Missing policy should default to reporting enabled for enterprise-enrolled
+  // devices, see crbug/456186.
+  SetMetricsReportingSettings(REMOVE_METRICS_POLICY);
+  const base::Value* saved_value = provider_->Get(kStatsReportingPref);
+  ASSERT_TRUE(saved_value);
+  bool bool_value;
+  EXPECT_TRUE(saved_value->GetAsBoolean(&bool_value));
+  EXPECT_TRUE(bool_value);
+}
+
+TEST_F(DeviceSettingsProviderTest, NoPolicyDefaultsOff) {
+  // Missing policy should default to reporting enabled for non-enterprise-
+  // enrolled devices, see crbug/456186.
+  SetMetricsReportingSettings(REMOVE_METRICS_POLICY);
+  const base::Value* saved_value = provider_->Get(kStatsReportingPref);
+  ASSERT_TRUE(saved_value);
+  bool bool_value;
+  EXPECT_TRUE(saved_value->GetAsBoolean(&bool_value));
+  EXPECT_FALSE(bool_value);
+}
+
 TEST_F(DeviceSettingsProviderTest, SetPrefFailed) {
-  SetMetricsReportingSettings(false);
+  SetMetricsReportingSettings(DISABLE_METRICS);
 
   // If we are not the owner no sets should work.
   base::Value value(true);
@@ -489,4 +532,5 @@
   SetLogUploadSettings(false);
   VerifyLogUploadSettings(false);
 }
-} // namespace chromeos
+
+}  // namespace chromeos
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 7b7c352..085fd949 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -980,13 +980,41 @@
       BrowserContext::GetStoragePartition(
           render_frame_host()->GetProcess()->GetBrowserContext(),
           render_frame_host()->GetSiteInstance());
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("downloads_api_run_async", R"(
+        semantics {
+          sender: "Downloads API"
+          description:
+            "This request is made when an extension makes an API call to "
+            "download a file."
+          trigger:
+            "An API call from an extension, can be in response to user input "
+            "or autonomously."
+          data:
+            "The extension may provide any data that it has permission to "
+            "access, or is provided to it by the user."
+          destination: OTHER
+        }
+        policy {
+          cookies_allowed: true
+          cookies_store: "user"
+          setting:
+            "This feature cannot be disabled in settings, but disabling all "
+            "extensions will prevent it."
+          chrome_policy {
+            ExtensionInstallBlacklist {
+              ExtensionInstallBlacklist: {
+                entries: '*'
+              }
+            }
+          }
+        })");
   std::unique_ptr<content::DownloadUrlParameters> download_params(
       new content::DownloadUrlParameters(
           download_url, render_frame_host()->GetProcess()->GetID(),
           render_frame_host()->GetRenderViewHost()->GetRoutingID(),
           render_frame_host()->GetRoutingID(),
-          storage_partition->GetURLRequestContext(),
-          NO_TRAFFIC_ANNOTATION_YET));
+          storage_partition->GetURLRequestContext(), traffic_annotation));
 
   base::FilePath creator_suggested_filename;
   if (options.filename.get()) {
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index d9535400..9f653a7 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -668,10 +668,40 @@
   content::StoragePartition* storage_partition =
       BrowserContext::GetStoragePartition(profile_,
                                           render_frame_host->GetSiteInstance());
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("webstore_installer", R"(
+        semantics {
+          sender: "Webstore Installer"
+          description: "Downloads an extension for installation."
+          trigger:
+            "User initiates a webstore extension installation flow, including "
+            "installing from the webstore, inline installation from a site, "
+            "re-installing a corrupted extension, and others."
+          data:
+            "The id of the extension to be installed and information about the "
+            "user's installation, including version, language, distribution "
+            "(Chrome vs Chromium), NaCl architecture, installation source (as "
+            "an enum), and accepted crx formats."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: true
+          cookies_store: "user"
+          setting:
+            "This feature cannot be disabled. It is only activated if the user "
+            "triggers an extension installation."
+          chrome_policy {
+            ExtensionInstallBlacklist {
+              ExtensionInstallBlacklist: {
+                entries: '*'
+              }
+            }
+          }
+        })");
   std::unique_ptr<DownloadUrlParameters> params(new DownloadUrlParameters(
       download_url_, render_process_host_id, render_view_host_routing_id,
       render_frame_host->GetRoutingID(),
-      storage_partition->GetURLRequestContext(), NO_TRAFFIC_ANNOTATION_YET));
+      storage_partition->GetURLRequestContext(), traffic_annotation));
   params->set_file_path(file);
   if (controller.GetVisibleEntry())
     params->set_referrer(content::Referrer::SanitizeForRequest(
diff --git a/chrome/browser/predictors/loading_data_collector.h b/chrome/browser/predictors/loading_data_collector.h
index 65274eef..cb5c321 100644
--- a/chrome/browser/predictors/loading_data_collector.h
+++ b/chrome/browser/predictors/loading_data_collector.h
@@ -16,14 +16,13 @@
 
 namespace predictors {
 
-// Records navigation events as reported by various observers to the database
-// and stats collection classes. All the non-static methods of this class need
+// Records to the database and stats collection classes navigation events as
+// reported by various observers. All the non-static methods of this class need
 // to be called on the UI thread.
 class LoadingDataCollector
     : public base::SupportsWeakPtr<LoadingDataCollector> {
  public:
-  explicit LoadingDataCollector(
-      predictors::ResourcePrefetchPredictor* predictor);
+  explicit LoadingDataCollector(ResourcePrefetchPredictor* predictor);
   ~LoadingDataCollector();
 
   // Thread safe.
@@ -37,11 +36,11 @@
   // requests. Should only be called if the corresponding Should* functions
   // return true.
   void RecordURLRequest(
-      const predictors::ResourcePrefetchPredictor::URLRequestSummary& request);
+      const ResourcePrefetchPredictor::URLRequestSummary& request);
   void RecordURLResponse(
-      const predictors::ResourcePrefetchPredictor::URLRequestSummary& response);
+      const ResourcePrefetchPredictor::URLRequestSummary& response);
   void RecordURLRedirect(
-      const predictors::ResourcePrefetchPredictor::URLRequestSummary& response);
+      const ResourcePrefetchPredictor::URLRequestSummary& response);
 
   // Called when the main frame of a page completes loading.
   void RecordMainFrameLoadComplete(const NavigationID& navigation_id);
@@ -69,7 +68,7 @@
 
   static void SetAllowPortInUrlsForTesting(bool state);
 
-  predictors::ResourcePrefetchPredictor* const predictor_;
+  ResourcePrefetchPredictor* const predictor_;
 };
 
 }  // namespace predictors
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 236d02a..d152ac8 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -652,6 +652,16 @@
            static_cast<void*>(it->second), sizeof(void*));
   }
 
+  // Prevent the TreeStateTracker from getting any more notifications by
+  // severing the link between it and the CTVerifier and unregistering it from
+  // new STH notifications.
+  //
+  // Only do this if the |cert_transparency_verifier_| is not null.
+  if (cert_transparency_verifier_) {
+    cert_transparency_verifier_->SetObserver(nullptr);
+    ct_tree_tracker_unregistration_.Run();
+  }
+
   // Destroy certificate_report_sender_ before main_request_context_,
   // since the former has a reference to the latter.
   if (transport_security_state_)
@@ -1291,16 +1301,6 @@
 
 void ProfileIOData::DestroyResourceContext() {
   resource_context_.reset();
-  // Prevent the cert_transparency_observer_ from getting any more
-  // notifications by severing the link between it and the
-  // cert_transparency_verifier_ and unregistering it from new STH
-  // notifications.
-  // Only do this if the profile was initalized and
-  // |cert_transparency_verifier_| is not null.
-  if (cert_transparency_verifier_) {
-    cert_transparency_verifier_->SetObserver(nullptr);
-    ct_tree_tracker_unregistration_.Run();
-  }
 }
 
 std::unique_ptr<net::HttpNetworkSession>
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index 63168e7a..fdb621c 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -148,7 +148,7 @@
   resource.url = phishing_url;
   resource.original_url = phishing_url;
   resource.is_subresource = false;
-  resource.threat_type = SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL;
+  resource.threat_type = SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING;
   resource.threat_source =
       safe_browsing::ThreatSource::PASSWORD_PROTECTION_SERVICE;
   resource.web_contents_getter =
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
index e7670c2..a30d126 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -393,7 +393,7 @@
   EXPECT_EQ(GURL(kPhishingURL), resource.url);
   EXPECT_EQ(GURL(kPhishingURL), resource.original_url);
   EXPECT_FALSE(resource.is_subresource);
-  EXPECT_EQ(SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL,
+  EXPECT_EQ(SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING,
             resource.threat_type);
   EXPECT_EQ(ThreatSource::PASSWORD_PROTECTION_SERVICE, resource.threat_source);
   EXPECT_EQ(web_contents(), resource.web_contents_getter.Run());
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index fd293fd1..b5ba16f 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -566,7 +566,7 @@
       resource.url = phishing_url;
       resource.original_url = phishing_url;
       resource.is_subresource = false;
-      resource.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL;
+      resource.threat_type = SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING;
       resource.threat_source =
           safe_browsing::ThreatSource::CLIENT_SIDE_DETECTION;
       resource.web_contents_getter = safe_browsing::SafeBrowsingUIManager::
@@ -602,7 +602,7 @@
       resource.url = malware_url;
       resource.original_url = original_url;
       resource.is_subresource = (malware_url.host() != original_url.host());
-      resource.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL;
+      resource.threat_type = SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE;
       resource.threat_source =
           safe_browsing::ThreatSource::CLIENT_SIDE_DETECTION;
       resource.web_contents_getter = safe_browsing::SafeBrowsingUIManager::
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index 41054f5..e2772e6 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -561,7 +561,7 @@
   EXPECT_EQ(phishing_url, resource.url);
   EXPECT_EQ(phishing_url, resource.original_url);
   EXPECT_FALSE(resource.is_subresource);
-  EXPECT_EQ(SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL, resource.threat_type);
+  EXPECT_EQ(SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING, resource.threat_type);
   EXPECT_EQ(ThreatSource::CLIENT_SIDE_DETECTION, resource.threat_source);
   EXPECT_EQ(web_contents(), resource.web_contents_getter.Run());
 
@@ -647,7 +647,7 @@
   EXPECT_EQ(other_phishing_url, resource.url);
   EXPECT_EQ(other_phishing_url, resource.original_url);
   EXPECT_FALSE(resource.is_subresource);
-  EXPECT_EQ(SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL, resource.threat_type);
+  EXPECT_EQ(SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING, resource.threat_type);
   EXPECT_EQ(ThreatSource::CLIENT_SIDE_DETECTION, resource.threat_source);
   EXPECT_EQ(web_contents(), resource.web_contents_getter.Run());
 
@@ -860,7 +860,7 @@
   EXPECT_EQ(malware_ip_url, resource.url);
   EXPECT_EQ(malware_landing_url, resource.original_url);
   EXPECT_TRUE(resource.is_subresource);
-  EXPECT_EQ(SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL, resource.threat_type);
+  EXPECT_EQ(SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE, resource.threat_type);
   EXPECT_EQ(ThreatSource::CLIENT_SIDE_DETECTION, resource.threat_source);
   EXPECT_EQ(web_contents(), resource.web_contents_getter.Run());
 
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index 43d631d..aad28a88 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -222,7 +222,7 @@
   }
 
   bool IsDangerous(SBThreatType threat_type) const {
-    return threat_type == SB_THREAT_TYPE_BINARY_MALWARE_URL;
+    return threat_type == SB_THREAT_TYPE_URL_BINARY_MALWARE;
   }
 
   // Implements SafeBrowsingDatabaseManager::Client.
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
index e8d6a59..eee25760 100644
--- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -233,7 +233,7 @@
   LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck* check =
       new LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck(
           arg0, std::vector<SBFullHash>(), arg1, BINURL,
-          std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL));
+          std::vector<SBThreatType>(1, SB_THREAT_TYPE_URL_BINARY_MALWARE));
   for (size_t i = 0; i < check->url_results.size(); ++i)
     check->url_results[i] = threat_type;
   BrowserThread::PostTask(
@@ -1797,7 +1797,7 @@
   {
     EXPECT_CALL(*sb_service_->mock_database_manager(),
                 CheckDownloadUrl(ContainerEq(url_chain), NotNull()))
-        .WillOnce(DoAll(CheckDownloadUrlDone(SB_THREAT_TYPE_BINARY_MALWARE_URL),
+        .WillOnce(DoAll(CheckDownloadUrlDone(SB_THREAT_TYPE_URL_BINARY_MALWARE),
                         Return(false)));
     RunLoop run_loop;
     download_service_->CheckDownloadUrl(
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc
index f4a80af..f831b73 100644
--- a/chrome/browser/safe_browsing/local_database_manager.cc
+++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -166,7 +166,7 @@
     case UNWANTEDURL:
       return SB_THREAT_TYPE_URL_UNWANTED;
     case BINURL:
-      return SB_THREAT_TYPE_BINARY_MALWARE_URL;
+      return SB_THREAT_TYPE_URL_BINARY_MALWARE;
     case EXTENSIONBLACKLIST:
       return SB_THREAT_TYPE_EXTENSION;
     case RESOURCEBLACKLIST:
@@ -352,7 +352,7 @@
   std::unique_ptr<SafeBrowsingCheck> check =
       base::MakeUnique<SafeBrowsingCheck>(
           url_chain, std::vector<SBFullHash>(), client, BINURL,
-          std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL));
+          std::vector<SBThreatType>(1, SB_THREAT_TYPE_URL_BINARY_MALWARE));
   std::vector<SBPrefix> prefixes;
   SafeBrowsingDatabase::GetDownloadUrlPrefixes(url_chain, &prefixes);
   StartSafeBrowsingCheck(
diff --git a/chrome/browser/safe_browsing/local_database_manager_unittest.cc b/chrome/browser/safe_browsing/local_database_manager_unittest.cc
index ee13eba7..4f3d93a4 100644
--- a/chrome/browser/safe_browsing/local_database_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/local_database_manager_unittest.cc
@@ -103,7 +103,7 @@
 
 TEST_F(LocalDatabaseManagerTest, CheckCorrespondsListTypeForHash) {
   std::vector<SBThreatType> malware_threat(1,
-                                           SB_THREAT_TYPE_BINARY_MALWARE_URL);
+                                           SB_THREAT_TYPE_URL_BINARY_MALWARE);
   EXPECT_FALSE(RunSBHashTest(BINURL, malware_threat, {kMalwareList}));
   EXPECT_TRUE(RunSBHashTest(BINURL, malware_threat, {kBinUrlList}));
 
@@ -130,7 +130,7 @@
       {{host2, kBinUrlList}};
 
   std::vector<SBThreatType> malware_threat =
-      {SB_THREAT_TYPE_BINARY_MALWARE_URL};
+      {SB_THREAT_TYPE_URL_BINARY_MALWARE};
   EXPECT_FALSE(RunUrlTest(url, BINURL, malware_threat, malware_list_result));
   EXPECT_TRUE(RunUrlTest(url, BINURL, malware_threat, binurl_list_result));
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index c7dfe22..21443d4 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -141,9 +141,9 @@
   return threat_type == SB_THREAT_TYPE_URL_PHISHING ||
          threat_type == SB_THREAT_TYPE_URL_MALWARE ||
          threat_type == SB_THREAT_TYPE_URL_UNWANTED ||
-         threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL ||
-         threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL ||
-         threat_type == SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL;
+         threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING ||
+         threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE ||
+         threat_type == SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING;
 }
 
 SafeBrowsingBlockingPage::~SafeBrowsingBlockingPage() {
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 4c9f799..ed2c88a 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -1220,7 +1220,7 @@
   client->CheckDownloadUrl(badbin_urls);
 
   // Now, the badbin_url is not safe since it is added to download database.
-  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
+  EXPECT_EQ(SB_THREAT_TYPE_URL_BINARY_MALWARE, client->GetThreatType());
 }
 
 IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckUnwantedSoftwareUrl) {
@@ -1326,7 +1326,7 @@
   client->CheckDownloadUrl(badbin_urls);
 
   // Now, the badbin_url is not safe since it is added to download database.
-  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
+  EXPECT_EQ(SB_THREAT_TYPE_URL_BINARY_MALWARE, client->GetThreatType());
 }
 
 IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckResourceUrl) {
@@ -1386,7 +1386,7 @@
   client->CheckDownloadUrl(badbin_urls);
 
   // badbin_url is not safe since it is added to download database.
-  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
+  EXPECT_EQ(SB_THREAT_TYPE_URL_BINARY_MALWARE, client->GetThreatType());
 
   //
   // Now introducing delays and we should hit timeout.
@@ -2113,7 +2113,7 @@
   client->CheckDownloadUrl(badbin_urls);
 
   // Now, the badbin_url is not safe since it is added to download database.
-  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
+  EXPECT_EQ(SB_THREAT_TYPE_URL_BINARY_MALWARE, client->GetThreatType());
 }
 #endif  // defined(GOOGLE_CHROME_BUILD)
 
@@ -2213,7 +2213,7 @@
   client->CheckDownloadUrl(badbin_urls);
 
   // Now, the badbin_url is not safe since it is added to download database.
-  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
+  EXPECT_EQ(SB_THREAT_TYPE_URL_BINARY_MALWARE, client->GetThreatType());
 }
 #endif  // defined(GOOGLE_CHROME_BUILD)
 
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc
index 2ed74e7..1be5e57a 100644
--- a/chrome/browser/safe_browsing/threat_details_unittest.cc
+++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
@@ -1081,7 +1081,7 @@
       ->NavigateAndCommit(GURL(kLandingURL));
 
   UnsafeResource resource;
-  InitResource(&resource, SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL,
+  InitResource(&resource, SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING,
                true /* is_subresource */, GURL(kThreatURL));
 
   scoped_refptr<ThreatDetailsWrap> report =
@@ -1107,7 +1107,7 @@
   actual.ParseFromString(serialized);
 
   ClientSafeBrowsingReportRequest expected;
-  expected.set_type(ClientSafeBrowsingReportRequest::CLIENT_SIDE_PHISHING_URL);
+  expected.set_type(ClientSafeBrowsingReportRequest::URL_CLIENT_SIDE_PHISHING);
   expected.set_url(kThreatURL);
   expected.set_page_url(kLandingURL);
   expected.set_referrer_url("");
@@ -1164,7 +1164,7 @@
       ->NavigateAndCommit(GURL(kLandingURL));
 
   UnsafeResource resource;
-  InitResource(&resource, SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL,
+  InitResource(&resource, SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING,
                true /* is_subresource */, GURL(kThreatURLHttps));
 
   scoped_refptr<ThreatDetailsWrap> report =
@@ -1190,7 +1190,7 @@
   actual.ParseFromString(serialized);
 
   ClientSafeBrowsingReportRequest expected;
-  expected.set_type(ClientSafeBrowsingReportRequest::CLIENT_SIDE_PHISHING_URL);
+  expected.set_type(ClientSafeBrowsingReportRequest::URL_CLIENT_SIDE_PHISHING);
   expected.set_url(kThreatURLHttps);
   expected.set_page_url(kLandingURL);
   expected.set_referrer_url("");
@@ -1244,7 +1244,7 @@
       ->NavigateAndCommit(GURL(kLandingURL));
 
   UnsafeResource resource;
-  InitResource(&resource, SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL,
+  InitResource(&resource, SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE,
                true /* is_subresource */, GURL(kThreatURL));
 
   scoped_refptr<ThreatDetailsWrap> report =
@@ -1267,7 +1267,7 @@
   actual.ParseFromString(serialized);
 
   ClientSafeBrowsingReportRequest expected;
-  expected.set_type(ClientSafeBrowsingReportRequest::CLIENT_SIDE_MALWARE_URL);
+  expected.set_type(ClientSafeBrowsingReportRequest::URL_CLIENT_SIDE_MALWARE);
   expected.set_url(kThreatURL);
   expected.set_page_url(kLandingURL);
   expected.set_referrer_url("");
diff --git a/chrome/browser/sessions/better_session_restore_browsertest.cc b/chrome/browser/sessions/better_session_restore_browsertest.cc
index 4619174..b44c1cd 100644
--- a/chrome/browser/sessions/better_session_restore_browsertest.cc
+++ b/chrome/browser/sessions/better_session_restore_browsertest.cc
@@ -741,7 +741,14 @@
       ->SetDefaultCookieSetting(CONTENT_SETTING_SESSION_ONLY);
 }
 
-IN_PROC_BROWSER_TEST_F(NoSessionRestoreTest, LocalStorageClearedOnExit) {
+// Crashes on Windows. http://crbug.com/732013
+#if defined(OS_WIN)
+#define MAYBE_NSRT_LocalStorageClearedOnExit DISABLED_LocalStorageClearedOnExit
+#else
+#define MAYBE_NSRT_LocalStorageClearedOnExit LocalStorageClearedOnExit
+#endif
+IN_PROC_BROWSER_TEST_F(NoSessionRestoreTest,
+                       MAYBE_NSRT_LocalStorageClearedOnExit) {
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   EXPECT_EQ(std::string(url::kAboutBlankURL), web_contents->GetURL().spec());
diff --git a/chrome/browser/ssl/security_state_tab_helper.cc b/chrome/browser/ssl/security_state_tab_helper.cc
index 590c3fd..4313182 100644
--- a/chrome/browser/ssl/security_state_tab_helper.cc
+++ b/chrome/browser/ssl/security_state_tab_helper.cc
@@ -164,18 +164,18 @@
       case safe_browsing::SB_THREAT_TYPE_SAFE:
         break;
       case safe_browsing::SB_THREAT_TYPE_URL_PHISHING:
-      case safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL:
-      case safe_browsing::SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL:
+      case safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING:
+      case safe_browsing::SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING:
         return security_state::MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING;
         break;
       case safe_browsing::SB_THREAT_TYPE_URL_MALWARE:
-      case safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL:
+      case safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE:
         return security_state::MALICIOUS_CONTENT_STATUS_MALWARE;
         break;
       case safe_browsing::SB_THREAT_TYPE_URL_UNWANTED:
         return security_state::MALICIOUS_CONTENT_STATUS_UNWANTED_SOFTWARE;
         break;
-      case safe_browsing::SB_THREAT_TYPE_BINARY_MALWARE_URL:
+      case safe_browsing::SB_THREAT_TYPE_URL_BINARY_MALWARE:
       case safe_browsing::SB_THREAT_TYPE_EXTENSION:
       case safe_browsing::SB_THREAT_TYPE_BLACKLISTED_RESOURCE:
       case safe_browsing::SB_THREAT_TYPE_API_ABUSE:
diff --git a/chrome/browser/ui/omnibox/OWNERS b/chrome/browser/ui/omnibox/OWNERS
index 48c43f2..8a44467 100644
--- a/chrome/browser/ui/omnibox/OWNERS
+++ b/chrome/browser/ui/omnibox/OWNERS
@@ -1,3 +1,4 @@
+jdonnelly@chromium.org
 pkasting@chromium.org
 sky@chromium.org
 
diff --git a/chrome/browser/ui/views/omnibox/OWNERS b/chrome/browser/ui/views/omnibox/OWNERS
index fc03347..392e67cf 100644
--- a/chrome/browser/ui/views/omnibox/OWNERS
+++ b/chrome/browser/ui/views/omnibox/OWNERS
@@ -1,3 +1,4 @@
+jdonnelly@chromium.org
 pkasting@chromium.org
 
 # COMPONENT: UI>Browser>Omnibox
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 6841d01..451a461 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -240,9 +240,9 @@
     } else if (type_param == "phishing") {
       threat_type = safe_browsing::SB_THREAT_TYPE_URL_PHISHING;
     } else if (type_param == "clientside_malware") {
-      threat_type = safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL;
+      threat_type = safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE;
     } else if (type_param == "clientside_phishing") {
-      threat_type = safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL;
+      threat_type = safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING;
     }
   }
   safe_browsing::SafeBrowsingBlockingPage::UnsafeResource resource;
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java
index 7f0ea2a5..d65f865 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java
@@ -55,6 +55,8 @@
     private int mSeparatorPosition;
     private Animator mAnimator;
     private Runnable mReverseAnimationRunnable;
+    // Boolean to track if the keyboard accessory has just popped up or has already been showing.
+    private boolean mFirstAppearance;
 
     /**
      * Creates an AutofillKeyboardAccessory with specified parameters.
@@ -84,6 +86,7 @@
         mAnimationDurationMillis = animationDurationMillis;
         mStartAnimationTranslationPx = getResources().getDimensionPixelSize(
                 R.dimen.keyboard_accessory_start_animation_translation);
+        mFirstAppearance = true;
     }
 
     /**
@@ -192,7 +195,7 @@
             container.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         }
 
-        if (mAnimationDurationMillis > 0) {
+        if (mAnimationDurationMillis > 0 && mFirstAppearance) {
             cancelAnimations(container);
             mAnimator = ObjectAnimator.ofFloat(
                     this, View.TRANSLATION_X, -mStartAnimationTranslationPx, 0);
@@ -205,6 +208,7 @@
                         // finished the reverse animation and removed the first suggestion. This
                         // prevents a sudden movement of these suggestions when the container view
                         // is redrawn. See |scheduleReverseAnimation|.
+                        // TODO(jsaul): Doesn't work properly; investigate animate+hint variation.
                         for (int i = mSeparatorPosition + 1; i < getChildCount(); ++i) {
                             getChildAt(i).setAlpha(0);
                         }
@@ -223,14 +227,17 @@
         container.post(new Runnable() {
             @Override
             public void run() {
-                if (mAnimationDurationMillis > 0) {
+                if (mAnimationDurationMillis > 0 && mFirstAppearance) {
                     mAnimator.start();
                 } else {
                     container.scrollTo(isRtl ? getRight() : 0, 0);
                 }
+                mFirstAppearance = false;
             }
         });
-        announceForAccessibility(container.getContentDescription());
+        if (mFirstAppearance) {
+            announceForAccessibility(container.getContentDescription());
+        }
     }
 
     /**
@@ -242,6 +249,8 @@
         container.setVisibility(View.GONE);
         mWindowAndroid.removeKeyboardVisibilityListener(this);
         ((View) container.getParent()).requestLayout();
+        // Next time the keyboard accessory appears, do animations/accessibility work if applicable.
+        mFirstAppearance = true;
     }
 
     @Override
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 9e81bc0..15e9b94 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -1008,7 +1008,7 @@
 
   if (base::FeatureList::IsEnabled(
           features::kDataReductionProxyDecidesTransform)) {
-    return ShouldAcceptServerLoFi(request, previews_decider);
+    return ShouldAcceptServerPreview(request, previews_decider);
   }
 
   bool enable_lofi = ShouldEnableLoFiInternal(request, previews_decider);
@@ -1032,7 +1032,7 @@
 
   if (base::FeatureList::IsEnabled(
           features::kDataReductionProxyDecidesTransform)) {
-    return ShouldAcceptLitePages(request, previews_decider);
+    return ShouldAcceptServerPreview(request, previews_decider);
   }
 
   return ShouldEnableLitePagesInternal(request, previews_decider);
@@ -1063,67 +1063,30 @@
   }
 }
 
-bool DataReductionProxyConfig::ShouldAcceptServerLoFi(
+bool DataReductionProxyConfig::ShouldAcceptServerPreview(
     const net::URLRequest& request,
     const previews::PreviewsDecider& previews_decider) const {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(base::FeatureList::IsEnabled(
       features::kDataReductionProxyDecidesTransform));
 
-  if (IsBlackListedOrDisabled(request, previews_decider,
-                              previews::PreviewsType::LOFI)) {
+  // For the transition to server-driven previews decisions, we will
+  // use existing Lo-Fi flags for disabling and cellular-only mode.
+  // TODO(dougarnett): Refactor flag names as part of bug 725645.
+  if (params::IsLoFiDisabledViaFlags()) {
     return false;
   }
 
-  if (params::IsLoFiAlwaysOnViaFlags()) {
-    return true;
-  }
-
-  if (params::IsLoFiCellularOnlyViaFlags()) {
-    return net::NetworkChangeNotifier::IsConnectionCellular(connection_type_);
-  }
-
-  if (params::IsLoFiSlowConnectionsOnlyViaFlags() ||
-      params::IsIncludedInLoFiEnabledFieldTrial()) {
-    // Accept Lo-Fi from the data reduction proxy (it will handle the effective
-    // connection type check).
-    return true;
-  }
-
-  return false;
-}
-
-bool DataReductionProxyConfig::ShouldAcceptLitePages(
-    const net::URLRequest& request,
-    const previews::PreviewsDecider& previews_decider) const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(base::FeatureList::IsEnabled(
-      features::kDataReductionProxyDecidesTransform));
-
   if (IsBlackListedOrDisabled(request, previews_decider,
                               previews::PreviewsType::LITE_PAGE)) {
     return false;
   }
 
-  if (params::IsLoFiAlwaysOnViaFlags() &&
-      params::AreLitePagesEnabledViaFlags()) {
-    return true;
-  }
-
-  if (params::IsLoFiCellularOnlyViaFlags() &&
-      params::AreLitePagesEnabledViaFlags()) {
+  if (params::IsLoFiCellularOnlyViaFlags()) {
     return net::NetworkChangeNotifier::IsConnectionCellular(connection_type_);
   }
 
-  if ((params::IsLoFiSlowConnectionsOnlyViaFlags() &&
-       params::AreLitePagesEnabledViaFlags()) ||
-      params::IsIncludedInLitePageFieldTrial()) {
-    // Accept LitePages from the data reduction proxy (it will handle the
-    // effective connection type check).
-    return true;
-  }
-
-  return false;
+  return true;
 }
 
 bool DataReductionProxyConfig::ShouldEnableLoFiInternal(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
index 677c5c9..ec1889f 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -252,7 +252,8 @@
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest, WarmupURL);
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest,
                            ShouldAcceptServerLoFi);
-  FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest, ShouldAcceptLitePages);
+  FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest,
+                           ShouldAcceptServerPreview);
 
   // Values of the estimated network quality at the beginning of the most
   // recent query of the Network Quality Estimator.
@@ -306,20 +307,11 @@
       previews::PreviewsType previews_type) const;
 
   // Returns whether the client should report to the data reduction proxy that
-  // it is willing to accept the Server Lo-Fi optimization for |request|.
+  // it is willing to accept server previews for |request|.
   // |previews_decider| is used to check if |request| is locally blacklisted.
   // Should only be used if the kDataReductionProxyDecidesTransform feature is
   // enabled.
-  bool ShouldAcceptServerLoFi(
-      const net::URLRequest& request,
-      const previews::PreviewsDecider& previews_decider) const;
-
-  // Returns whether the client should report to the data reduction proxy that
-  // it is willing to accept a LitePage optimization for |request|.
-  // |previews_decider| is used to check if |request| is locally blacklisted.
-  // Should only be used if the kDataReductionProxyDecidesTransform feature is
-  // enabled.
-  bool ShouldAcceptLitePages(
+  bool ShouldAcceptServerPreview(
       const net::URLRequest& request,
       const previews::PreviewsDecider& previews_decider) const;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index 76a9679..3d9e073 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -1539,7 +1539,7 @@
       config()->ShouldEnableLitePages(*request.get(), *previews_decider.get()));
 }
 
-TEST_F(DataReductionProxyConfigTest, ShouldAcceptServerLoFi) {
+TEST_F(DataReductionProxyConfigTest, ShouldAcceptServerPreview) {
   // Turn on proxy-decides-transform feature to satisfy DCHECK.
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
@@ -1554,35 +1554,25 @@
   std::unique_ptr<TestPreviewsDecider> previews_decider =
       base::MakeUnique<TestPreviewsDecider>(false);
 
-  // Verify false for no flags.
-  EXPECT_FALSE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                                *previews_decider.get()));
+  // Verify true for no flags.
+  EXPECT_TRUE(config()->ShouldAcceptServerPreview(*request.get(),
+                                                  *previews_decider.get()));
 
-  // Verify true for Always-On flag.
+  // Verify false for kill switch.
   base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kDataReductionProxyLoFi,
-      switches::kDataReductionProxyLoFiValueAlwaysOn);
-  EXPECT_TRUE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                               *previews_decider.get()));
-
-  // Verify true for Always-On with LitePages enabled too.
-  base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kDataReductionProxyLoFi,
-      switches::kDataReductionProxyLoFiValueAlwaysOn);
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableDataReductionProxyLitePage);
-  EXPECT_TRUE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                               *previews_decider.get()));
+      switches::kDataReductionProxyLoFiValueDisabled);
+  EXPECT_FALSE(config()->ShouldAcceptServerPreview(*request.get(),
+                                                   *previews_decider.get()));
 
   // Verify true for Slow Connection flag.
   base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kDataReductionProxyLoFi,
       switches::kDataReductionProxyLoFiValueSlowConnectionsOnly);
-  EXPECT_TRUE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                               *previews_decider.get()));
+  EXPECT_TRUE(config()->ShouldAcceptServerPreview(*request.get(),
+                                                  *previews_decider.get()));
 
   // Verify false for Cellular Only flag and WIFI connection.
   base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
@@ -1591,34 +1581,14 @@
       switches::kDataReductionProxyLoFiValueCellularOnly);
   config()->SetConnectionTypeForTesting(
       net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
-  EXPECT_FALSE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                                *previews_decider.get()));
+  EXPECT_FALSE(config()->ShouldAcceptServerPreview(*request.get(),
+                                                   *previews_decider.get()));
 
   // Verify true for Cellular Only flag and 3G connection.
   config()->SetConnectionTypeForTesting(
       net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G);
-  EXPECT_TRUE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                               *previews_decider.get()));
-
-  // Verify true for field trial.
-  {
-    base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-    base::FieldTrialList field_trial_list(nullptr);
-    base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(),
-                                           "Enabled");
-    EXPECT_TRUE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                                 *previews_decider.get()));
-  }
-
-  // Verify false for control field trial.
-  {
-    base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-    base::FieldTrialList field_trial_list(nullptr);
-    base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(),
-                                           "Control");
-    EXPECT_FALSE(config()->ShouldAcceptServerLoFi(*request.get(),
+  EXPECT_TRUE(config()->ShouldAcceptServerPreview(*request.get(),
                                                   *previews_decider.get()));
-  }
 
   // Verify PreviewsDecider check.
   {
@@ -1629,103 +1599,11 @@
     base::FieldTrialList field_trial_list(nullptr);
     base::FieldTrialList::CreateFieldTrial(
         "DataReductionProxyPreviewsBlackListTransition", "Enabled");
-    EXPECT_FALSE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                                  *previews_decider.get()));
+    EXPECT_FALSE(config()->ShouldAcceptServerPreview(*request.get(),
+                                                     *previews_decider.get()));
     previews_decider = base::MakeUnique<TestPreviewsDecider>(true);
-    EXPECT_TRUE(config()->ShouldAcceptServerLoFi(*request.get(),
-                                                 *previews_decider.get()));
-  }
-}
-
-TEST_F(DataReductionProxyConfigTest, ShouldAcceptLitePages) {
-  // Turn on proxy-decides-transform feature to satisfy DCHECK.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      features::kDataReductionProxyDecidesTransform);
-
-  net::TestURLRequestContext context_;
-  net::TestDelegate delegate_;
-  std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
-      GURL(), net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
-  request->SetLoadFlags(request->load_flags() |
-                        net::LOAD_MAIN_FRAME_DEPRECATED);
-  std::unique_ptr<TestPreviewsDecider> previews_decider =
-      base::MakeUnique<TestPreviewsDecider>(false);
-
-  // Verify false for no flags.
-  EXPECT_FALSE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-
-  // Verify true for Always-On flag and LitePage flag.
-  base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kDataReductionProxyLoFi,
-      switches::kDataReductionProxyLoFiValueAlwaysOn);
-  EXPECT_FALSE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableDataReductionProxyLitePage);
-  EXPECT_TRUE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-
-  // Verify true for Slow Connection flag and LitePage flag.
-  base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kDataReductionProxyLoFi,
-      switches::kDataReductionProxyLoFiValueSlowConnectionsOnly);
-  EXPECT_FALSE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableDataReductionProxyLitePage);
-  EXPECT_TRUE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-
-  // Verify true for Cellular Only flag and 3G connection.
-  base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kDataReductionProxyLoFi,
-      switches::kDataReductionProxyLoFiValueCellularOnly);
-  config()->SetConnectionTypeForTesting(
-      net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G);
-  EXPECT_FALSE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableDataReductionProxyLitePage);
-  EXPECT_TRUE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-
-  // Verify false for Cellular Only flag and WIFI connection.
-  config()->SetConnectionTypeForTesting(
-      net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
-  EXPECT_FALSE(
-      config()->ShouldAcceptLitePages(*request.get(), *previews_decider.get()));
-
-  // Verify true for field trial.
-  {
-    base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-    base::FieldTrialList field_trial_list(nullptr);
-    base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(),
-                                           "Enabled_Preview");
-    EXPECT_TRUE(config()->ShouldAcceptLitePages(*request.get(),
-                                                *previews_decider.get()));
-  }
-
-  // Verify PreviewsDecider check.
-  {
-    base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kDataReductionProxyLoFi,
-        switches::kDataReductionProxyLoFiValueAlwaysOn);
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kEnableDataReductionProxyLitePage);
-    base::FieldTrialList field_trial_list(nullptr);
-    base::FieldTrialList::CreateFieldTrial(
-        "DataReductionProxyPreviewsBlackListTransition", "Enabled");
-    EXPECT_FALSE(config()->ShouldAcceptLitePages(*request.get(),
-                                                 *previews_decider.get()));
-    previews_decider = base::MakeUnique<TestPreviewsDecider>(true);
-    EXPECT_TRUE(config()->ShouldAcceptLitePages(*request.get(),
-                                                *previews_decider.get()));
+    EXPECT_TRUE(config()->ShouldAcceptServerPreview(*request.get(),
+                                                    *previews_decider.get()));
   }
 }
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
index 2dc55ff..ff0f58c 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
@@ -116,7 +116,9 @@
         experiments_.push_back(experiment_tokenizer.token());
     }
   } else if (params::AreLitePagesEnabledViaFlags()) {
-    experiments_.push_back(chrome_proxy_force_lite_page_experiment());
+    experiments_.push_back(chrome_proxy_experiment_force_lite_page());
+  } else if (params::IsLoFiOnViaFlags()) {
+    experiments_.push_back(chrome_proxy_experiment_force_empty_image());
   } else {
     // If no other "exp" directive is forced by flags, add the field trial
     // value.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
index e0bbf40..eb11d63 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
@@ -360,7 +360,7 @@
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableDataReductionProxyLitePage);
   expected_experiments.clear();
-  expected_experiments.push_back(chrome_proxy_force_lite_page_experiment());
+  expected_experiments.push_back(chrome_proxy_experiment_force_lite_page());
   SetHeaderExpectations(kExpectedSession, kExpectedCredentials, std::string(),
                         kClientStr, kExpectedBuild, kExpectedPatch, kPageId,
                         expected_experiments, &expected_header);
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
index 8961f1b7..52cf1328d 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
@@ -46,7 +46,9 @@
 // The legacy Chrome-Proxy response header directive for LoFi images.
 const char kLegacyChromeProxyLoFiResponseDirective[] = "q=low";
 
-const char kChromeProxyForceLitePageExperiment[] = "force_lite_page";
+const char kChromeProxyExperimentForceLitePage[] = "force_lite_page";
+const char kChromeProxyExperimentForceEmptyImage[] =
+    "force_page_policies_empty_image";
 
 const char kIfHeavyQualifier[] = "if-heavy";
 
@@ -154,8 +156,12 @@
   return kIdentityDirective;
 }
 
-const char* chrome_proxy_force_lite_page_experiment() {
-  return kChromeProxyForceLitePageExperiment;
+const char* chrome_proxy_experiment_force_lite_page() {
+  return kChromeProxyExperimentForceLitePage;
+}
+
+const char* chrome_proxy_experiment_force_empty_image() {
+  return kChromeProxyExperimentForceEmptyImage;
 }
 
 const char* if_heavy_qualifier() {
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
index 8320207..2415143b 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
@@ -100,7 +100,11 @@
 
 // Gets the Chrome-Proxy experiment ("exp") value to force a lite page preview
 // for requests that accept lite pages.
-const char* chrome_proxy_force_lite_page_experiment();
+const char* chrome_proxy_experiment_force_lite_page();
+
+// Gets the Chrome-Proxy experiment ("exp") value to force an empty image
+// preview for requests that enable server provided previews.
+const char* chrome_proxy_experiment_force_empty_image();
 
 // Requests a transformation only if the server determines that the page is
 // otherwise heavy (i.e., the associated page load ordinarily requires the
diff --git a/components/omnibox/OWNERS b/components/omnibox/OWNERS
index 52130b8..509133c2 100644
--- a/components/omnibox/OWNERS
+++ b/components/omnibox/OWNERS
@@ -1,5 +1,6 @@
-pkasting@chromium.org
+jdonnelly@chromium.org
 mpearson@chromium.org
+pkasting@chromium.org
 
 per-file clipboard_url_provider.*=jif@chromium.org
 
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc
index 76d14a5..13d75998 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -629,7 +629,7 @@
     const CloudPolicyClient::StatusCallback& callback,
     DeviceManagementStatus status,
     int net_error,
-    const enterprise_management::DeviceManagementResponse& response) {
+    const em::DeviceManagementResponse& response) {
   bool success = true;
   status_ = status;
   if (status != DM_STATUS_SUCCESS) {
@@ -718,7 +718,7 @@
     const CloudPolicyClient::StatusCallback& callback,
     DeviceManagementStatus status,
     int net_error,
-    const enterprise_management::DeviceManagementResponse& response) {
+    const em::DeviceManagementResponse& response) {
   status_ = status;
   if (status != DM_STATUS_SUCCESS)
     NotifyClientError();
@@ -733,8 +733,8 @@
     const RemoteCommandCallback& callback,
     DeviceManagementStatus status,
     int net_error,
-    const enterprise_management::DeviceManagementResponse& response) {
-  std::vector<enterprise_management::RemoteCommand> commands;
+    const em::DeviceManagementResponse& response) {
+  std::vector<em::RemoteCommand> commands;
   if (status == DM_STATUS_SUCCESS) {
     if (response.has_remote_command_response()) {
       for (const auto& command : response.remote_command_response().commands())
@@ -753,7 +753,7 @@
     const StatusCallback& callback,
     DeviceManagementStatus status,
     int net_error,
-    const enterprise_management::DeviceManagementResponse& response) {
+    const em::DeviceManagementResponse& response) {
   status_ = status;
   if (status != DM_STATUS_SUCCESS)
     NotifyClientError();
diff --git a/components/safe_browsing/base_blocking_page.cc b/components/safe_browsing/base_blocking_page.cc
index 184a1b2..674fd63 100644
--- a/components/safe_browsing/base_blocking_page.cc
+++ b/components/safe_browsing/base_blocking_page.cc
@@ -283,14 +283,14 @@
     const BaseUIManager::UnsafeResource& resource = *iter;
     safe_browsing::SBThreatType threat_type = resource.threat_type;
     if (threat_type == SB_THREAT_TYPE_URL_MALWARE ||
-        threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL) {
+        threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE) {
       return BaseSafeBrowsingErrorUI::SB_REASON_MALWARE;
     } else if (threat_type == SB_THREAT_TYPE_URL_UNWANTED) {
       harmful = true;
     } else {
       DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING ||
-             threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL ||
-             threat_type == SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL);
+             threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING ||
+             threat_type == SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING);
     }
   }
 
diff --git a/components/safe_browsing/base_ping_manager.cc b/components/safe_browsing/base_ping_manager.cc
index d397c2a..cc89412f 100644
--- a/components/safe_browsing/base_ping_manager.cc
+++ b/components/safe_browsing/base_ping_manager.cc
@@ -199,11 +199,11 @@
   DCHECK(hit_report.threat_type == SB_THREAT_TYPE_URL_MALWARE ||
          hit_report.threat_type == SB_THREAT_TYPE_URL_PHISHING ||
          hit_report.threat_type == SB_THREAT_TYPE_URL_UNWANTED ||
-         hit_report.threat_type == SB_THREAT_TYPE_BINARY_MALWARE_URL ||
-         hit_report.threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL ||
-         hit_report.threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL ||
+         hit_report.threat_type == SB_THREAT_TYPE_URL_BINARY_MALWARE ||
+         hit_report.threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING ||
+         hit_report.threat_type == SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE ||
          hit_report.threat_type ==
-             SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL);
+             SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING);
   std::string url = ProtocolManagerHelper::ComposeUrl(
       url_prefix_, "report", client_name_, version_, std::string(),
       hit_report.extended_reporting_level);
@@ -219,16 +219,16 @@
     case SB_THREAT_TYPE_URL_UNWANTED:
       threat_list = "uwsblhit";
       break;
-    case SB_THREAT_TYPE_BINARY_MALWARE_URL:
+    case SB_THREAT_TYPE_URL_BINARY_MALWARE:
       threat_list = "binurlhit";
       break;
-    case SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL:
+    case SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING:
       threat_list = "phishcsdhit";
       break;
-    case SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL:
+    case SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE:
       threat_list = "malcsdhit";
       break;
-    case SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL:
+    case SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING:
       threat_list = "phishpphit";
       break;
     default:
diff --git a/components/safe_browsing/base_ping_manager_unittest.cc b/components/safe_browsing/base_ping_manager_unittest.cc
index 467611af..f65676e 100644
--- a/components/safe_browsing/base_ping_manager_unittest.cc
+++ b/components/safe_browsing/base_ping_manager_unittest.cc
@@ -125,7 +125,7 @@
 
   {
     HitReport hp(base_hp);
-    hp.threat_type = SB_THREAT_TYPE_BINARY_MALWARE_URL;
+    hp.threat_type = SB_THREAT_TYPE_URL_BINARY_MALWARE;
     hp.threat_source = ThreatSource::REMOTE;
     hp.extended_reporting_level = SBER_LEVEL_OFF;
     hp.is_metrics_reporting_active = true;
@@ -143,7 +143,7 @@
 
   {
     HitReport hp(base_hp);
-    hp.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL;
+    hp.threat_type = SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING;
     hp.threat_source = ThreatSource::LOCAL_PVER4;
     hp.extended_reporting_level = SBER_LEVEL_OFF;
     hp.is_metrics_reporting_active = false;
@@ -161,7 +161,7 @@
 
   {
     HitReport hp(base_hp);
-    hp.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL;
+    hp.threat_type = SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE;
     hp.threat_source = ThreatSource::LOCAL_PVER4;
     hp.extended_reporting_level = SBER_LEVEL_OFF;
     hp.is_metrics_reporting_active = false;
@@ -180,7 +180,7 @@
   // Same as above, but add population_id
   {
     HitReport hp(base_hp);
-    hp.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL;
+    hp.threat_type = SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE;
     hp.threat_source = ThreatSource::LOCAL_PVER4;
     hp.extended_reporting_level = SBER_LEVEL_OFF;
     hp.is_metrics_reporting_active = false;
@@ -270,7 +270,7 @@
   hp.malicious_url = GURL("http://malicious.url.com");
   hp.page_url = GURL("http://page.url.com");
   hp.referrer_url = GURL("http://referrer.url.com");
-  hp.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL;
+  hp.threat_type = SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE;
   hp.threat_source = ThreatSource::LOCAL_PVER4;
   hp.extended_reporting_level = SBER_LEVEL_OFF;
   hp.is_metrics_reporting_active = false;
diff --git a/components/safe_browsing/browser/threat_details.cc b/components/safe_browsing/browser/threat_details.cc
index 2dee280c2..0b7a7dc 100644
--- a/components/safe_browsing/browser/threat_details.cc
+++ b/components/safe_browsing/browser/threat_details.cc
@@ -72,12 +72,12 @@
       return ClientSafeBrowsingReportRequest::URL_MALWARE;
     case SB_THREAT_TYPE_URL_UNWANTED:
       return ClientSafeBrowsingReportRequest::URL_UNWANTED;
-    case SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL:
-      return ClientSafeBrowsingReportRequest::CLIENT_SIDE_PHISHING_URL;
-    case SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL:
-      return ClientSafeBrowsingReportRequest::CLIENT_SIDE_MALWARE_URL;
-    case SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL:
-      return ClientSafeBrowsingReportRequest::PASSWORD_PROTECTION_PHISHING_URL;
+    case SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING:
+      return ClientSafeBrowsingReportRequest::URL_CLIENT_SIDE_PHISHING;
+    case SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE:
+      return ClientSafeBrowsingReportRequest::URL_CLIENT_SIDE_MALWARE;
+    case SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING:
+      return ClientSafeBrowsingReportRequest::URL_PASSWORD_PROTECTION_PHISHING;
     default:  // Gated by SafeBrowsingBlockingPage::ShouldReportThreatDetails.
       NOTREACHED() << "We should not send report for threat type "
                    << threat_type;
@@ -367,7 +367,7 @@
     report_->set_type(GetReportTypeFromSBThreatType(resource_.threat_type));
   }
 
-  if (resource_.threat_type == SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL)
+  if (resource_.threat_type == SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING)
     report_->set_token(resource_.token);
 
   GURL referrer_url;
diff --git a/components/safe_browsing/csd.proto b/components/safe_browsing/csd.proto
index 8d8b415..d84cc15 100644
--- a/components/safe_browsing/csd.proto
+++ b/components/safe_browsing/csd.proto
@@ -903,12 +903,12 @@
     URL_PHISHING = 1;
     URL_MALWARE = 2;
     URL_UNWANTED = 3;
-    CLIENT_SIDE_PHISHING_URL = 4;
-    CLIENT_SIDE_MALWARE_URL = 5;
+    URL_CLIENT_SIDE_PHISHING = 4;
+    URL_CLIENT_SIDE_MALWARE = 5;
     DANGEROUS_DOWNLOAD_RECOVERY = 6;
     DANGEROUS_DOWNLOAD_WARNING = 7;
     DANGEROUS_DOWNLOAD_BY_API = 10;
-    PASSWORD_PROTECTION_PHISHING_URL = 12;
+    URL_PASSWORD_PROTECTION_PHISHING = 12;
   }
 
   message HTTPHeader {
diff --git a/components/safe_browsing_db/BUILD.gn b/components/safe_browsing_db/BUILD.gn
index 5804b2fb..5eeacf1 100644
--- a/components/safe_browsing_db/BUILD.gn
+++ b/components/safe_browsing_db/BUILD.gn
@@ -33,6 +33,7 @@
     ":prefix_set",
     ":safebrowsing_proto",
     ":util",
+    ":v4_feature_list",  # Used by SafeBrowsingService
     "//components/safe_browsing/common:safe_browsing_prefs",
   ]
 }
diff --git a/components/safe_browsing_db/v4_local_database_manager.cc b/components/safe_browsing_db/v4_local_database_manager.cc
index 33d8629..be4f66b 100644
--- a/components/safe_browsing_db/v4_local_database_manager.cc
+++ b/components/safe_browsing_db/v4_local_database_manager.cc
@@ -69,7 +69,7 @@
       // The GetUrlMalBinId list is not working for non-GoogleChrome builds
       // currently so making it Chrome-only. See: http://crbug.com/728757
       ListInfo(kSyncOnlyOnChromeBuilds, "UrlMalBin.store", GetUrlMalBinId(),
-               SB_THREAT_TYPE_BINARY_MALWARE_URL),
+               SB_THREAT_TYPE_URL_BINARY_MALWARE),
       ListInfo(kSyncAlways, "ChromeExtMalware.store", GetChromeExtMalwareId(),
                SB_THREAT_TYPE_EXTENSION),
       ListInfo(kSyncOnlyOnChromeBuilds, "ChromeUrlClientIncident.store",
diff --git a/components/safe_browsing_db/v4_local_database_manager_unittest.cc b/components/safe_browsing_db/v4_local_database_manager_unittest.cc
index 5e20cb7..489ff7bd 100644
--- a/components/safe_browsing_db/v4_local_database_manager_unittest.cc
+++ b/components/safe_browsing_db/v4_local_database_manager_unittest.cc
@@ -1093,7 +1093,7 @@
   store_and_hash_prefixes.emplace_back(GetUrlMalBinId(), bad_hash_prefix);
   ReplaceV4Database(store_and_hash_prefixes, true /* stores_available */);
 
-  TestClient client(SB_THREAT_TYPE_BINARY_MALWARE_URL, url_chain);
+  TestClient client(SB_THREAT_TYPE_URL_BINARY_MALWARE, url_chain);
   EXPECT_FALSE(
       v4_local_database_manager_->CheckDownloadUrl(url_chain, &client));
   EXPECT_FALSE(client.on_check_download_urls_result_called_);
diff --git a/components/safe_browsing_db/v4_protocol_manager_util.h b/components/safe_browsing_db/v4_protocol_manager_util.h
index 54b52250..944f2f1 100644
--- a/components/safe_browsing_db/v4_protocol_manager_util.h
+++ b/components/safe_browsing_db/v4_protocol_manager_util.h
@@ -93,18 +93,18 @@
   SB_THREAT_TYPE_URL_UNWANTED,
 
   // The download URL is malware.
-  SB_THREAT_TYPE_BINARY_MALWARE_URL,
+  SB_THREAT_TYPE_URL_BINARY_MALWARE,
 
   // Url detected by the client-side phishing model.  Note that unlike the
   // above values, this does not correspond to a downloaded list.
-  SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL,
+  SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING,
 
   // The Chrome extension or app (given by its ID) is malware.
   SB_THREAT_TYPE_EXTENSION,
 
   // Url detected by the client-side malware IP list. This IP list is part
   // of the client side detection model.
-  SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL,
+  SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE,
 
   // Url leads to a blacklisted resource script. Note that no warnings should be
   // shown on this threat type, but an incident report might be sent.
@@ -120,7 +120,7 @@
   SB_THREAT_TYPE_CSD_WHITELIST,
 
   // Url detected by password protection service.
-  SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL,
+  SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING,
 };
 
 // The information required to uniquely identify each list the client is
diff --git a/components/security_interstitials/content/unsafe_resource.cc b/components/security_interstitials/content/unsafe_resource.cc
index e8dd701..410c3c7 100644
--- a/components/security_interstitials/content/unsafe_resource.cc
+++ b/components/security_interstitials/content/unsafe_resource.cc
@@ -43,10 +43,10 @@
   // Client-side phishing/malware detection and password protection phishing
   // interstitials never block the main frame load, since they happen after the
   // page is finished loading.
-  if (threat_type == safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL ||
-      threat_type == safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL ||
+  if (threat_type == safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING ||
+      threat_type == safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE ||
       threat_type ==
-          safe_browsing::SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL) {
+          safe_browsing::SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING) {
     return false;
   }
 
diff --git a/components/security_interstitials/content/unsafe_resource.h b/components/security_interstitials/content/unsafe_resource.h
index bb10b65b..fdb31b4 100644
--- a/components/security_interstitials/content/unsafe_resource.h
+++ b/components/security_interstitials/content/unsafe_resource.h
@@ -68,7 +68,7 @@
   base::Callback<content::WebContents*(void)> web_contents_getter;
   safe_browsing::ThreatSource threat_source;
   // |token| field is only set if |threat_type| is
-  // SB_THREAT_TYPE_PASSWORD_PROTECTION_PHISHING_URL
+  // SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING
   std::string token;
 };
 
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index 39cf232..b87bb5e 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -71,17 +71,17 @@
   ResponseHeaderDictionary::const_iterator it = header_dictionary.begin();
   for (; it != header_dictionary.end(); ++it) {
     const std::string key_name(it->first);
+    const std::string value(it->second);
     if (key_name == kServiceTypeAttrName) {
-      params.service_type =
-          GetGAIAServiceTypeFromHeader(header_dictionary[kServiceTypeAttrName]);
+      params.service_type = GetGAIAServiceTypeFromHeader(value);
     } else if (key_name == kEmailAttrName) {
-      params.email = header_dictionary[kEmailAttrName];
+      params.email = value;
     } else if (key_name == kIsSamlAttrName) {
-      params.is_saml = header_dictionary[kIsSamlAttrName] == "true";
+      params.is_saml = value == "true";
     } else if (key_name == kContinueUrlAttrName) {
-      params.continue_url = header_dictionary[kContinueUrlAttrName];
+      params.continue_url = value;
     } else if (key_name == kIsSameTabAttrName) {
-      params.is_same_tab = header_dictionary[kIsSameTabAttrName] == "true";
+      params.is_same_tab = value == "true";
     } else {
       DLOG(WARNING) << "Unexpected Gaia header attribute '" << key_name << "'.";
     }
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index 54836d3..f97d520 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -337,4 +337,23 @@
   EXPECT_EQ(fake_header, header);
 }
 
+TEST_F(SigninHeaderHelperTest, TestInvalidManageAccountsParams) {
+  ManageAccountsParams params = BuildManageAccountsParams("blah");
+  EXPECT_EQ(GAIA_SERVICE_TYPE_NONE, params.service_type);
+}
+
+TEST_F(SigninHeaderHelperTest, TestBuildManageAccountsParams) {
+  const char kContinueURL[] = "https://www.example.com/continue";
+  const char kEmail[] = "foo@example.com";
+
+  ManageAccountsParams params = BuildManageAccountsParams(base::StringPrintf(
+      "action=REAUTH,email=%s,is_saml=true,is_same_tab=true,continue_url=%s",
+      kEmail, kContinueURL));
+  EXPECT_EQ(GAIA_SERVICE_TYPE_REAUTH, params.service_type);
+  EXPECT_EQ(kEmail, params.email);
+  EXPECT_EQ(true, params.is_saml);
+  EXPECT_EQ(true, params.is_same_tab);
+  EXPECT_EQ(GURL(kContinueURL), params.continue_url);
+}
+
 }  // namespace signin
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
index 46753cd..635b9fd 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -702,11 +702,11 @@
        safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS},
       {ActivationDecision::ACTIVATION_CONDITIONS_NOT_MET,
        ActivationList::PHISHING_INTERSTITIAL,
-       safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL,
+       safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE,
        safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS},
       {ActivationDecision::ACTIVATION_CONDITIONS_NOT_MET,
        ActivationList::PHISHING_INTERSTITIAL,
-       safe_browsing::SB_THREAT_TYPE_BINARY_MALWARE_URL,
+       safe_browsing::SB_THREAT_TYPE_URL_BINARY_MALWARE,
        safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS},
       {ActivationDecision::ACTIVATION_CONDITIONS_NOT_MET,
        ActivationList::PHISHING_INTERSTITIAL,
@@ -718,7 +718,7 @@
        safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS},
       {ActivationDecision::ACTIVATION_CONDITIONS_NOT_MET,
        ActivationList::PHISHING_INTERSTITIAL,
-       safe_browsing::SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL,
+       safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING,
        safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS},
       {ActivationDecision::ACTIVATION_CONDITIONS_NOT_MET,
        ActivationList::PHISHING_INTERSTITIAL,
diff --git a/components/translate/core/browser/ranker_model_loader_unittest.cc b/components/translate/core/browser/ranker_model_loader_unittest.cc
index c312c2d09..cc4b7650 100644
--- a/components/translate/core/browser/ranker_model_loader_unittest.cc
+++ b/components/translate/core/browser/ranker_model_loader_unittest.cc
@@ -22,14 +22,10 @@
 #include "base/test/scoped_task_scheduler.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/metrics/proto/translate_event.pb.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/translate/core/browser/proto/ranker_model.pb.h"
 #include "components/translate/core/browser/proto/translate_ranker_model.pb.h"
 #include "components/translate/core/browser/ranker_model.h"
 #include "components/translate/core/browser/translate_download_manager.h"
-#include "components/translate/core/browser/translate_prefs.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 945fa74..c514d5a 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -516,9 +516,6 @@
   DCHECK(!host_);
 
   cc::LayerTreeSettings settings;
-  settings.renderer_settings.refresh_rate = 60.0;
-  settings.renderer_settings.allow_antialiasing = false;
-  settings.renderer_settings.highp_threshold_min = 2048;
   settings.use_zero_copy = true;
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -782,11 +779,13 @@
       root_window_->GetBeginFrameSource(), task_runner,
       display_output_surface->capabilities().max_frames_pending));
 
+  cc::RendererSettings renderer_settings;
+  renderer_settings.allow_antialiasing = false;
+  renderer_settings.highp_threshold_min = 2048;
   display_.reset(new cc::Display(
       viz::HostSharedBitmapManager::current(),
-      BrowserGpuMemoryBufferManager::current(),
-      host_->GetSettings().renderer_settings, frame_sink_id_,
-      std::move(display_output_surface), std::move(scheduler),
+      BrowserGpuMemoryBufferManager::current(), renderer_settings,
+      frame_sink_id_, std::move(display_output_surface), std::move(scheduler),
       base::MakeUnique<cc::TextureMailboxDeleter>(task_runner)));
 
   auto compositor_frame_sink =
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
index 866222a0..66a37f2 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
@@ -41,6 +41,8 @@
 
 import java.util.concurrent.Semaphore;
 
+import javax.annotation.concurrent.GuardedBy;
+
 /**
  * This class implements all of the functionality for {@link ChildProcessService} which owns an
  * object of {@link ChildProcessServiceImpl}.
@@ -56,17 +58,20 @@
     // Only for a check that create is only called once.
     private static boolean sCreateCalled;
 
-    // Lock that protects the following members.
     private final Object mBinderLock = new Object();
-    private IGpuProcessCallback mGpuCallback;
+
+    @GuardedBy("mBinderLock")
     private boolean mBindToCallerCheck;
+
     // PID of the client of this service, set in bindToCaller(), if mBindToCallerCheck is true.
+    @GuardedBy("mBinderLock")
     private int mBoundCallingPid;
 
     // This is the native "Main" thread for the renderer / utility process.
     private Thread mMainThread;
     // Parameters received via IPC, only accessed while holding the mMainThread monitor.
     private String[] mCommandLineParams;
+    private IGpuProcessCallback mGpuCallback;
     private int mCpuCount;
     private long mCpuFeatures;
     // File descriptors that should be registered natively.
@@ -109,8 +114,8 @@
         // NOTE: Implement any IChildProcessService methods here.
         @Override
         public boolean bindToCaller() {
-            assert mBindToCallerCheck;
             synchronized (mBinderLock) {
+                assert mBindToCallerCheck;
                 int callingPid = Binder.getCallingPid();
                 if (mBoundCallingPid == 0) {
                     mBoundCallingPid = callingPid;
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index f8cadcf..f743446 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -392,8 +392,6 @@
       compositor_deps->IsGpuMemoryBufferCompositorResourcesEnabled();
   settings.enable_color_correct_rasterization =
       cmd.HasSwitch(switches::kEnableColorCorrectRendering);
-  settings.renderer_settings.enable_color_correct_rendering =
-      cmd.HasSwitch(switches::kEnableColorCorrectRendering);
   settings.resource_settings.buffer_to_texture_target_map =
       compositor_deps->GetBufferToTextureTargetMap();
 
@@ -402,8 +400,6 @@
 
   settings.use_layer_lists = cmd.HasSwitch(cc::switches::kEnableLayerLists);
 
-  settings.renderer_settings.allow_antialiasing &=
-      !cmd.HasSwitch(cc::switches::kDisableCompositedAntialiasing);
   // The means the renderer compositor has 2 possible modes:
   // - Threaded compositing with a scheduler.
   // - Single threaded compositing without a scheduler (for layout tests only).
@@ -460,7 +456,6 @@
     settings.scrollbar_animator = cc::LayerTreeSettings::NO_ANIMATOR;
     settings.solid_color_scrollbar_color = SK_ColorTRANSPARENT;
   }
-  settings.renderer_settings.highp_threshold_min = 2048;
   // Android WebView handles root layer flings itself.
   settings.ignore_root_layer_flings = using_synchronous_compositor;
   // Memory policy on Android WebView does not depend on whether device is
@@ -484,9 +479,6 @@
     // raster-on-demand, and use 50% of the memory otherwise.
     settings.max_memory_for_prepaint_percentage = 50;
   }
-  // Webview does not own the surface so should not clear it.
-  settings.renderer_settings.should_clear_root_render_pass =
-      !using_synchronous_compositor;
 
   if (base::SysInfo::IsLowEndDevice()) {
     // When running on a low end device, we limit cached bytes to 2MB.
@@ -547,8 +539,6 @@
 
   settings.disallow_non_exact_resource_reuse =
       cmd.HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
-  settings.renderer_settings.disallow_non_exact_resource_reuse =
-      settings.disallow_non_exact_resource_reuse;
 
   return settings;
 }
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 4ea8d78d..bcb6d396 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "cc/base/switches.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/test/pixel_test_output_surface.h"
 #include "cc/test/test_compositor_frame_sink.h"
@@ -54,6 +55,7 @@
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/icc_profile.h"
+#include "ui/gfx/switches.h"
 #include "ui/gfx/test/icc_profiles.h"
 
 #if defined(OS_MACOSX)
@@ -340,18 +342,21 @@
     if (!task_runner)
       task_runner = base::ThreadTaskRunnerHandle::Get().get();
 
-    ScreenInfo dummy_screen_info;
-    cc::LayerTreeSettings settings =
-        RenderWidgetCompositor::GenerateLayerTreeSettings(
-            *base::CommandLine::ForCurrentProcess(), deps, 1.f, false,
-            dummy_screen_info);
+    cc::RendererSettings renderer_settings;
+    base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
+    renderer_settings.enable_color_correct_rendering =
+        cmd->HasSwitch(switches::kEnableColorCorrectRendering);
+    renderer_settings.allow_antialiasing &=
+        !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
+    renderer_settings.highp_threshold_min = 2048;
 
     constexpr bool disable_display_vsync = false;
+    constexpr double refresh_rate = 60.0;
     auto compositor_frame_sink = base::MakeUnique<cc::TestCompositorFrameSink>(
         std::move(compositor_context_provider),
         std::move(worker_context_provider), nullptr /* shared_bitmap_manager */,
-        gpu_memory_buffer_manager, settings.renderer_settings, task_runner,
-        synchronous_composite, disable_display_vsync);
+        gpu_memory_buffer_manager, renderer_settings, task_runner,
+        synchronous_composite, disable_display_vsync, refresh_rate);
     compositor_frame_sink->SetClient(this);
     compositor_frame_sinks_[routing_id] = compositor_frame_sink.get();
     return std::move(compositor_frame_sink);
diff --git a/docs/git_tips.md b/docs/git_tips.md
index 7bb9ffa..ee1e031 100644
--- a/docs/git_tips.md
+++ b/docs/git_tips.md
@@ -29,6 +29,22 @@
     understand Git, here's a cheat sheet to quickly remind you of all the
     commands you need.
 
+## Configuring the output of "git log"
+
+By default, the date that "git log" displays is the "author date." In Chromium,
+this generally corresponds to the date that the committed patch was last
+uploaded. In most cases, however, the date that is of interest is the date that
+the patch was committed in the tree. To configure "git log" to instead display
+the latter date for your Chromium checkout, execute the following command:
+
+```shell
+git config format.pretty 'format:%C(auto,yellow)commit %H%C(auto)%d%nAuthor:    %an <%ae>%nCommitted: %cd%n%n%w(0,4,4)%B%-%n'
+```
+
+If you want to change *all* your repos (e.g., because you have multiple Chromium
+checkouts and don't care about having the default for other repos), add
+"--global" after "config" in the above command.
+
 ## Committing changes
 
 For a simple workflow (always commit all changed files, don't keep local
diff --git a/ios/chrome/app/startup_tasks.mm b/ios/chrome/app/startup_tasks.mm
index 34d2b65..8b8b6da 100644
--- a/ios/chrome/app/startup_tasks.mm
+++ b/ios/chrome/app/startup_tasks.mm
@@ -66,7 +66,7 @@
       GetApplicationContext()
           ->GetIOSChromeIOThread()
           ->system_url_request_context_getter(),
-      base::BindBlock(^(const UpgradeRecommendedDetails& details) {
+      base::BindBlockArc(^(const UpgradeRecommendedDetails& details) {
         [[UpgradeCenter sharedInstance] upgradeNotificationDidOccur:details];
       }));
 #endif  // defined(GOOGLE_CHROME_BUILD)
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm
index 11af4f9..002f4f9 100644
--- a/ios/chrome/browser/translate/translate_egtest.mm
+++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -727,7 +727,8 @@
 
 // Tests that translation occurs automatically on second navigation to an
 // already translated page.
-- (void)testAutoTranslate {
+// TODO(crbug.com/732797): Reenable this test.
+- (void)DISABLED_testAutoTranslate {
   // The translate machinery will not auto-fire without API keys, unless that
   // behavior is overridden for testing.
   translate::TranslateManager::SetIgnoreMissingKeyForTesting(true);
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 32fd3f7..07177392 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -447,9 +447,31 @@
 
 test("ios_web_unittests") {
   deps = [
-    ":core",
+    ":ios_web_general_unittests",
+    ":ios_web_navigation_unittests",
+    ":ios_web_net_unittests",
+    ":ios_web_public_unittests",
     ":ios_web_unittests_bundle_data",
+    ":ios_web_web_state_js_unittests",
+    ":ios_web_web_state_ui_unittests",
+    ":ios_web_web_state_unittests",
+    ":ios_web_webui_unittests",
     ":run_all_unittests",
+  ]
+
+  public_deps = [
+    ":ios_web_unittests_arc",
+  ]
+
+  assert_no_deps = ios_assert_no_deps
+
+  allow_circular_includes_from = [ ":ios_web_unittests_arc" ]
+}
+
+source_set("ios_web_general_unittests") {
+  testonly = true
+  deps = [
+    ":core",
     ":user_agent",
     ":web",
     "//base",
@@ -472,14 +494,44 @@
     "//ui/base:test_support",
   ]
 
-  public_deps = [
-    ":ios_web_unittests_arc",
-  ]
-
   sources = [
     "active_state_manager_impl_unittest.mm",
     "browser_state_unittest.cc",
     "history_state_util_unittest.mm",
+    "payments/payment_request_unittest.cc",
+    "test/web_test_unittest.mm",
+    "url_scheme_util_unittest.mm",
+    "url_util_unittest.cc",
+  ]
+}
+
+source_set("ios_web_navigation_unittests") {
+  testonly = true
+  deps = [
+    ":core",
+    ":user_agent",
+    ":web",
+    "//base",
+    "//base/test:test_support",
+    "//components/payments/core",
+    "//components/url_formatter",
+    "//ios/net",
+    "//ios/testing:ios_test_support",
+    "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
+    "//net:test_support",
+    "//services/service_manager/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base:test_support",
+  ]
+
+  sources = [
     "navigation/crw_navigation_item_storage_unittest.mm",
     "navigation/crw_session_controller_unittest.mm",
     "navigation/crw_session_storage_unittest.mm",
@@ -488,6 +540,36 @@
     "navigation/navigation_item_storage_test_util.mm",
     "navigation/navigation_manager_impl_unittest.mm",
     "navigation/nscoder_util_unittest.mm",
+  ]
+}
+
+source_set("ios_web_net_unittests") {
+  testonly = true
+  deps = [
+    ":core",
+    ":user_agent",
+    ":web",
+    "//base",
+    "//base/test:test_support",
+    "//components/payments/core",
+    "//components/url_formatter",
+    "//ios/net",
+    "//ios/testing:ios_test_support",
+    "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
+    "//net:test_support",
+    "//services/service_manager/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base:test_support",
+  ]
+
+  sources = [
     "net/cert_host_pair_unittest.cc",
     "net/cert_policy_unittest.cc",
     "net/crw_cert_verification_controller_unittest.mm",
@@ -495,7 +577,36 @@
     "net/request_group_util_unittest.mm",
     "net/request_tracker_impl_unittest.mm",
     "net/web_http_protocol_handler_delegate_unittest.mm",
-    "payments/payment_request_unittest.cc",
+  ]
+}
+
+source_set("ios_web_public_unittests") {
+  testonly = true
+  deps = [
+    ":core",
+    ":user_agent",
+    ":web",
+    "//base",
+    "//base/test:test_support",
+    "//components/payments/core",
+    "//components/url_formatter",
+    "//ios/net",
+    "//ios/testing:ios_test_support",
+    "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
+    "//net:test_support",
+    "//services/service_manager/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base:test_support",
+  ]
+
+  sources = [
     "public/origin_util_unittest.mm",
     "public/referrer_util_unittest.cc",
     "public/serializable_user_data_manager_unittest.mm",
@@ -503,20 +614,114 @@
     "public/test/crw_mock_web_state_delegate.mm",
     "public/user_agent_unittest.mm",
     "public/web_state/page_viewport_state_unittest.mm",
-    "test/web_test_unittest.mm",
-    "url_scheme_util_unittest.mm",
-    "url_util_unittest.cc",
+  ]
+}
+
+source_set("ios_web_web_state_unittests") {
+  testonly = true
+  deps = [
+    ":core",
+    ":ios_web_public_unittests",
+    ":user_agent",
+    ":web",
+    "//base",
+    "//base/test:test_support",
+    "//components/payments/core",
+    "//components/url_formatter",
+    "//ios/net",
+    "//ios/testing:ios_test_support",
+    "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
+    "//net:test_support",
+    "//services/service_manager/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base:test_support",
+  ]
+
+  sources = [
     "web_state/context_menu_params_utils_unittest.mm",
     "web_state/crw_pass_kit_downloader_unittest.mm",
     "web_state/error_translation_util_unittest.mm",
+    "web_state/navigation_context_impl_unittest.mm",
+    "web_state/page_display_state_unittest.mm",
+    "web_state/web_state_delegate_bridge_unittest.mm",
+    "web_state/web_state_impl_unittest.mm",
+    "web_state/web_state_observer_bridge_unittest.mm",
+    "web_state/web_state_unittest.mm",
+    "web_state/web_view_internal_creation_util_unittest.mm",
+    "web_state/wk_web_view_security_util_unittest.mm",
+  ]
+}
+
+source_set("ios_web_web_state_js_unittests") {
+  testonly = true
+  deps = [
+    ":core",
+    ":user_agent",
+    ":web",
+    "//base",
+    "//base/test:test_support",
+    "//components/payments/core",
+    "//components/url_formatter",
+    "//ios/net",
+    "//ios/testing:ios_test_support",
+    "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
+    "//net:test_support",
+    "//services/service_manager/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base:test_support",
+  ]
+
+  sources = [
     "web_state/js/common_js_unittest.mm",
     "web_state/js/context_menu_js_unittest.mm",
     "web_state/js/crw_js_injection_manager_unittest.mm",
     "web_state/js/crw_js_post_request_loader_unittest.mm",
     "web_state/js/crw_js_window_id_manager_unittest.mm",
     "web_state/js/page_script_util_unittest.mm",
-    "web_state/navigation_context_impl_unittest.mm",
-    "web_state/page_display_state_unittest.mm",
+  ]
+}
+
+source_set("ios_web_web_state_ui_unittests") {
+  testonly = true
+  deps = [
+    ":core",
+    ":user_agent",
+    ":web",
+    "//base",
+    "//base/test:test_support",
+    "//components/payments/core",
+    "//components/url_formatter",
+    "//ios/net",
+    "//ios/testing:ios_test_support",
+    "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
+    "//net:test_support",
+    "//services/service_manager/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base:test_support",
+  ]
+
+  sources = [
     "web_state/ui/crw_web_controller_container_view_unittest.mm",
     "web_state/ui/crw_web_controller_observer_unittest.mm",
     "web_state/ui/crw_web_controller_unittest.mm",
@@ -526,21 +731,41 @@
     "web_state/ui/web_view_js_utils_unittest.mm",
     "web_state/ui/wk_back_forward_list_item_holder_unittest.mm",
     "web_state/ui/wk_web_view_configuration_provider_unittest.mm",
-    "web_state/web_state_delegate_bridge_unittest.mm",
-    "web_state/web_state_impl_unittest.mm",
-    "web_state/web_state_observer_bridge_unittest.mm",
-    "web_state/web_state_unittest.mm",
-    "web_state/web_view_internal_creation_util_unittest.mm",
-    "web_state/wk_web_view_security_util_unittest.mm",
+  ]
+}
+
+source_set("ios_web_webui_unittests") {
+  testonly = true
+  deps = [
+    ":core",
+    ":user_agent",
+    ":web",
+    "//base",
+    "//base/test:test_support",
+    "//components/payments/core",
+    "//components/url_formatter",
+    "//ios/net",
+    "//ios/testing:ios_test_support",
+    "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
+    "//net:test_support",
+    "//services/service_manager/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base:test_support",
+  ]
+
+  sources = [
     "webui/crw_web_ui_manager_unittest.mm",
     "webui/crw_web_ui_page_builder_unittest.mm",
     "webui/mojo_facade_unittest.mm",
     "webui/url_fetcher_block_adapter_unittest.mm",
   ]
-
-  assert_no_deps = ios_assert_no_deps
-
-  allow_circular_includes_from = [ ":ios_web_unittests_arc" ]
 }
 
 test("ios_web_inttests") {
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
index 17f1f1b2..3c2ef70 100644
--- a/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -248,6 +248,6 @@
   testonly = true
   sources = [
     "echo.mojom",
-    "echo_import.mojom",
+    "echo_import/echo_import.mojom",
   ]
 }
diff --git a/mojo/public/interfaces/bindings/tests/echo.mojom b/mojo/public/interfaces/bindings/tests/echo.mojom
index 56c60630..545c5c9 100644
--- a/mojo/public/interfaces/bindings/tests/echo.mojom
+++ b/mojo/public/interfaces/bindings/tests/echo.mojom
@@ -4,7 +4,7 @@
 
 module test.echo.mojom;
 
-import "echo_import.mojom";
+import "echo_import/echo_import.mojom";
 
 interface Echo {
   EchoPoint(test.echo_import.mojom.Point point)
diff --git a/mojo/public/interfaces/bindings/tests/echo_import/OWNERS b/mojo/public/interfaces/bindings/tests/echo_import/OWNERS
new file mode 100644
index 0000000..6c1f2fb
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/echo_import/OWNERS
@@ -0,0 +1,6 @@
+per-file *.mojom=file://mojo/OWNERS
+
+# These mojom test files don't really require security review, but we need to
+# add these to please PRESUBMIT.
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/mojo/public/interfaces/bindings/tests/echo_import.mojom b/mojo/public/interfaces/bindings/tests/echo_import/echo_import.mojom
similarity index 100%
rename from mojo/public/interfaces/bindings/tests/echo_import.mojom
rename to mojo/public/interfaces/bindings/tests/echo_import/echo_import.mojom
diff --git a/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl b/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl
index 0b9eb157..8772a404 100644
--- a/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl
@@ -27,7 +27,7 @@
   if (mojo.config.autoLoadMojomDeps) {
     mojo.internal.loadMojomIfNecessary(
         '{{import.path}}',
-        new URL('{{import|get_relative_path(module)}}.js',
+        new URL('{{import|get_relative_url(module)}}.js',
                 document.currentScript.src).href);
   }
 {%-   endfor %}
diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py
index a6e3134..969a055b 100644
--- a/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -8,6 +8,7 @@
 import mojom.generate.module as mojom
 import mojom.generate.pack as pack
 import os
+import urllib
 from mojom.generate.template_expander import UseJinja
 
 _kind_to_javascript_default_value = {
@@ -88,8 +89,9 @@
   return expected_dimension_sizes
 
 
-def GetRelativePath(module, base_module):
-  return os.path.relpath(module.path, os.path.dirname(base_module.path))
+def GetRelativeUrl(module, base_module):
+  return urllib.pathname2url(
+      os.path.relpath(module.path, os.path.dirname(base_module.path)))
 
 
 class JavaScriptStylizer(generator.Stylizer):
@@ -140,7 +142,7 @@
       "encode_snippet": self._JavaScriptEncodeSnippet,
       "expression_to_text": self._ExpressionToText,
       "field_offset": JavaScriptFieldOffset,
-      "get_relative_path": GetRelativePath,
+      "get_relative_url": GetRelativeUrl,
       "has_callbacks": mojom.HasCallbacks,
       "is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind,
       "is_array_kind": mojom.IsArrayKind,
diff --git a/ppapi/api/pp_graphics_3d.idl b/ppapi/api/pp_graphics_3d.idl
index 86dc6ae..43b854d8 100644
--- a/ppapi/api/pp_graphics_3d.idl
+++ b/ppapi/api/pp_graphics_3d.idl
@@ -79,5 +79,10 @@
   /**
    * The context may be high-power and may be created on a discrete gpu.
    */
-  PP_GRAPHICS3DATTRIB_GPU_PREFERENCE_PERFORMANCE = 0x11002
+  PP_GRAPHICS3DATTRIB_GPU_PREFERENCE_PERFORMANCE = 0x11002,
+  /**
+   * Whether or not offscreen color buffers exist in front/back pairs that
+   * can be swapped.
+   */
+  PP_GRAPHICS3DATTRIB_SINGLE_BUFFER = 0x3085
 };
diff --git a/ppapi/c/pp_graphics_3d.h b/ppapi/c/pp_graphics_3d.h
index 77b20aae..dfe76ac5 100644
--- a/ppapi/c/pp_graphics_3d.h
+++ b/ppapi/c/pp_graphics_3d.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From pp_graphics_3d.idl modified Wed Oct  3 15:55:01 2012. */
+/* From pp_graphics_3d.idl modified Fri Jun  9 15:44:15 2017. */
 
 #ifndef PPAPI_C_PP_GRAPHICS_3D_H_
 #define PPAPI_C_PP_GRAPHICS_3D_H_
@@ -92,7 +92,12 @@
   /**
    * The context may be high-power and may be created on a discrete gpu.
    */
-  PP_GRAPHICS3DATTRIB_GPU_PREFERENCE_PERFORMANCE = 0x11002
+  PP_GRAPHICS3DATTRIB_GPU_PREFERENCE_PERFORMANCE = 0x11002,
+  /**
+   * Whether or not offscreen color buffers exist in front/back pairs that
+   * can be swapped.
+   */
+  PP_GRAPHICS3DATTRIB_SINGLE_BUFFER = 0x3085
 } PP_Graphics3DAttrib;
 PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_Graphics3DAttrib, 4);
 /**
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc
index a38c2c3..31b29bc1 100644
--- a/ppapi/proxy/ppb_graphics_3d_proxy.cc
+++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -193,6 +193,9 @@
                   ? gl::PreferIntegratedGpu
                   : gl::PreferDiscreteGpu;
           break;
+        case PP_GRAPHICS3DATTRIB_SINGLE_BUFFER:
+          attrib_helper.single_buffer = !!attr[1];
+          break;
         default:
           attribs.push_back(attr[0]);
           attribs.push_back(attr[1]);
diff --git a/services/preferences/tracked/registry_hash_store_contents_win.cc b/services/preferences/tracked/registry_hash_store_contents_win.cc
index 4b80458..354a5bf 100644
--- a/services/preferences/tracked/registry_hash_store_contents_win.cc
+++ b/services/preferences/tracked/registry_hash_store_contents_win.cc
@@ -6,12 +6,10 @@
 
 #include <windows.h>
 
-#include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -68,21 +66,43 @@
   return false;
 }
 
+// Deletes |reg_key_name| if it exists.
+void DeleteRegistryKey(const base::string16& reg_key_name) {
+  base::win::RegKey key;
+  if (key.Open(HKEY_CURRENT_USER, reg_key_name.c_str(),
+               KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+    LONG result = key.DeleteKey(L"");
+    DCHECK(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) << result;
+  }
+}
+
 }  // namespace
 
+void TempScopedDirRegistryCleaner::SetRegistryPath(
+    const base::string16& registry_path) {
+  if (registry_path_.empty())
+    registry_path_ = registry_path;
+  else
+    DCHECK_EQ(registry_path_, registry_path);
+}
+
+TempScopedDirRegistryCleaner::~TempScopedDirRegistryCleaner() {
+  DCHECK(!registry_path_.empty());
+  DeleteRegistryKey(registry_path_);
+}
+
 RegistryHashStoreContentsWin::RegistryHashStoreContentsWin(
     const base::string16& registry_path,
-    const base::string16& store_key)
+    const base::string16& store_key,
+    scoped_refptr<TempScopedDirCleaner> temp_dir_cleaner)
     : preference_key_name_(registry_path + L"\\PreferenceMACs\\" + store_key),
-      reset_on_delete_(base::StartsWith(store_key,
-                                        base::ScopedTempDir::GetTempDirPrefix(),
-                                        base::CompareCase::INSENSITIVE_ASCII)) {
+      temp_dir_cleaner_(std::move(temp_dir_cleaner)) {
+  if (temp_dir_cleaner_)
+    static_cast<TempScopedDirRegistryCleaner*>(temp_dir_cleaner_.get())
+        ->SetRegistryPath(preference_key_name_);
 }
 
-RegistryHashStoreContentsWin::~RegistryHashStoreContentsWin() {
-  if (reset_on_delete_)
-    Reset();
-}
+RegistryHashStoreContentsWin::~RegistryHashStoreContentsWin() = default;
 
 RegistryHashStoreContentsWin::RegistryHashStoreContentsWin(
     const RegistryHashStoreContentsWin& other) = default;
@@ -101,14 +121,7 @@
 }
 
 void RegistryHashStoreContentsWin::Reset() {
-  base::win::RegKey key;
-  if (key.Open(HKEY_CURRENT_USER, preference_key_name_.c_str(),
-               KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
-    LONG result = key.DeleteKey(L"");
-    DCHECK(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND ||
-           result == ERROR_ACCESS_DENIED || result == ERROR_KEY_DELETED)
-        << result;
-  }
+  DeleteRegistryKey(preference_key_name_);
 }
 
 bool RegistryHashStoreContentsWin::GetMac(const std::string& path,
diff --git a/services/preferences/tracked/registry_hash_store_contents_win.h b/services/preferences/tracked/registry_hash_store_contents_win.h
index 0b3b396..dd55669 100644
--- a/services/preferences/tracked/registry_hash_store_contents_win.h
+++ b/services/preferences/tracked/registry_hash_store_contents_win.h
@@ -8,18 +8,29 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "services/preferences/tracked/hash_store_contents.h"
+#include "services/preferences/tracked/temp_scoped_dir_cleaner.h"
+
+// Helper object to clear registry entries for scoped temporary pref stores.
+class TempScopedDirRegistryCleaner : public TempScopedDirCleaner {
+ public:
+  void SetRegistryPath(const base::string16& registry_path);
+
+ private:
+  friend class base::RefCountedThreadSafe<TempScopedDirRegistryCleaner>;
+  ~TempScopedDirRegistryCleaner() override;
+
+  base::string16 registry_path_;
+};
 
 // Implements HashStoreContents by storing MACs in the Windows registry.
 class RegistryHashStoreContentsWin : public HashStoreContents {
  public:
   // Constructs a RegistryHashStoreContents which acts on a registry entry
-  // defined by |registry_path| and |store_key|. If |store_key| begins with
-  // base::ScopedTempDir::GetTempDirPrefix(), this RegistryHashStoreContentsWin
-  // will self Reset() on destruction to avoid proliferating keys in tests that
-  // create a profile in a ScopedTempDir (https://crbug.com/721245).
-  explicit RegistryHashStoreContentsWin(const base::string16& registry_path,
-                                        const base::string16& store_key);
-
+  // defined by |registry_path| and |store_key|.
+  explicit RegistryHashStoreContentsWin(
+      const base::string16& registry_path,
+      const base::string16& store_key,
+      scoped_refptr<TempScopedDirCleaner> temp_dir_cleaner);
   ~RegistryHashStoreContentsWin() override;
 
   // HashStoreContents overrides:
@@ -49,7 +60,7 @@
       const RegistryHashStoreContentsWin& other);
 
   const base::string16 preference_key_name_;
-  const bool reset_on_delete_;
+  scoped_refptr<TempScopedDirCleaner> temp_dir_cleaner_;
 };
 
 #endif  // SERVICES_PREFERENCES_TRACKED_REGISTRY_HASH_STORE_CONTENTS_WIN_H_
diff --git a/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc b/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc
index 4688434..d85fdbf 100644
--- a/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc
+++ b/services/preferences/tracked/registry_hash_store_contents_win_unittest.cc
@@ -4,9 +4,13 @@
 
 #include "services/preferences/tracked/registry_hash_store_contents_win.h"
 
+#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_reg_util_win.h"
+#include "base/threading/thread.h"
 #include "base/values.h"
 #include "base/win/registry.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -33,7 +37,8 @@
     ASSERT_NO_FATAL_FAILURE(
         registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
 
-    contents.reset(new RegistryHashStoreContentsWin(kRegistryPath, kStoreKey));
+    contents.reset(
+        new RegistryHashStoreContentsWin(kRegistryPath, kStoreKey, nullptr));
   }
 
   std::unique_ptr<HashStoreContents> contents;
@@ -118,3 +123,90 @@
   EXPECT_FALSE(contents->GetSplitMacs(kSplitPrefPath, &split_macs));
   EXPECT_EQ(0U, split_macs.size());
 }
+
+TEST(RegistryHashStoreContentsWinScopedTest, TestScopedDirsCleared) {
+  std::string stored_mac;
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  const base::string16 registry_path =
+      temp_dir.GetPath().DirName().BaseName().LossyDisplayName();
+
+  RegistryHashStoreContentsWin verifying_contents(registry_path, kStoreKey,
+                                                  nullptr);
+
+  scoped_refptr<TempScopedDirRegistryCleaner> temp_scoped_dir_cleaner =
+      base::MakeRefCounted<TempScopedDirRegistryCleaner>();
+  std::unique_ptr<RegistryHashStoreContentsWin> contentsA =
+      base::MakeUnique<RegistryHashStoreContentsWin>(registry_path, kStoreKey,
+                                                     temp_scoped_dir_cleaner);
+  std::unique_ptr<RegistryHashStoreContentsWin> contentsB =
+      base::MakeUnique<RegistryHashStoreContentsWin>(registry_path, kStoreKey,
+                                                     temp_scoped_dir_cleaner);
+
+  contentsA->SetMac(kAtomicPrefPath, kTestStringA);
+  contentsB->SetMac(kAtomicPrefPath, kTestStringB);
+
+  temp_scoped_dir_cleaner = nullptr;
+  EXPECT_TRUE(verifying_contents.GetMac(kAtomicPrefPath, &stored_mac));
+  EXPECT_EQ(kTestStringB, stored_mac);
+
+  contentsB.reset();
+  EXPECT_TRUE(verifying_contents.GetMac(kAtomicPrefPath, &stored_mac));
+  EXPECT_EQ(kTestStringB, stored_mac);
+
+  contentsA.reset();
+  EXPECT_FALSE(verifying_contents.GetMac(kAtomicPrefPath, &stored_mac));
+}
+
+void OffThreadTempScopedDirDestructor(
+    base::string16 registry_path,
+    std::unique_ptr<HashStoreContents> contents) {
+  std::string stored_mac;
+
+  RegistryHashStoreContentsWin verifying_contents(registry_path, kStoreKey,
+                                                  nullptr);
+
+  contents->SetMac(kAtomicPrefPath, kTestStringB);
+  EXPECT_TRUE(verifying_contents.GetMac(kAtomicPrefPath, &stored_mac));
+  EXPECT_EQ(kTestStringB, stored_mac);
+
+  contents.reset();
+  EXPECT_FALSE(verifying_contents.GetMac(kAtomicPrefPath, &stored_mac));
+}
+
+TEST(RegistryHashStoreContentsWinScopedTest, TestScopedDirsClearedMultiThread) {
+  std::string stored_mac;
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  const base::string16 registry_path =
+      temp_dir.GetPath().DirName().BaseName().LossyDisplayName();
+
+  RegistryHashStoreContentsWin verifying_contents(registry_path, kStoreKey,
+                                                  nullptr);
+
+  base::Thread test_thread("scoped_dir_cleaner_test_thread");
+  test_thread.StartAndWaitForTesting();
+
+  scoped_refptr<TempScopedDirRegistryCleaner> temp_scoped_dir_cleaner =
+      base::MakeRefCounted<TempScopedDirRegistryCleaner>();
+  std::unique_ptr<RegistryHashStoreContentsWin> contents =
+      base::MakeUnique<RegistryHashStoreContentsWin>(
+          registry_path, kStoreKey, std::move(temp_scoped_dir_cleaner));
+  base::OnceClosure other_thread_closure =
+      base::BindOnce(&OffThreadTempScopedDirDestructor, registry_path,
+                     base::Passed(contents->MakeCopy()));
+
+  contents->SetMac(kAtomicPrefPath, kTestStringA);
+  contents.reset();
+
+  EXPECT_TRUE(verifying_contents.GetMac(kAtomicPrefPath, &stored_mac));
+  EXPECT_EQ(kTestStringA, stored_mac);
+
+  test_thread.task_runner()->PostTask(FROM_HERE,
+                                      std::move(other_thread_closure));
+  test_thread.FlushForTesting();
+
+  EXPECT_FALSE(verifying_contents.GetMac(kAtomicPrefPath, &stored_mac));
+}
diff --git a/services/preferences/tracked/temp_scoped_dir_cleaner.h b/services/preferences/tracked/temp_scoped_dir_cleaner.h
new file mode 100644
index 0000000..4359b76
--- /dev/null
+++ b/services/preferences/tracked/temp_scoped_dir_cleaner.h
@@ -0,0 +1,18 @@
+// 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 SERVICES_PREFERENCES_TRACKED_TEMP_SCOPED_DIR_CLEANER_H_
+#define SERVICES_PREFERENCES_TRACKED_TEMP_SCOPED_DIR_CLEANER_H_
+
+#include "base/memory/ref_counted.h"
+
+// Helper object to clear additional data for scoped temporary pref stores.
+class TempScopedDirCleaner
+    : public base::RefCountedThreadSafe<TempScopedDirCleaner> {
+ protected:
+  friend class base::RefCountedThreadSafe<TempScopedDirCleaner>;
+  virtual ~TempScopedDirCleaner(){};
+};
+
+#endif  // SERVICES_PREFERENCES_TRACKED_TEMP_SCOPED_DIR_CLEANER_H_
diff --git a/services/preferences/tracked/tracked_persistent_pref_store_factory.cc b/services/preferences/tracked/tracked_persistent_pref_store_factory.cc
index ffb5ab2..be4ce2d 100644
--- a/services/preferences/tracked/tracked_persistent_pref_store_factory.cc
+++ b/services/preferences/tracked/tracked_persistent_pref_store_factory.cc
@@ -16,9 +16,12 @@
 #include "services/preferences/tracked/pref_hash_filter.h"
 #include "services/preferences/tracked/pref_hash_store_impl.h"
 #include "services/preferences/tracked/segregated_pref_store.h"
+#include "services/preferences/tracked/temp_scoped_dir_cleaner.h"
 #include "services/preferences/tracked/tracked_preferences_migration.h"
 
 #if defined(OS_WIN)
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/string_util.h"
 #include "services/preferences/tracked/registry_hash_store_contents_win.h"
 #endif
 
@@ -41,16 +44,18 @@
 
 std::pair<std::unique_ptr<PrefHashStore>, std::unique_ptr<HashStoreContents>>
 GetExternalVerificationPrefHashStorePair(
-    const prefs::mojom::TrackedPersistentPrefStoreConfiguration& config) {
+    const prefs::mojom::TrackedPersistentPrefStoreConfiguration& config,
+    scoped_refptr<TempScopedDirCleaner> temp_dir_cleaner) {
 #if defined(OS_WIN)
-  return std::make_pair(
-      base::MakeUnique<PrefHashStoreImpl>(config.registry_seed,
-                                          config.legacy_device_id,
-                                          false /* use_super_mac */),
-      base::MakeUnique<RegistryHashStoreContentsWin>(
-          config.registry_path, config.unprotected_pref_filename.DirName()
-                                    .BaseName()
-                                    .LossyDisplayName()));
+  return std::make_pair(base::MakeUnique<PrefHashStoreImpl>(
+                            config.registry_seed, config.legacy_device_id,
+                            false /* use_super_mac */),
+                        base::MakeUnique<RegistryHashStoreContentsWin>(
+                            config.registry_path,
+                            config.unprotected_pref_filename.DirName()
+                                .BaseName()
+                                .LossyDisplayName(),
+                            std::move(temp_dir_cleaner)));
 #else
   return std::make_pair(nullptr, nullptr);
 #endif
@@ -82,15 +87,33 @@
   }
   config->tracking_configuration.clear();
 
+  scoped_refptr<TempScopedDirCleaner> temp_scoped_dir_cleaner;
+#if defined(OS_WIN)
+  // For tests that create a profile in a ScopedTempDir, share a ref_counted
+  // object between the unprotected and protected hash filter's
+  // RegistryHashStoreContentsWin which will clear the registry keys when
+  // destroyed. (https://crbug.com/721245)
+  if (base::StartsWith(config->unprotected_pref_filename.DirName()
+                           .BaseName()
+                           .LossyDisplayName(),
+                       base::ScopedTempDir::GetTempDirPrefix(),
+                       base::CompareCase::INSENSITIVE_ASCII)) {
+    temp_scoped_dir_cleaner =
+        base::MakeRefCounted<TempScopedDirRegistryCleaner>();
+  }
+#endif
+
   std::unique_ptr<PrefHashFilter> unprotected_pref_hash_filter(
       new PrefHashFilter(CreatePrefHashStore(*config, false),
-                         GetExternalVerificationPrefHashStorePair(*config),
+                         GetExternalVerificationPrefHashStorePair(
+                             *config, temp_scoped_dir_cleaner),
                          unprotected_configuration, nullptr,
                          config->validation_delegate.get(),
                          config->reporting_ids_count, false));
   std::unique_ptr<PrefHashFilter> protected_pref_hash_filter(new PrefHashFilter(
       CreatePrefHashStore(*config, true),
-      GetExternalVerificationPrefHashStorePair(*config),
+      GetExternalVerificationPrefHashStorePair(*config,
+                                               temp_scoped_dir_cleaner),
       protected_configuration, std::move(config->reset_on_load_observer),
       config->validation_delegate.get(), config->reporting_ids_count, true));
 
@@ -125,9 +148,10 @@
 void InitializeMasterPrefsTracking(
     prefs::mojom::TrackedPersistentPrefStoreConfigurationPtr configuration,
     base::DictionaryValue* master_prefs) {
-  PrefHashFilter(CreatePrefHashStore(*configuration, false),
-                 GetExternalVerificationPrefHashStorePair(*configuration),
-                 configuration->tracking_configuration, nullptr, nullptr,
-                 configuration->reporting_ids_count, false)
+  PrefHashFilter(
+      CreatePrefHashStore(*configuration, false),
+      GetExternalVerificationPrefHashStorePair(*configuration, nullptr),
+      configuration->tracking_configuration, nullptr, nullptr,
+      configuration->reporting_ids_count, false)
       .Initialize(master_prefs);
 }
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json
index 4c13da6..9217168 100644
--- a/testing/buildbot/chromium.webkit.json
+++ b/testing/buildbot/chromium.webkit.json
@@ -26,37 +26,6 @@
         "test": "wtf_unittests"
       }
     ],
-    "isolated_scripts": [
-      {
-        "isolate_name": "webkit_layout_tests_exparchive",
-        "merge": {
-          "args": [
-            "--verbose",
-            "--results-json-override-with-build-property",
-            "build_number",
-            "buildnumber",
-            "--results-json-override-with-build-property",
-            "builder_name",
-            "buildername",
-            "--results-json-override-with-build-property",
-            "chromium_revision",
-            "got_revision_cp"
-          ],
-          "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results"
-        },
-        "name": "webkit_layout_tests",
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-14.04"
-            }
-          ],
-          "shards": 6
-        }
-      }
-    ],
     "scripts": [
       {
         "name": "webkit_lint",
@@ -95,37 +64,6 @@
         "test": "wtf_unittests"
       }
     ],
-    "isolated_scripts": [
-      {
-        "isolate_name": "webkit_layout_tests_exparchive",
-        "merge": {
-          "args": [
-            "--verbose",
-            "--results-json-override-with-build-property",
-            "build_number",
-            "buildnumber",
-            "--results-json-override-with-build-property",
-            "builder_name",
-            "buildername",
-            "--results-json-override-with-build-property",
-            "chromium_revision",
-            "got_revision_cp"
-          ],
-          "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results"
-        },
-        "name": "webkit_layout_tests",
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-14.04"
-            }
-          ],
-          "shards": 6
-        }
-      }
-    ],
     "scripts": [
       {
         "name": "webkit_lint",
@@ -163,44 +101,6 @@
         },
         "test": "wtf_unittests"
       }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--additional-expectations",
-          "src/third_party/WebKit/LayoutTests/ASANExpectations",
-          "--time-out-ms",
-          "48000",
-          "--enable-sanitizer"
-        ],
-        "isolate_name": "webkit_layout_tests_exparchive",
-        "merge": {
-          "args": [
-            "--verbose",
-            "--results-json-override-with-build-property",
-            "build_number",
-            "buildnumber",
-            "--results-json-override-with-build-property",
-            "builder_name",
-            "buildername",
-            "--results-json-override-with-build-property",
-            "chromium_revision",
-            "got_revision_cp"
-          ],
-          "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results"
-        },
-        "name": "webkit_layout_tests",
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-14.04"
-            }
-          ],
-          "shards": 6
-        }
-      }
     ]
   },
   "WebKit Linux Trusty Leak": {
@@ -230,44 +130,7 @@
         "test": "wtf_unittests"
       }
     ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--additional-expectations",
-          "src/third_party/WebKit/LayoutTests/LeakExpectations",
-          "--time-out-ms",
-          "48000",
-          "--enable-leak-detection"
-        ],
-        "isolate_name": "webkit_layout_tests_exparchive",
-        "merge": {
-          "args": [
-            "--verbose",
-            "--results-json-override-with-build-property",
-            "build_number",
-            "buildnumber",
-            "--results-json-override-with-build-property",
-            "builder_name",
-            "buildername",
-            "--results-json-override-with-build-property",
-            "chromium_revision",
-            "got_revision_cp"
-          ],
-          "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results"
-        },
-        "name": "webkit_layout_tests",
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-14.04"
-            }
-          ],
-          "shards": 6
-        }
-      }
-    ]
+    "scripts": []
   },
   "WebKit Linux Trusty MSAN": {
     "gtest_tests": [
@@ -295,44 +158,6 @@
         },
         "test": "wtf_unittests"
       }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--additional-expectations",
-          "src/third_party/WebKit/LayoutTests/MSANExpectations",
-          "--time-out-ms",
-          "66000",
-          "--enable-sanitizer"
-        ],
-        "isolate_name": "webkit_layout_tests_exparchive",
-        "merge": {
-          "args": [
-            "--verbose",
-            "--results-json-override-with-build-property",
-            "build_number",
-            "buildnumber",
-            "--results-json-override-with-build-property",
-            "builder_name",
-            "buildername",
-            "--results-json-override-with-build-property",
-            "chromium_revision",
-            "got_revision_cp"
-          ],
-          "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results"
-        },
-        "name": "webkit_layout_tests",
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-14.04"
-            }
-          ],
-          "shards": 6
-        }
-      }
     ]
   },
   "WebKit Mac10.10": {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 4fc005b..9b4d161 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -82,11 +82,6 @@
 crbug.com/664852 virtual/gpu/fast/canvas/canvas-createImageBitmap-webgl.html [ Pass Failure ]
 crbug.com/664852 virtual/gpu/fast/canvas/OffscreenCanvas-2d-drawImage.html [ Pass Failure ]
 
-########## Skia issues ##########
-crbug.com/728566 virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png.html [ NeedsManualRebaseline ]
-crbug.com/728566 virtual/gpu-rasterization/images/color-profile-background-image-cross-fade.html [ NeedsManualRebaseline ]
-crbug.com/728566 virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ NeedsManualRebaseline ]
-
 ########## Bugs to fix ##########
 # This is a missing event and increasing the timeout or using run-after-layout-and-paint doesn't
 # seem to fix it.
@@ -375,7 +370,6 @@
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-027.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-028.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-029.xht [ Failure ]
-crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-031.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-036.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-038.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-039.xht [ Failure ]
@@ -384,7 +378,6 @@
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-109.xht [ Skip ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-110.xht [ Skip ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-113.xht [ Failure ]
-crbug.com/719620 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-114.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-126.xht [ Skip ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-127.xht [ Skip ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-128.xht [ Skip ]
@@ -442,14 +435,8 @@
 ### virtual/layout_ng/external/wpt/css/CSS2/normal-flow
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-formatting-context-height-001.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-formatting-context-height-002.xht [ Failure ]
-crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-formatting-contexts-015.xht [ Failure ]
-crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001a.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001f.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-insert-002f.xht [ Failure ]
-crbug.com/719646 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-margins-001a.xht [ Failure ]
-crbug.com/719646 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-margins-001b.xht [ Failure ]
-crbug.com/719646 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-margins-002a.xht [ Failure ]
-crbug.com/719646 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-margins-002b.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-percents-001.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-remove-002.xht [ Failure Pass ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-in-inline-remove-004.xht [ Failure Pass ]
@@ -479,7 +466,6 @@
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inlines-006.xht [ Skip ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inlines-013.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inlines-017.xht [ Failure ]
-crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inlines-020.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/max-height-applies-to-012.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/max-height-percentage-002.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/max-width-applies-to-005.xht [ Failure ]
@@ -669,7 +655,6 @@
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-in-float-painting.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-inserted-into-clean-line.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-list-changed-before-layout-crash.html [ Crash ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-crash2.html [ Crash ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-first-letter.html [ Crash ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling-crash.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling3.html [ Failure ]
@@ -753,20 +738,15 @@
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/bfc-beside-float-complex-margin-collapsing.html [ Failure ]
 
 ### virtual/layout_ng/fast/block/margin-collapse/block-inside-inline
-crbug.com/719646 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/001.html [ Failure ]
 crbug.com/719646 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/002.html [ Failure ]
 crbug.com/719646 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/003.html [ Failure ]
 crbug.com/719646 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/004.html [ Failure ]
-crbug.com/719646 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/005.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/006.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/010.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/011.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/012.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/015.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/016.html [ Failure ]
-crbug.com/719646 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/018.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/021.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/022.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/block-inside-inline/025.html [ Failure ]
 
 ### virtual/layout_ng/fast/block/margin-collapse
@@ -2365,6 +2345,14 @@
 
 # Manual tests that have not been automated.
 crbug.com/626703 external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.html [ Timeout ]
+crbug.com/732451 external/wpt/viewport/viewport-page-manual.html [ Skip ]
+crbug.com/732451 external/wpt/viewport/viewport-scroll-event-manual.html [ Skip ]
+crbug.com/732451 external/wpt/viewport/viewport-dimensions-scrollbars-manual.html [ Skip ]
+crbug.com/732451 external/wpt/viewport/viewport-resize-event-manual.html [ Skip ]
+crbug.com/732451 external/wpt/viewport/viewport-offset-manual.html [ Skip ]
+crbug.com/732451 external/wpt/viewport/viewport-scale-iframe-manual.html [ Skip ]
+crbug.com/732451 external/wpt/viewport/viewport-dimensions-custom-scrollbars-manual.html [ Skip ]
+crbug.com/732451 external/wpt/viewport/viewport-scale-manual.html [ Skip ]
 
 # Other untriaged test failures, timeouts and crashes from newly-imported WPT tests.
 crbug.com/666703 external/wpt/html/browsers/sandboxing/sandbox-disallow-same-origin.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/battery-status/detached-no-crash-expected.txt b/third_party/WebKit/LayoutTests/battery-status/detached-no-crash-expected.txt
index ab52d16..e7dfc5c6 100644
--- a/third_party/WebKit/LayoutTests/battery-status/detached-no-crash-expected.txt
+++ b/third_party/WebKit/LayoutTests/battery-status/detached-no-crash-expected.txt
@@ -4,7 +4,7 @@
 
 
 PASS typeof(nav.getBattery()) == 'object' is true
-Error Code is 18
+PASS nav.getBattery() is undefined.
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/battery-status/detached-no-crash.html b/third_party/WebKit/LayoutTests/battery-status/detached-no-crash.html
index 58cbb5d..3caf6e05 100644
--- a/third_party/WebKit/LayoutTests/battery-status/detached-no-crash.html
+++ b/third_party/WebKit/LayoutTests/battery-status/detached-no-crash.html
@@ -18,15 +18,8 @@
         w.close();
         w = null;
     } else if (event.data == "closed") {
-      nav.getBattery().then(battery => {
-        assert_unreachable('getBattery should reject on a closed window');
-      })
-      .catch(error => {
-        // DOMException.SECURITY_ERR = 18.
-        debug('Error Code is ' + error.code);
-        assert_equals(error.code, DOMException.SECURITY_ERR);
-      });
-      setTimeout(finishJSTest, 0);
+        shouldBeUndefined("nav.getBattery()");
+        finishJSTest();
     }
 }
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-iframe.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-iframe.https-expected.txt
new file mode 100644
index 0000000..13eb105
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-iframe.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL throw a 'SecurityError' when invoking navigator.getBattery() within iframe assert_unreached: Should have rejected: undefined Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-insecure-context-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-insecure-context-expected.txt
new file mode 100644
index 0000000..6594edf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-insecure-context-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL navigator.getBattery() shall throw a 'SecurityError' in an insecure context assert_unreached: Should have rejected: undefined Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/viewport/OWNERS
new file mode 100644
index 0000000..c0dd4aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/OWNERS
@@ -0,0 +1,2 @@
+# TEAM: input-dev@chromium.org
+# COMPONENT: Blink>Input
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-custom-scrollbars-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-custom-scrollbars-manual.html
new file mode 100644
index 0000000..f4671c9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-custom-scrollbars-manual.html
@@ -0,0 +1,146 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Dimensions with custom scrollbars</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_done: true, explicit_timeout: true});
+        </script>
+        <style>
+          #spacer {
+            width: 10000px;
+            height: 10000px;
+            position: absolute;
+            visibility: hidden;
+          }
+          ::-webkit-scrollbar {
+            width: 20px;
+            height: 25px;
+          }
+
+          ::-webkit-scrollbar-track {
+                background-color: #b46868;
+          }
+
+          ::-webkit-scrollbar-thumb {
+                background-color: rgba(0, 0, 0, 0.2);
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Dimensions with custom scrollbars</h1>
+    <h4>
+        Test Description: Tests the viewport dimensions correctly account for
+        custom scrollbars
+    </h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip</button>
+        <p>
+            Skip this test if your browser doesn't support custom scrollbars or
+            browser-zoom (Ctrl+/-).
+        </p>
+    </p>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <div id="log"></div>
+    <div id="spacer"></div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        var originalWidth = 0;
+        var originalHeight = 0;
+        var originalInnerWidth = 0;
+
+        addManualTestStep(
+            function() {},
+            null,
+            '1. Ensure the browser is at the default pinch and browser zoom ' +
+            'levels (100%). Most browsers: ctrl+0');
+
+        addManualTestStep(
+            function() {
+                originalWidth = window.view.width;
+                originalHeight = window.view.height;
+                originalInnerWidth = window.innerWidth;
+
+                assert_equals(
+                    window.view.width,
+                    window.innerWidth - 20,
+                    "Custom scrollbar width subtracted from viewport.");
+                assert_equals(
+                    window.view.height,
+                    window.innerHeight - 25,
+                    "Custom scrollbar height subtracted from viewport.");
+            },
+            'No zoom or scale applied',
+            '2. Browser-zoom into 200% (ctrl +)');
+
+        addManualTestStep(
+            function() {
+                // Ensure we zoomed in to about what we expect.
+                assert_approx_equals(
+                    originalInnerWidth / window.innerWidth,
+                    2.0,
+                    0.1,
+                    "Browser zoom to correct level");
+
+                assert_equals(
+                    window.view.width,
+                    window.innerWidth - 20,
+                    "Custom scrollbar width subtracted from viewport.");
+                assert_equals(
+                    window.view.height,
+                    window.innerHeight - 25,
+                    "Custom scrollbar height subtracted from viewport.");
+            },
+            'With 200% browser zoom',
+            '3. Reset browser zoom (ctrl+0).');
+
+        addManualTestStep(
+            showPinchWidget.bind(null, 2.0, 0, 0, continueTest),
+            null,
+            'Pinch-zoom dialog in progress');
+
+        addManualTestStep(
+            function() {
+                assert_approx_equals(
+                    window.view.scale, 2, 0.2, "Pinch zoom to correct scale");
+
+                // Scrollbars do not grow with pinch-zoom so they take up fewer
+                // CSS pixels as you zoom in.
+                assert_approx_equals(
+                    window.view.width,
+                    originalWidth / window.view.scale,
+                    1,
+                    "Custom scrollbar width subtracted from viewport.");
+                assert_approx_equals(
+                    window.view.height,
+                    originalHeight / window.view.scale,
+                    1,
+                    "Custom scrollbar width subtracted from viewport.");
+            },
+            'With ~200% pinch zoom',
+            '4. Pinch-zoom out.');
+
+        addManualTestStep(
+            function() { continueBtn.remove(); },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-scrollbars-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-scrollbars-manual.html
new file mode 100644
index 0000000..078efc7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-scrollbars-manual.html
@@ -0,0 +1,132 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Dimensions with scrollbars</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_done: true, explicit_timeout: true});
+        </script>
+        <style>
+          #spacer {
+            width: 10000px;
+            height: 10000px;
+            position: absolute;
+            visibility: hidden;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Dimensions with scrollbars</h1>
+    <h4>
+        Test Description: Tests the viewport dimensions correctly account for
+        scrollbars
+    </h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip Test</button>
+        <p>
+            If your browser doesn't support browser-zoom (Ctrl+/-, e.g. Mobile
+            Browsers) please skip.
+        </p>
+    </p>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <div id="log"></div>
+    <div id="spacer"></div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+        var scrollbarThickness = calculateScrollbarThickness();
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        var originalWidth = 0;
+        var originalHeight = 0;
+        var originalInnerWidth = 0;
+
+        addManualTestStep(
+            function() {},
+            null,
+            '1. Ensure the browser is at the default pinch and browser zoom ' +
+            'levels (100%). Most browsers: ctrl+0');
+
+        addManualTestStep(
+            function() {
+                originalWidth = window.view.width;
+                originalHeight = window.view.height;
+                originalInnerWidth = window.innerWidth;
+
+                assert_equals(
+                    window.view.width,
+                    window.innerWidth - scrollbarThickness,
+                    "Scrollbar width subtracted from viewport.");
+                assert_equals(
+                    window.view.height,
+                    window.innerHeight - scrollbarThickness,
+                    "Scrollbar height subtracted from viewport.");
+            },
+            'No zoom or scale applied',
+            '2. Browser-zoom into 200% (ctrl +)');
+
+        addManualTestStep(
+            function() {
+                assert_approx_equals(
+                    originalInnerWidth / window.innerWidth,
+                    2.0,
+                    0.1,
+                    "Browser zoom to correct level");
+
+                // Scrollbars on the window don't grow with browser-zoom so
+                // they'll be fewer CSS pixels as the user zooms in.
+                assert_equals(
+                    window.view.width,
+                    window.innerWidth - scrollbarThickness / 2,
+                    "Scrollbar width subtracted from viewport.");
+                assert_equals(
+                    window.view.height,
+                    window.innerHeight - scrollbarThickness / 2,
+                    "Scrollbar height subtracted from viewport.");
+            },
+            'With 200% browser zoom',
+            '3. Reset browser zoom (ctrl+0).');
+
+        addManualTestStep(
+            showPinchWidget.bind(null, 2.0, 0, 0, continueTest),
+            null,
+            'Pinch-zoom dialog in progress');
+
+        addManualTestStep(
+            function() {
+                assert_approx_equals(
+                    window.view.scale, 2, 0.2, "Pinch zoom to correct scale");
+
+                assert_approx_equals(window.view.width,
+                              originalWidth / window.view.scale,
+                              1,
+                              "Scrollbar width subtracted from viewport.");
+                assert_approx_equals(window.view.height,
+                              originalHeight / window.view.scale,
+                              1,
+                              "Scrollbar width subtracted from viewport.");
+            },
+            'With ~200% pinch zoom',
+            '4. Pinch-zoom out.');
+
+        addManualTestStep(
+            function() { continueBtn.remove(); },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-offset-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-offset-manual.html
new file mode 100644
index 0000000..67d41d6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-offset-manual.html
@@ -0,0 +1,151 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Offset</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_done: true, explicit_timeout: true});
+        </script>
+        <style>
+          html {
+            width: 100%;
+            height: 100%;
+          }
+          #fullscreenBox {
+            position: fixed;
+            left: 0;
+            top: 0;
+            width: 100%;
+            height: 100%;
+            visibility: hidden;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Offset</h1>
+    <h4>
+        Test Description: Tests the offset scrolling properties on an
+        unscrollable page.
+    </h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip Test</button>
+    </p>
+    <h4>Instruction</h4>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <div id="log"></div>
+    <div id="fullscreenBox">
+      <!-- Invisible but needed to get maximum scrollable extents in the
+           presence of a collapsible URL bar. -->
+    </div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        // Prevent scrolling (though there should be no overflow) so that all
+        // scrolling must happen as panning the visual viewport within the
+        // layout viewport.
+        document.documentElement.style.overflow = "hidden";
+
+        addManualTestStep(
+            function() {},
+            null,
+            '1. Ensure the browser is at the default pinch and browser zoom ' +
+            'levels (100%). Most browsers: ctrl+0');
+
+        var scale = 3.0;
+        var xTarget =  2 * window.innerWidth / scale;
+        var yTarget =  2 * window.innerHeight / scale;
+        addManualTestStep(
+            showPinchWidget.bind(null, scale, xTarget, yTarget, continueTest),
+            null,
+            '2.Follow instructions on pinch zoom dialog.');
+
+        addManualTestStep(
+            function() {
+                var actualScale = window.view.scale;
+                var actualOffsetLeft = window.view.offsetLeft;
+                var actualOffsetTop = window.view.offsetTop;
+
+                // This needs to happen before assertions in case they fail. A
+                // failed assertion stops running this function.
+                window.scrollTo(0, 0);
+
+                // Ensure we zoomed in to about what we expect.
+                assert_approx_equals(actualScale, scale, 0.2,
+                    "window.view.scale reflects pinch-zoom level");
+                assert_approx_equals(actualOffsetLeft, xTarget, 5,
+                    "offsetLeft value is correct.");
+                assert_approx_equals(actualOffsetTop, yTarget, 5,
+                    "offsetTop value is correct.");
+            },
+            'With ~300% pinch-zoom',
+            '3. Pinch-zoom back out to the minimum scale');
+
+        addManualTestStep(
+            showPinchWidget.bind(null, 2, 0, 0, continueTest),
+            null,
+            '4.Follow instructions on pinch zoom dialog.');
+
+        addManualTestStep(
+            function() {
+              document.documentElement.style.overflow = "";
+              continueBtn.style.position = "absolute";
+              continueBtn.style.left = "150%";
+              continueBtn.style.top = "150%";
+
+              assert_approx_equals(window.view.scale, 2, 0.2,
+                  "window.view.scale reflects pinch-zoom level");
+            },
+            'Tester pinch zoomed in correctly',
+            '5. Scroll fully to the bottom right. Click the continue button ' +
+            'there.');
+
+        addManualTestStep(
+            function() {
+              var fullscreenBox = document.getElementById('fullscreenBox');
+              var expectedLeft = fullscreenBox.clientWidth / 2;
+              var expectedTop = fullscreenBox.clientHeight / 2;
+              var viewOffsetLeft = window.view.offsetLeft;
+              var viewOffsetTop = window.view.offsetTop;
+
+              // This needs to happen before assertions in case they fail. A
+              // failed assertion stops running this function.
+              continueBtn.style.position = "";
+              continueBtn.style.left = "";
+              continueBtn.style.top = "";
+
+              window.scrollTo(0, 0);
+
+              assert_approx_equals(viewOffsetLeft, expectedLeft, 10,
+                  "OffsetLeft is correct");
+              assert_approx_equals(viewOffsetTop, expectedTop, 10,
+                  "OffsetTop");
+            },
+            'OffsetLeft and OffsetTop correct when there\'s some layout ' +
+            'viewport scrolling as well.',
+            '6. Pinch-zoom out fully');
+
+        addManualTestStep(
+            function() {
+                continueBtn.remove();
+            },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-page-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-page-manual.html
new file mode 100644
index 0000000..00f8cca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-page-manual.html
@@ -0,0 +1,108 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Page</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_done: true, explicit_timeout: true});
+        </script>
+        <style>
+          html {
+            width: 100%;
+            height: 100%;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Page</h1>
+    <h4>
+        Test Description: Tests the page scrolling properties.
+    </h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip Test</button>
+    </p>
+    <h4>Instruction</h4>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <div id="log"></div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+        var icbWidth = 0;
+        var icbHeight = 0;
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        addManualTestStep(
+            function() {},
+            null,
+            '1. Ensure the browser is at the default pinch and browser zoom ' +
+            'levels (100%). Most browsers: ctrl+0');
+
+        addManualTestStep(
+            showPinchWidget.bind(null, 1.5, 0, 0, continueTest),
+            null,
+            '2.Follow instructions on pinch zoom dialog.');
+
+        addManualTestStep(
+            function() {
+              continueBtn.style.position = "absolute";
+              continueBtn.style.left = "400%";
+              continueBtn.style.top = "400%";
+
+              assert_approx_equals(window.view.scale, 1.5, 0.2,
+                  "window.view.scale reflects pinch-zoom level");
+            },
+            'Tester pinch zoomed in correctly',
+            '3. Scroll fully to the bottom right. Click the continue button there.');
+
+        addManualTestStep(
+            function() {
+              var expectedLeft =
+                  document.documentElement.clientWidth * 4 +
+                  continueBtn.clientWidth -
+                  window.view.width;
+              var expectedTop =
+                  document.documentElement.clientHeight * 4 +
+                  continueBtn.clientHeight -
+                  window.view.height;
+              var viewPageLeft = window.view.pageLeft;
+              var viewPageTop = window.view.pageTop;
+
+              // This needs to happen before assertions in case they fail. A
+              // failed assertion stops running this function.
+              continueBtn.style.position = "";
+              continueBtn.style.left = "";
+              continueBtn.style.top = "";
+
+              window.scrollTo(0, 0);
+
+              assert_approx_equals(viewPageLeft, expectedLeft, 10,
+                  "window.view.scale reflects pinch-zoom level");
+              assert_approx_equals(viewPageTop, expectedTop, 10,
+                  "window.view.scale reflects pinch-zoom level");
+            },
+            'PageLeft and PageTop correct when scrolled',
+            '4. Pinch-zoom out fully');
+
+        addManualTestStep(
+            function() {
+                continueBtn.remove();
+            },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-causes-layout.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-causes-layout.html
new file mode 100644
index 0000000..21d9a910
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-causes-layout.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+  html {
+    height: 100%;
+  }
+</style>
+
+<h4>This test checks that requesting the viewport size causes any pending layout to occur.</h4>
+<script>
+  async_test(function(t) {
+    window.onload = t.step_func(function() {
+      assert_equals(window.view.width, document.documentElement.clientWidth,
+          "window.view.width should match the window width.");
+      assert_equals(view.height, document.documentElement.clientHeight,
+          "window.view.height should match the window height.");
+
+      // Add overflow so scrollbars appear.
+      document.body.style.width = "2000px";
+      document.body.style.height = "2000px";
+
+      var viewportWidth = window.view.width;
+      var viewportHeight = window.view.height;
+
+      assert_equals(viewportWidth, document.documentElement.clientWidth,
+          "Reading viewport width should cause a layout and exclude the new scrollbar.");
+      assert_equals(viewportHeight, document.documentElement.clientHeight,
+          "Reading viewport height should cause a layout and exclude the new scrollbar.");
+      t.done();
+    });
+  });
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-in-iframe-causes-layout.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-in-iframe-causes-layout.html
new file mode 100644
index 0000000..63cb005
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-in-iframe-causes-layout.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+  iframe {
+    width: 200px;
+    height: 300px;
+  }
+</style>
+
+<h4>This test checks that requesting the viewport size in an iframe causes any pending layout to occur.</h4>
+<iframe srcdoc="<!DOCTYPE html><style>html{height:100%}</style>"></iframe>
+<script>
+  async_test(function(t) {
+    window.onload = t.step_func(function() {
+      assert_equals(frames[0].window.view.width, 200,
+          "Reading width of iframe viewport should match iframe width.");
+      assert_equals(frames[0].window.view.height, 300,
+          "Reading height of iframe viewport should match iframe height.");
+
+      // Add overflow so scrollbars appear.
+      window.frames[0].window.document.body.style.width = "2000px";
+      window.frames[0].window.document.body.style.height = "2000px";
+
+      var viewportWidth = frames[0].window.view.width;
+      var viewportHeight = frames[0].window.view.height;
+
+      assert_equals(viewportWidth, frames[0].window.document.documentElement.clientWidth,
+          "Reading width of iframe viewport should cause a layout and exclude the new scrollbar.");
+      assert_equals(viewportHeight, frames[0].window.document.documentElement.clientHeight,
+          "Reading height of iframe viewport should cause a layout and exclude the new scrollbar.");
+      t.done();
+    });
+  });
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-resize-event-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-resize-event-manual.html
new file mode 100644
index 0000000..ba02e93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-resize-event-manual.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Window Resize Fires Event</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_timeout: true, explicit_done: true})
+        </script>
+    </head>
+    <body>
+    <h1>Viewport: Window Resize Fires Event</h1>
+    <h4>
+        Test Description: This test checks that a resize event is fired against
+        the window.view object when the browser window is resized.
+    </h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip Test</button>
+    </p>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <div id="log"></div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        var didResizeView;
+        var cancelable;
+        var bubbles;
+
+        function resetValues() {
+            didResizeView = false;
+            cancelable = undefined;
+            bubbles = undefined;
+        }
+
+        addManualTestStep(
+            function() {
+                resetValues();
+                window.view.addEventListener('resize', function(e) {
+                    didResizeView = true;
+                    cancelable = e.cancelable;
+                    bubbles = e.bubbles;
+                });
+            },
+            null,
+            '1. Resize the browser window (if on mobile, rotate the device)');
+
+
+        addManualTestStep(
+            function() {
+                assert_true(didResizeView);
+                assert_false(cancelable);
+                assert_false(bubbles);
+             },
+            'Resize event fired at window.view after window resized',
+            '2. Unrotate the device or reset window size if needed.');
+
+        addManualTestStep(
+            resetValues,
+            null,
+            '3. Pinch-zoom anywhere on the page by any amount.');
+
+        addManualTestStep(
+            function() {
+                assert_true(didResizeView);
+                assert_false(cancelable);
+                assert_false(bubbles);
+            },
+            'Pinch-zooming fires a resize event',
+            '4. Pinch-zoom back out');
+
+        addManualTestStep(
+            function() { continueBtn.remove(); },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-iframe-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-iframe-manual.html
new file mode 100644
index 0000000..29f1290
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-iframe-manual.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Scale iframe</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_done: true, explicit_timeout: true});
+        </script>
+        <style>
+          iframe {
+            width: 200px;
+            height: 200px;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Scale iframe</h1>
+    <h4>Test Description: Tests the view.scale property inside an iframe</h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip Test</button>
+    </p>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <p>
+        <iframe srcdoc="<!DOCTYPE html><style>html {background-color: coral;}</style>"></iframe>
+    </p>
+    <div id="log"></div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        addManualTestStep(
+            function() {},
+            null,
+            '1. Ensure the browser is at the default pinch and browser zoom ' +
+            'levels (100%). Most browsers: ctrl+0');
+
+        addManualTestStep(
+            showPinchWidget.bind(null, 2.0, 0, 0, continueTest),
+            null,
+            '2.Follow instructions on pinch zoom dialog.');
+
+        addManualTestStep(
+            function() {
+                // Ensure we zoomed in to about what we expect.
+                assert_approx_equals(window.view.scale, 2.0, 0.2,
+                    "Main window.view.scale reflects pinch-zoom level");
+
+                assert_equals(frames[0].window.view.scale, 1.0,
+                    "Iframe scale unchanged even when pinch-zoomed");
+            },
+            'Check iframe scale is unchanged when page is pinch-zoomed',
+            '3. Pinch-zoom back out to the minimum scale');
+
+        addManualTestStep(
+            function() {
+                continueBtn.remove();
+            },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-manual.html
new file mode 100644
index 0000000..6aaffcc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-manual.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Scale</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_done: true, explicit_timeout: true});
+        </script>
+    </head>
+    <body>
+    <h1>Viewport: Scale</h1>
+    <h4>Test Description: Tests the view.scale property</h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip Test</button>
+    </p>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <div id="log"></div>
+    <div id="spacer"></div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        addManualTestStep(
+            function() {},
+            null,
+            '1. Ensure the browser is at the default pinch and browser zoom ' +
+            'levels (100%). Most browsers: ctrl+0');
+
+        addManualTestStep(
+            showPinchWidget.bind(null, 2.0, 0, 0, continueTest),
+            null,
+            '2.Follow instructions on pinch zoom dialog.');
+
+        addManualTestStep(
+            function() {
+                // Ensure we zoomed in to about what we expect.
+                assert_approx_equals(window.view.scale, 2.0, 0.2,
+                    "window.view.scale reflects pinch-zoom level");
+            },
+            'With ~200% pinch-zoom',
+            '3. Pinch-zoom back out to the minimum scale');
+
+        addManualTestStep(
+            function() {
+                assert_equals(window.view.scale, 1);
+            },
+            'Fully pinch-zoomed out',
+            '4. If your browser supports it, browser-zoom in (using ctrl-+). ' +
+            'Otherwise just click continue.');
+
+        addManualTestStep(
+            function() {
+                assert_equals(window.view.scale, 1);
+            },
+            'Browser zoom doesn\'t change view.scale',
+            '5. Reset browser zoom to default (ctrl-0)');
+
+        addManualTestStep(
+            function() {
+                continueBtn.remove();
+            },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scroll-event-manual.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scroll-event-manual.html
new file mode 100644
index 0000000..3e286a6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scroll-event-manual.html
@@ -0,0 +1,182 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Scroll Event</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <script>
+           setup({explicit_timeout: true, explicit_done: true})
+        </script>
+        <style>
+          html {
+            width: 100%;
+            height: 100%;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Scroll Event</h1>
+    <h4>
+        Test Description: This test checks that a scroll event is fired against
+        the window.view object when the viewport is scrolled.
+    </h4>
+    <h2 style="color: red">THIS IS A MANUAL TEST</h2>
+    <p id="skip">
+        <button id="skipbtn" onclick="skipManualTest();">Skip Test</button>
+    </p>
+    <h4>Instruction</h4>
+    <p id="instruction"></p>
+    <button id="continue">Start Test</button>
+    <div id="log"></div>
+    </body>
+    <script>
+        var continueBtn = document.getElementById("continue");
+
+        function continueTest() {
+          nextStep(function(instructionText) {
+            var instruction = document.getElementById("instruction");
+            continueBtn.innerText = "Continue";
+            instruction.innerText = instructionText;
+          });
+        }
+
+        continueBtn.addEventListener('click', continueTest);
+
+        var didGetScrollEvent = false;
+        var cancelable = undefined;
+        var bubbles = undefined;
+
+        function resetValues() {
+            didGetScrollEvent = false;
+            cancelable = undefined;
+            bubbles = undefined;
+        }
+
+        addManualTestStep(
+            function() {
+                window.view.addEventListener('scroll', function(e) {
+                    didGetScrollEvent = true;
+                    cancelable = e.cancelable;
+                    bubbles = e.bubbles;
+                });
+                document.documentElement.style.overflow = "hidden";
+            },
+            null,
+            '1. Pinch-zoom a little near the "Continue" button but don\'t ' +
+            'perform any scrolling.');
+
+        addManualTestStep(
+            function() {
+                requestAnimationFrame(continueTest);
+                assert_true(didGetScrollEvent, "Got event");
+                assert_false(cancelable, "Event is not cancelable");
+                assert_false(bubbles, "Event does not bubble");
+             },
+            'Got scroll event while pinch-zooming',
+            '');
+
+        addManualTestStep(
+            resetValues,
+            null,
+            '2. Scroll in any direction.');
+
+        addManualTestStep(
+            function() {
+                requestAnimationFrame(continueTest);
+                assert_true(didGetScrollEvent, "Got event");
+                assert_false(cancelable, "Event is not cancelable");
+                assert_false(bubbles, "Event does not bubble");
+            },
+            'Panning viewport fires a scroll event',
+            '');
+
+        addManualTestStep(
+            function() {
+                continueBtn.style.position = "absolute";
+                continueBtn.style.right = "10px";
+                continueBtn.style.bottom = "10px";
+            },
+            null,
+            '3. Scroll fully to the bottom right and click the continue ' +
+            'button.');
+
+        var offsetLeft;
+        var offsetTop;
+        addManualTestStep(
+            function() {
+                resetValues();
+                document.documentElement.style.overflow = "";
+                document.body.style.width = "500%";
+                document.body.style.height = "500%";
+                continueBtn.style.position = "";
+                continueBtn.style.left = "";
+                continueBtn.style.top = "";
+
+                offsetLeft = window.view.offsetLeft;
+                offsetTop = window.view.offsetTop;
+
+                // The visual viewport should be fully scrolled so even if
+                // scrollTo does normally "push" the layout viewport with the
+                // visual, there should be no change to either offsetValue
+                window.scrollTo(10000, 10000);
+
+                requestAnimationFrame(continueTest);
+                assert_equals(window.view.offsetLeft, offsetLeft,
+                    "OffsetLeft Unchanged");
+                assert_equals(window.view.offsetTop, offsetTop,
+                    "OffsetTop Unchanged");
+                assert_false(didGetScrollEvent,
+                    "Should not get view scroll event");
+            },
+            'scrollTo down and right on a fully scrolled visual viewport ' +
+            'shouldn\'t change offsets',
+            '');
+
+        addManualTestStep(
+            function() {
+                requestAnimationFrame(continueTest);
+                assert_false(didGetScrollEvent,
+                    "Should not get view scroll event");
+                resetValues();
+            },
+            'scrollTo without changing offsets shouldn\'t fire scroll event ' +
+            'on view',
+            '');
+
+        addManualTestStep(
+            function() {
+              requestAnimationFrame(continueTest);
+              resetValues();
+              window.scrollTo(0, 0);
+            },
+            null,
+            '');
+
+        addManualTestStep(
+            function() {
+                // How scrollTo behaves in this case isn't fully spec'd but
+                // make sure it's at least rational if it does change the
+                // offset values.
+                var scrollChangedOffset =
+                  offsetLeft != window.view.offsetLeft ||
+                  offsetTop != window.view.offsetTop;
+
+                document.body.style.width = "";
+                document.body.style.height = "";
+
+                assert_equals(didGetScrollEvent, scrollChangedOffset,
+                    'If the scrollTo changed offsets it must have fired a ' +
+                    'scroll event');
+            },
+            'scrollTo must fire scroll event if it changes view.offsetLeft|Top',
+            '6. Pinch-zoom out fully');
+
+        addManualTestStep(
+            function() { continueBtn.remove(); },
+            null,
+            'Test Complete');
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scrollbars-cause-resize.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scrollbars-cause-resize.html
new file mode 100644
index 0000000..ec3e9ee
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scrollbars-cause-resize.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Scrollbars Cause Resize</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+    </head>
+    <body>
+    <h1>Viewport: Scrollbars Cause Resize</h1>
+    <h4>
+        Test Description: This test checks that the appearance of classic
+        scrollbars will cause a resize event to be fired at window.view.
+    </h4>
+    <script>
+      function runTest() {
+        var scrollbarThickness = calculateScrollbarThickness();
+
+        document.documentElement.style.overflow = "hidden";
+        var initialWidth = view.width;
+        var initialHeight = view.height;
+
+        test(function() {
+              assert_equals(window.view.width, window.innerWidth);
+              assert_equals(window.view.height, window.innerHeight);
+            }, "view size initially matches window size");
+
+
+        var t = async_test(
+            "Resize event was fired at window.view if, and only if, " +
+            "scrollbars are classic (i.e. affect flow)");
+        var viewResized = false;
+        window.view.addEventListener('resize', function() {
+            viewResized = true;
+        });
+
+        requestAnimationFrame(t.step_func_done(function() {
+            assert_equals(viewResized, scrollbarThickness > 0);
+        }));
+
+        document.documentElement.style.overflow = "";
+        document.body.style.width = "10000px";
+        document.body.style.height = "10000px";
+
+        var expectedWidth = initialWidth - scrollbarThickness;
+        var expectedHeight = initialHeight - scrollbarThickness;
+
+        test(function() {
+              assert_equals(window.view.width, expectedWidth);
+              assert_equals(window.view.height, expectedHeight);
+            }, "view size reflects appearance of classic scrollbars");
+
+
+        document.body.style.width = "";
+        document.body.style.height = "";
+      }
+
+      // Run the test after load to make sure any resize from a previous test
+      // doesn't interfere.
+      window.onload = runTest;
+    </script>
+    <div id="log"></div>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-type.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-type.html
new file mode 100644
index 0000000..77e4354
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-type.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: window.view type</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+    </head>
+    <body>
+    <h1>Viewport: window.view type</h1>
+    <h4>Test Description: This test checks that window.view is an object of type VisualViewport.</h4>
+    <script>
+        test(function() {
+              assert_equals(typeof(window.view), "object");
+            }, "window.view is an object");
+
+        test(function() {
+              assert_equals(window.view.toString(), "[object VisualViewport]");
+            }, "window.view has type `VisualViewport`");
+
+        addEventListener("load", function() {
+            document.getElementById("viewtype-log").innerText = typeof(window.view);
+        });
+    </script>
+    <div id="complete-notice">
+        <p>window.view is of type: <span id="viewtype-log"></span>.</p>
+    </div>
+    <div id="log"></div>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale-iframe.html
new file mode 100644
index 0000000..72835d72
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale-iframe.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Unscaled scale iframe</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <style>
+            iframe {
+              width: 200px;
+              height: 300px;
+            }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Unscaled scale iframe</h1>
+    <h4>Test Description: This test checks that the default value for scale inside an iframe is 1.</h4>
+    <iframe></iframe>
+    <div id="complete-notice">
+        <p>iframe's window.view.scale is <span id="view-scale-log"></span>.</p>
+    </div>
+    <div id="log"></div>
+    </body>
+    <script>
+        test(function() {
+              assert_equals(frames[0].window.view.scale, 1);
+            }, "iframe's view.scale default value.");
+
+        document.getElementById("view-scale-log").innerText = frames[0].window.view.scale;
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale.html
new file mode 100644
index 0000000..41e7928
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Unscaled scale</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+    </head>
+    <body>
+    <h1>Viewport: Unscaled scale</h1>
+    <h4>Test Description: This test checks that the default value for scale is 1.</h4>
+    <div id="complete-notice">
+        <p>window.view.scale is <span id="view-scale-log"></span>.</p>
+    </div>
+    <div id="log"></div>
+    </body>
+    <script>
+        test(function() {
+              assert_equals(window.view.scale, 1);
+            }, "view.scale default value.");
+
+        document.getElementById("view-scale-log").innerText = window.view.scale;
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll-iframe.html
new file mode 100644
index 0000000..c7f7b2c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll-iframe.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Scroll in iframe - no page scale</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <style>
+          iframe {
+            width: 200px;
+            height: 300px;
+            border: 0;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Scroll in iframe - no page scale</h1>
+    <h4>Test Description: This test checks that window.view returns correct offset and scroll values without any pinch-zoom page scale applied.</h4>
+    <iframe></iframe>
+    <div id="complete-notice">
+        <p>frames[0].window.view's offsetLeft and offsetTop is (<span id="scroll-offset-log"></span>).</p>
+        <p>frames[0].window.view's pageLeft and pageTop is (<span id="scroll-page-log"></span>).</p>
+    </div>
+    <div id="log"></div>
+    </body>
+    <script>
+        var iframe = frames[0].window;
+
+        // Add overflow we can scroll.
+        iframe.document.body.style.width = "2000px";
+        iframe.document.body.style.height = "2000px";
+
+        iframe.scrollTo(1000, 1200);
+
+
+        test(function() {
+              assert_equals(iframe.view.offsetLeft, 0);
+            }, "offsetLeft must be 0.");
+        test(function() {
+              assert_equals(iframe.view.offsetTop, 0);
+            }, "offsetTop must be 0.");
+        test(function() {
+              assert_equals(iframe.view.pageLeft, 1000);
+            }, "pageLeft must reflect location of viewport in document.");
+        test(function() {
+              assert_equals(iframe.view.pageTop, 1200);
+            }, "pageTop must reflect location of viewport in document.");
+
+        document.getElementById("scroll-offset-log").innerText = iframe.view.offsetLeft+ ", " + iframe.view.offsetTop;
+        document.getElementById("scroll-page-log").innerText = iframe.view.pageLeft + ", " + iframe.view.pageTop;
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll.html
new file mode 100644
index 0000000..359713df
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Scroll - no page scale</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+    </head>
+    <body>
+    <h1>Viewport: Scroll - no page scale</h1>
+    <h4>Test Description: This test checks that window.view returns correct offset and scroll values without any pinch-zoom page scale applied.</h4>
+    <div id="complete-notice">
+        <p>window.view's offsetLeft and offsetTop is (<span id="scroll-offset-log"></span>).</p>
+        <p>window.view's pageLeft and pageTop is (<span id="scroll-page-log"></span>).</p>
+    </div>
+    <div id="log"></div>
+    </body>
+    <script>
+        // Add overflow we can scroll.
+        document.body.style.width = "5000px";
+        document.body.style.height = "5000px";
+
+        scrollTo(1000, 1200);
+
+        test(function() {
+              assert_equals(window.view.offsetLeft, 0);
+            }, "offsetLeft must be 0.");
+        test(function() {
+              assert_equals(window.view.offsetTop, 0);
+            }, "offsetTop must be 0.");
+        test(function() {
+              assert_equals(window.view.pageLeft, 1000);
+            }, "pageLeft must reflect location of viewport in document.");
+        test(function() {
+              assert_equals(window.view.pageTop, 1200);
+            }, "pageTop must reflect location of viewport in document.");
+
+        document.getElementById("scroll-offset-log").innerText = window.view.offsetLeft+ ", " + window.view.offsetTop;
+        document.getElementById("scroll-page-log").innerText = window.view.pageLeft + ", " + window.view.pageTop;
+
+        scrollTo(0, 0);
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size-iframe.html
new file mode 100644
index 0000000..de7a591
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size-iframe.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Size in iframe - no page scale</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <style>
+          iframe {
+            width: 200px;
+            height: 300px;
+            border: 0;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Size in iframe - no page scale</h1>
+    <h4>Test Description: This test checks that window.view returns correct sizes without any pinch-zoom page scale applied but with scrollbars.</h4>
+    <iframe></iframe>
+    <div id="complete-notice">
+        <p>frames[0].window.view width and height is (<span id="size-log"></span>).</p>
+        <p>frames[0].window.view width and height when scrollbars are present is (<span id="size-scrollbars-log"></span>).</p>
+    </div>
+    <div id="log"></div>
+    </body>
+    <script>
+        var scrollbarThickness = calculateScrollbarThickness();
+
+        test(function() {
+              assert_equals(frames[0].window.view.width, 200);
+            }, "window.view.width of iframe viewport should match iframe width.");
+        test(function() {
+              assert_equals(frames[0].window.view.height, 300);
+            }, "window.view.height of iframe viewport should match iframe height.");
+
+        document.getElementById("size-log").innerText = frames[0].window.view.width + ", " + frames[0].window.view.height;
+
+        // Add overflow so scrollbars appear.
+        window.frames[0].window.document.body.style.width = "2000px";
+        window.frames[0].window.document.body.style.height = "2000px";
+
+        test(function() {
+              assert_equals(frames[0].window.view.width, 200 - scrollbarThickness);
+            }, "window.view.width of iframe viewport should not include scrollbar.");
+        test(function() {
+              assert_equals(frames[0].window.view.height, 300 - scrollbarThickness);
+            }, "window.view.height of iframe viewport should not include scrollbar.");
+
+        document.getElementById("size-scrollbars-log").innerText = frames[0].window.view.width + ", " + frames[0].window.view.height;
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size.html b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size.html
new file mode 100644
index 0000000..4100995
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Viewport: Size unscaled</title>
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, minimum-scale=1">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="viewport_support.js"></script>
+        <style>
+          html {
+            width: 100%;
+            height: 100%;
+          }
+        </style>
+    </head>
+    <body>
+    <h1>Viewport: Size unscaled</h1>
+    <h4>Test Description: This test checks that window.view returns correct sizes without any pinch-zoom page scale applied.</h4>
+    <div id="complete-notice">
+        <p>window.view width and height is (<span id="view-size-log"></span>).</p>
+        <p>window.view width and height when scrollbars are present is (<span id="view-size-scrollbar-log"></span>).</p>
+    </div>
+    <div id="log"></div>
+    </body>
+    <script>
+        var scrollbarThickness = calculateScrollbarThickness();
+
+        test(function() {
+              assert_equals(window.view.width, document.documentElement.clientWidth);
+            }, "view.width should match documentElement.clientWidth when unzoomed.");
+        test(function() {
+              assert_equals(window.view.height, document.documentElement.clientHeight);
+            }, "view.height should match documentElement.clientHeight when unzoomed.");
+
+        document.getElementById("view-size-log").innerText = window.view.width + ", " + window.view.height;
+
+        // Add overflow so scrollbars appear.
+        document.body.style.width = "2000px";
+        document.body.style.height = "2000px";
+
+        test(function() {
+              assert_equals(window.view.width, document.documentElement.clientWidth);
+            }, "view.width should exclude scrollbar.");
+        test(function() {
+              assert_equals(window.view.height, document.documentElement.clientHeight);
+            }, "view.height should exclude scrollbar.");
+
+        document.getElementById("view-size-scrollbar-log").innerText = window.view.width + ", " + window.view.height;
+    </script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport_support.js b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport_support.js
new file mode 100644
index 0000000..5cea91a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport_support.js
@@ -0,0 +1,153 @@
+// If scrollbars affect layout (i.e. what the CSS Overflow spec calls "classic
+// scrollbars", as opposed to overlay scrollbars), return the scrollbar
+// thickness in CSS pixels. Returns 0 otherwise.
+function calculateScrollbarThickness() {
+    var container = document.createElement("div");
+    container.style.width = "100px";
+    container.style.height = "100px";
+    container.style.position = "absolute";
+    container.style.visibility = "hidden";
+    container.style.overflow = "auto";
+
+    document.body.appendChild(container);
+
+    var widthBefore = container.clientWidth;
+    var longContent = document.createElement("div");
+    longContent.style.height = "1000px";
+    container.appendChild(longContent);
+
+    var widthAfter = container.clientWidth;
+
+    container.remove();
+
+    return widthBefore - widthAfter;
+}
+
+// Puts up a widget on screen instructing the user to pinch-zoom in to the
+// given scale. The widget is sized such that the given scale is achieved. The
+// widget is placed at (x, y) on the page. A button on the widget is used by
+// the user to let the widget know that the user has finished. If a callback is
+// provided, it will be called when the user dismisses the widget.
+function showPinchWidget(scale, x, y, callback) {
+    var border = 10;
+    var width = window.innerWidth / scale - border;
+    var height = window.innerHeight / scale - border;
+
+    var box = document.createElement("div");
+    box.style.width = width + "px";
+    box.style.height = height + "px";
+
+    // Adjust the x/y coordinates by the border width. We want the box to
+    // appear in a place such that if the user gets the window edges exactly on
+    // the half-point of the border they end up at x/y
+    box.style.left = x - border/2 + "px";
+    box.style.top = y - border/2 + "px";
+
+    box.style.position = "absolute";
+    box.style.backgroundColor = "coral";
+    box.style.border = border + "px solid blue";
+    box.style.borderBottom = "0";
+    box.style.overflow = "auto";
+
+    var oldDocumentOverflow = document.documentElement.style.overflow;
+
+    var instructions = document.createElement("p");
+    instructions.innerText =
+        "Pinch-zoom and align this box so that the left, right, and top " +
+        "window edges are over the border on each side. When done, click the " +
+        "'DONE' button above";
+    instructions.style.textAlign = "center";
+    instructions.style.fontSize = "medium";
+
+    var button = document.createElement("button");
+    button.innerText = "DONE";
+    button.style.width = "50%";
+    button.style.height = "20%";
+    button.style.fontSize = "medium";
+    button.style.marginLeft = "25%";
+    button.addEventListener("click", function() {
+        box.remove();
+        document.documentElement.style.overflow = oldDocumentOverflow;
+        if (callback)
+            callback();
+    });
+
+    box.appendChild(button);
+    box.appendChild(instructions);
+
+    document.documentElement.style.overflow = "hidden";
+
+    document.body.appendChild(box);
+}
+
+// Ends a manual test. Must be called before any async tests are started.
+function skipManualTest() {
+    test(function() { assert_true(false); }, "Manual Test Skipped");
+    done();
+}
+
+var stepInstructions = [];
+var testNames = [];
+var stepFunctions = [];
+var steps;
+var curStep = 0;
+
+// Adds a manual test step to the test. A test will add a series of steps,
+// along with instructions.  Once all the tests steps are added, the test can
+// be run by continually running the nextStep() function. All manual test steps
+// must be added before calling nextStep.
+//
+// |func| A function to be executed at the given step. This function can include
+//        testharness assertions if |testName| is provided. If this is the last
+//        step, the |done()| function (used for manual testharness.js tests)
+//        will be called after |func| is executed.
+// |testName| If provided, the |func| will be wrapped in a testharness.js
+//            async_test with this name. If null, |func| will be executed as a
+//            free function.
+// |instructions| The text to display to the user. Note, these are shown after
+//                step is executed so these should be instructions to setup the
+//                checks in the next step.
+function addManualTestStep(func, testName, instructions) {
+    stepFunctions.push(func);
+    testNames.push(testName);
+    stepInstructions.push(instructions);
+}
+
+// Runs the next step of the test. This must be called only after all test steps
+// have been added using |addManualTestStep|.
+//
+// |callbackFunc| If provided, will be called with a single argument being the
+//                instruction string for the current step. Use this to update
+//                any necessary UI.
+function nextStep(callbackFunc) {
+    if (curStep == 0)
+      _startManualTest();
+
+    if (typeof(callbackFunc) === 'function')
+        callbackFunc(stepInstructions[curStep]);
+
+    steps[curStep]();
+    curStep++;
+}
+
+function _startManualTest() {
+    steps = [];
+    for (let i = 0; i < stepFunctions.length; ++i) {
+        var stepFunc = stepFunctions[i];
+        var testName = testNames[i];
+        if (testName) {
+            steps.push(async_test(testName).step_func(function() {
+                stepFunctions[i]();
+                this.done();
+                if (i == stepFunctions.length - 1)
+                    done();
+            }));
+        } else {
+            steps.push(function() {
+                stepFunctions[i]();
+                if (i == stepFunctions.length - 1)
+                    done();
+            });
+        }
+    }
+}
diff --git a/third_party/WebKit/LayoutTests/mojo/module-loading-manual-deps-loading.html b/third_party/WebKit/LayoutTests/mojo/module-loading-manual-deps-loading.html
index 668bba9..fc92d3f0 100644
--- a/third_party/WebKit/LayoutTests/mojo/module-loading-manual-deps-loading.html
+++ b/third_party/WebKit/LayoutTests/mojo/module-loading-manual-deps-loading.html
@@ -7,7 +7,7 @@
   mojo.config.autoLoadMojomDeps = false;
 </script>
 <script src="file:///gen/mojo/public/interfaces/bindings/tests/echo.mojom.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/echo_import.mojom.js"></script>
+<script src="file:///gen/mojo/public/interfaces/bindings/tests/echo_import/echo_import.mojom.js"></script>
 <script>
 
 promise_test(async () => {
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
index d78ce9a..29613cd 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
index d78ce9a..29613cd 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
index eb1f211f4..70bf067 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
index 9ead785..e519e09 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
index 9ead785..e519e09 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
index b0e53a8..70bf067 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
index 68c224d..5c9755b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
index 68c224d..5c9755b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
index 95b3dd1..49a8fbf 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 2a505e4..a4cda06 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -685,11 +685,13 @@
   DCHECK(IsInsideFlowThread());
 
   // See if we have the thread cached because we're in the middle of layout.
-  if (LayoutState* layout_state = View()->GetLayoutState()) {
-    // TODO(mstensho): We should really just return whatever
-    // layoutState->flowThread() returns here, also if the value is nullptr.
-    if (LayoutFlowThread* flow_thread = layout_state->FlowThread())
-      return flow_thread;
+  if (LayoutView* view = View()) {
+    if (LayoutState* layout_state = view->GetLayoutState()) {
+      // TODO(mstensho): We should really just return whatever
+      // layoutState->flowThread() returns here, also if the value is nullptr.
+      if (LayoutFlowThread* flow_thread = layout_state->FlowThread())
+        return flow_thread;
+    }
   }
 
   // Not in the middle of layout so have to find the thread the slow way.
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index a5c74dc..38a28a8 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -19,6 +19,7 @@
 #include "core/layout/ng/ng_constraint_space_builder.h"
 #include "core/layout/ng/ng_floats_utils.h"
 #include "core/layout/ng/ng_fragment_builder.h"
+#include "core/layout/ng/ng_layout_opportunity_iterator.h"
 #include "core/layout/ng/ng_layout_result.h"
 #include "core/layout/ng/ng_length_utils.h"
 #include "core/layout/ng/ng_space_utils.h"
@@ -49,37 +50,20 @@
       space_builder_(space) {
   container_builder_.MutableUnpositionedFloats() = space->UnpositionedFloats();
 
-  // TODO(crbug.com/716930): We may be an empty LayoutInline due to splitting.
-  // Only resolve our BFC offset if we know that we are non-empty as we may
-  // need to pass through our margin strut.
-  if (!inline_node.Items().IsEmpty()) {
-    LayoutUnit bfc_block_offset = ConstraintSpace().BfcOffset().block_offset;
-    bfc_block_offset += ConstraintSpace().MarginStrut().Sum();
-    MaybeUpdateFragmentBfcOffset(ConstraintSpace(), bfc_block_offset,
-                                 &container_builder_);
-    PositionPendingFloats(bfc_block_offset, &container_builder_,
-                          MutableConstraintSpace());
-  }
-
   if (!is_horizontal_writing_mode_)
     baseline_type_ = FontBaseline::kIdeographicBaseline;
 
   border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) +
                         ComputePadding(ConstraintSpace(), Style());
-
-  FindNextLayoutOpportunity();
-}
-
-LayoutUnit NGInlineLayoutAlgorithm::AvailableWidth() const {
-  return current_opportunity_.InlineSize();
 }
 
 // The offset of 'line-left' side.
 // https://drafts.csswg.org/css-writing-modes/#line-left
-LayoutUnit NGInlineLayoutAlgorithm::LogicalLeftOffset() const {
+LayoutUnit NGInlineLayoutAlgorithm::LogicalLeftOffset(
+    const NGLayoutOpportunity& opportunity) const {
   // TODO(kojii): We need to convert 'line start' to 'line left'. They're
   // different in RTL. Maybe there are more where start and left are misused.
-  return current_opportunity_.InlineStartOffset() -
+  return opportunity.InlineStartOffset() -
          ConstraintSpace().BfcOffset().inline_offset;
 }
 
@@ -92,12 +76,15 @@
   if (!PlaceItems(line_info, break_token))
     return false;
 
-  // Prepare for the next line.
-  NGLogicalOffset origin_point =
-      GetOriginPointForFloats(ContainerBfcOffset(), content_size_);
-  PositionPendingFloats(origin_point.block_offset, &container_builder_,
-                        MutableConstraintSpace());
-  FindNextLayoutOpportunity();
+  // If something has resolved our BFC offset we can place all of the
+  // unpositioned floats below the current line.
+  if (container_builder_.BfcOffset()) {
+    NGLogicalOffset origin_point =
+        GetOriginPointForFloats(ContainerBfcOffset(), content_size_);
+    PositionPendingFloats(origin_point.block_offset, &container_builder_,
+                          MutableConstraintSpace());
+  }
+
   return true;
 }
 
@@ -147,45 +134,6 @@
   line_items->swap(line_items_in_visual_order);
 }
 
-// TODO(glebl): Add the support of clearance for inline floats.
-void NGInlineLayoutAlgorithm::LayoutAndPositionFloat(
-    LayoutUnit end_position,
-    LayoutObject* layout_object) {
-  NGBlockNode node(ToLayoutBox(layout_object));
-
-  NGLogicalOffset origin_offset =
-      GetOriginPointForFloats(ContainerBfcOffset(), content_size_);
-  const ComputedStyle& float_style = node.Style();
-  NGBoxStrut margins = ComputeMargins(ConstraintSpace(), float_style,
-                                      ConstraintSpace().WritingMode(),
-                                      ConstraintSpace().Direction());
-
-  // TODO(ikilpatrick): Add support for float break tokens inside an inline
-  // layout context.
-  RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create(
-      current_opportunity_.size, ConstraintSpace().PercentageResolutionSize(),
-      origin_offset, ContainerBfcOffset(), margins, node,
-      /* break_token */ nullptr);
-  unpositioned_float->parent_bfc_block_offset =
-      ContainerBfcOffset().block_offset;
-
-  LayoutUnit inline_size = ComputeInlineSizeForUnpositionedFloat(
-      MutableConstraintSpace(), unpositioned_float.Get());
-
-  bool float_does_not_fit = end_position + inline_size + margins.InlineSum() >
-                            current_opportunity_.InlineSize();
-  // Check if we already have a pending float. That's because a float cannot be
-  // higher than any block or floated box generated before.
-  if (!container_builder_.UnpositionedFloats().IsEmpty() ||
-      float_does_not_fit) {
-    container_builder_.AddUnpositionedFloat(unpositioned_float);
-  } else {
-    container_builder_.AddPositionedFloat(
-        PositionFloat(unpositioned_float.Get(), MutableConstraintSpace()));
-    FindNextLayoutOpportunity();
-  }
-}
-
 bool NGInlineLayoutAlgorithm::PlaceItems(
     NGLineInfo* line_info,
     RefPtr<NGInlineBreakToken> break_token) {
@@ -295,12 +243,13 @@
   // the line box to the line top.
   line_box.MoveChildrenInBlockDirection(baseline);
 
+  NGLayoutOpportunity line_opp = FindLayoutOpportunityForLine();
+
   LayoutUnit inline_size = position;
-  NGLogicalOffset offset(LogicalLeftOffset(),
+  NGLogicalOffset offset(LogicalLeftOffset(line_opp),
                          baseline - box_states_.LineBoxState().metrics.ascent);
   ApplyTextAlign(line_style, line_style.GetTextAlign(line_info->IsLastLine()),
-                 &offset.inline_offset, inline_size,
-                 current_opportunity_.size.inline_size);
+                 &offset.inline_offset, inline_size, line_opp.InlineSize());
 
   line_box.SetInlineSize(inline_size);
   container_builder_.AddChild(line_box.ToLineBoxFragment(), offset);
@@ -383,18 +332,23 @@
   }
 }
 
-void NGInlineLayoutAlgorithm::FindNextLayoutOpportunity() {
+NGLayoutOpportunity NGInlineLayoutAlgorithm::FindLayoutOpportunityForLine() {
+  // TODO(ikilpatrick): Using the constraint space BFC offset here seems wrong.
+  // Logically we shouldn't hit this codepath when placing the items as we
+  // shouldn't have anything to place.
+  //
+  // Consider reworking PlaceItems to make sure this doesn't occur.
   NGLogicalOffset iter_offset = ConstraintSpace().BfcOffset();
   if (container_builder_.BfcOffset()) {
     iter_offset = ContainerBfcOffset();
-    iter_offset +=
-        {border_and_padding_.inline_start, border_and_padding_.block_start};
+    iter_offset += {border_and_padding_.inline_start, LayoutUnit()};
   }
   iter_offset.block_offset += content_size_;
-  auto* iter = MutableConstraintSpace()->LayoutOpportunityIterator(iter_offset);
-  NGLayoutOpportunity opportunity = iter->Next();
-  if (!opportunity.IsEmpty())
-    current_opportunity_ = opportunity;
+
+  return NGLayoutOpportunityIterator(ConstraintSpace().Exclusions().get(),
+                                     ConstraintSpace().AvailableSize(),
+                                     iter_offset)
+      .Next();
 }
 
 RefPtr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
@@ -402,9 +356,11 @@
   // within a previous fragment.
   content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start;
 
-  NGLineBreaker line_breaker(Node(), constraint_space_, BreakToken());
+  NGLineBreaker line_breaker(Node(), constraint_space_, &container_builder_,
+                             BreakToken());
   NGLineInfo line_info;
-  while (line_breaker.NextLine(&line_info, this))
+  while (line_breaker.NextLine(
+      &line_info, {border_and_padding_.inline_start, content_size_}))
     CreateLine(&line_info, line_breaker.CreateBreakToken());
 
   // TODO(crbug.com/716930): Avoid calculating border/padding twice.
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h
index 338d9a7..42dd4c4 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -14,6 +14,7 @@
 #include "core/layout/ng/ng_constraint_space_builder.h"
 #include "core/layout/ng/ng_fragment_builder.h"
 #include "core/layout/ng/ng_layout_algorithm.h"
+#include "core/layout/ng/ng_layout_opportunity_iterator.h"
 #include "platform/fonts/FontBaseline.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/Vector.h"
@@ -39,9 +40,6 @@
                           NGConstraintSpace*,
                           NGInlineBreakToken* = nullptr);
 
-  // The available width for the current line.
-  LayoutUnit AvailableWidth() const;
-
   // Create a line.
   // @return false if the line does not fit in the constraint space in block
   //         direction.
@@ -49,18 +47,10 @@
 
   RefPtr<NGLayoutResult> Layout() override;
 
-  // Lays out the inline float.
-  // List of actions:
-  // - tries to position the float right away if we have enough space.
-  // - updates the current_opportunity if we actually place the float.
-  // - if it's too wide then we add the float to the unpositioned list so it can
-  //   be positioned after we're done with the current line.
-  void LayoutAndPositionFloat(LayoutUnit end_position, LayoutObject*);
-
  private:
   bool IsHorizontalWritingMode() const { return is_horizontal_writing_mode_; }
 
-  LayoutUnit LogicalLeftOffset() const;
+  LayoutUnit LogicalLeftOffset(const NGLayoutOpportunity&) const;
 
   void BidiReorder(NGInlineItemResults*);
 
@@ -78,8 +68,7 @@
                       LayoutUnit inline_size,
                       LayoutUnit available_width);
 
-  // Finds the next layout opportunity for the next text fragment.
-  void FindNextLayoutOpportunity();
+  NGLayoutOpportunity FindLayoutOpportunityForLine();
 
   NGInlineLayoutStateStack box_states_;
   LayoutUnit content_size_;
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
index 0071e54..a7769672 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
@@ -357,11 +357,14 @@
           .SetTextDirection(style.Direction())
           .SetAvailableSize({available_inline_size, NGSizeIndefinite})
           .ToConstraintSpace(writing_mode);
-  NGLineBreaker line_breaker(node, space.Get());
-  NGInlineLayoutAlgorithm algorithm(node, space.Get());
+
+  NGFragmentBuilder container_builder(
+      NGPhysicalFragment::NGFragmentType::kFragmentBox, node);
+
+  NGLineBreaker line_breaker(node, space.Get(), &container_builder);
   NGLineInfo line_info;
   LayoutUnit result;
-  while (line_breaker.NextLine(&line_info, &algorithm)) {
+  while (line_breaker.NextLine(&line_info, NGLogicalOffset())) {
     LayoutUnit inline_size;
     for (const NGInlineItemResult item_result : line_info.Results())
       inline_size += item_result.inline_size;
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
index dd34fb3..3bb0c20 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
@@ -8,6 +8,7 @@
 #include "core/layout/ng/inline/ng_inline_layout_algorithm.h"
 #include "core/layout/ng/inline/ng_inline_node.h"
 #include "core/layout/ng/inline/ng_text_fragment.h"
+#include "core/layout/ng/ng_block_layout_algorithm.h"
 #include "core/layout/ng/ng_box_fragment.h"
 #include "core/layout/ng/ng_break_token.h"
 #include "core/layout/ng/ng_constraint_space.h"
@@ -56,10 +57,12 @@
 }  // namespace
 
 NGLineBreaker::NGLineBreaker(NGInlineNode node,
-                             const NGConstraintSpace* space,
-                             NGInlineBreakToken* break_token)
+                             NGConstraintSpace* space,
+                             NGFragmentBuilder* container_builder,
+                             const NGInlineBreakToken* break_token)
     : node_(node),
       constraint_space_(space),
+      container_builder_(container_builder),
       item_index_(0),
       offset_(0),
       break_iterator_(node.Text()),
@@ -72,8 +75,8 @@
 }
 
 bool NGLineBreaker::NextLine(NGLineInfo* line_info,
-                             NGInlineLayoutAlgorithm* algorithm) {
-  BreakLine(line_info, algorithm);
+                             const NGLogicalOffset& content_offset) {
+  BreakLine(line_info, content_offset);
 
   // TODO(kojii): When editing, or caret is enabled, trailing spaces at wrap
   // point should not be removed. For other cases, we can a) remove, b) leave
@@ -85,16 +88,21 @@
 }
 
 void NGLineBreaker::BreakLine(NGLineInfo* line_info,
-                              NGInlineLayoutAlgorithm* algorithm) {
+                              const NGLogicalOffset& content_offset) {
   NGInlineItemResults* item_results = &line_info->Results();
   item_results->clear();
   const Vector<NGInlineItem>& items = node_.Items();
   line_info->SetLineStyle(node_, !item_index_ && !offset_);
   UpdateBreakIterator(line_info->LineStyle());
-  available_width_ = algorithm->AvailableWidth();
   position_ = LayoutUnit(0);
   LineBreakState state = LineBreakState::kNotBreakable;
 
+  // We are only able to calculate our available_width if our container has
+  // been positioned in the BFC coordinate space yet.
+  WTF::Optional<LayoutUnit> available_width;
+  if (container_builder_->BfcOffset())
+    available_width = ComputeAvailableWidth(content_offset);
+
   while (item_index_ < items.size()) {
     // CloseTag prohibits to break before.
     const NGInlineItem& item = items[item_index_];
@@ -109,14 +117,32 @@
       line_info->SetIsLastLine(false);
       return;
     }
-    if (state == LineBreakState::kIsBreakable && position_ > available_width_)
-      return HandleOverflow(line_info);
+    if (state == LineBreakState::kIsBreakable && available_width &&
+        position_ > available_width.value())
+      return HandleOverflow(available_width.value(), line_info);
+
+    // We resolve the BFC-offset of the container if this line has an item with
+    // inline-size. Floats, and tags do not allow us to resolve the BFC-offset.
+    //
+    // If this line just has a float we place it in the unpositioned float list
+    // which will be positioned later.
+    bool should_resolve_bfc_offset =
+        !container_builder_->BfcOffset() &&
+        (item.Type() == NGInlineItem::kText ||
+         item.Type() == NGInlineItem::kAtomicInline ||
+         item.Type() == NGInlineItem::kControl);
+
+    if (should_resolve_bfc_offset) {
+      ResolveBFCOffset();
+      available_width = ComputeAvailableWidth(content_offset);
+    }
 
     item_results->push_back(
         NGInlineItemResult(item_index_, offset_, item.EndOffset()));
     NGInlineItemResult* item_result = &item_results->back();
     if (item.Type() == NGInlineItem::kText) {
-      state = HandleText(item, item_result);
+      DCHECK(available_width);
+      state = HandleText(item, available_width.value(), item_result);
     } else if (item.Type() == NGInlineItem::kAtomicInline) {
       state = HandleAtomicInline(item, item_result);
     } else if (item.Type() == NGInlineItem::kControl) {
@@ -129,18 +155,44 @@
       HandleOpenTag(item, item_result);
       state = LineBreakState::kNotBreakable;
     } else if (item.Type() == NGInlineItem::kFloating) {
-      HandleFloat(item, item_results, algorithm);
+      HandleFloat(item, content_offset, &available_width, item_results);
     } else {
       MoveToNextOf(item);
     }
   }
-  if (state == LineBreakState::kIsBreakable && position_ > available_width_)
-    return HandleOverflow(line_info);
+  if (state == LineBreakState::kIsBreakable && available_width &&
+      position_ > available_width.value())
+    return HandleOverflow(available_width.value(), line_info);
   line_info->SetIsLastLine(true);
 }
 
+// Resolves the BFC offset for the container, and positions any pending floats.
+void NGLineBreaker::ResolveBFCOffset() {
+  LayoutUnit container_bfc_block_offset =
+      constraint_space_->BfcOffset().block_offset +
+      constraint_space_->MarginStrut().Sum();
+  MaybeUpdateFragmentBfcOffset(*constraint_space_, container_bfc_block_offset,
+                               container_builder_);
+  PositionPendingFloats(container_bfc_block_offset, container_builder_,
+                        constraint_space_);
+}
+
+// Returns the inline size of the first layout opportunity from the given
+// content_offset.
+LayoutUnit NGLineBreaker::ComputeAvailableWidth(
+    const NGLogicalOffset& content_offset) const {
+  NGLogicalOffset offset = container_builder_->BfcOffset().value();
+  offset += content_offset;
+
+  NGLayoutOpportunityIterator iter(constraint_space_->Exclusions().get(),
+                                   constraint_space_->AvailableSize(), offset);
+  NGLayoutOpportunity opportunity = iter.Next();
+  return opportunity.InlineSize();
+};
+
 NGLineBreaker::LineBreakState NGLineBreaker::HandleText(
     const NGInlineItem& item,
+    LayoutUnit available_width,
     NGInlineItemResult* item_result) {
   DCHECK_EQ(item.Type(), NGInlineItem::kText);
 
@@ -148,7 +200,7 @@
   if (offset_ == item.StartOffset()) {
     item_result->inline_size = item.InlineSize();
     LayoutUnit next_position = position_ + item_result->inline_size;
-    if (!auto_wrap_ || next_position <= available_width_) {
+    if (!auto_wrap_ || next_position <= available_width) {
       position_ = next_position;
       MoveToNextOf(item);
       if (auto_wrap_ && break_iterator_.IsBreakable(item.EndOffset()))
@@ -160,10 +212,10 @@
 
   if (auto_wrap_) {
     // Try to break inside of this text item.
-    BreakText(item_result, item, available_width_ - position_);
+    BreakText(item_result, item, available_width - position_);
     position_ += item_result->inline_size;
 
-    bool is_overflow = position_ > available_width_;
+    bool is_overflow = position_ > available_width;
     item_result->no_break_opportunities_inside = is_overflow;
     if (item_result->end_offset < item.EndOffset()) {
       offset_ = item_result->end_offset;
@@ -284,12 +336,73 @@
   return LineBreakState::kNotBreakable;
 }
 
+// Performs layout and positions a float.
+//
+// If there is a known available_width (e.g. something has resolved the
+// container BFC offset) it will attempt to position the float on the current
+// line.
+// Additionally updates the available_width for the line as the float has
+// (probably) consumed space.
+//
+// If the float is too wide *or* we already have UnpositionedFloats we add it
+// as an UnpositionedFloat. This should be positioned *immediately* after we
+// are done with the current line.
+// We have this check if there are already UnpositionedFloats as we aren't
+// allowed to position a float "above" another float which has come before us
+// in the document.
+//
+// TODO(glebl): Add the support of clearance for inline floats.
 void NGLineBreaker::HandleFloat(const NGInlineItem& item,
-                                NGInlineItemResults* item_results,
-                                NGInlineLayoutAlgorithm* algorithm) {
-  algorithm->LayoutAndPositionFloat(position_, item.GetLayoutObject());
-  // Floats may change the available width if they fit.
-  available_width_ = algorithm->AvailableWidth();
+                                const NGLogicalOffset& content_offset,
+                                WTF::Optional<LayoutUnit>* available_width,
+                                NGInlineItemResults* item_results) {
+  NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
+
+  const ComputedStyle& float_style = node.Style();
+  NGBoxStrut margins = ComputeMargins(*constraint_space_, float_style,
+                                      constraint_space_->WritingMode(),
+                                      constraint_space_->Direction());
+
+  // TODO(ikilpatrick): Add support for float break tokens inside an inline
+  // layout context.
+  RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create(
+      constraint_space_->AvailableSize(),
+      constraint_space_->PercentageResolutionSize(),
+      constraint_space_->BfcOffset(), constraint_space_->BfcOffset(), margins,
+      node, /* break_token */ nullptr);
+
+  LayoutUnit inline_size = ComputeInlineSizeForUnpositionedFloat(
+      constraint_space_, unpositioned_float.Get());
+
+  // We can only determine if our float will fit if we have an available_width
+  // I.e. we may not have come across any text yet, in order to be able to
+  // resolve the BFC position.
+  bool float_does_not_fit =
+      !available_width->has_value() ||
+      position_ + inline_size + margins.InlineSum() > available_width->value();
+
+  // Check if we already have a pending float. That's because a float cannot be
+  // higher than any block or floated box generated before.
+  if (!container_builder_->UnpositionedFloats().IsEmpty() ||
+      float_does_not_fit) {
+    container_builder_->AddUnpositionedFloat(unpositioned_float);
+  } else {
+    NGLogicalOffset container_bfc_offset =
+        container_builder_->BfcOffset().value();
+    unpositioned_float->origin_offset = container_bfc_offset + content_offset;
+    unpositioned_float->from_offset.block_offset =
+        container_bfc_offset.block_offset;
+    unpositioned_float->parent_bfc_block_offset =
+        container_bfc_offset.block_offset;
+
+    container_builder_->AddPositionedFloat(
+        PositionFloat(unpositioned_float.Get(), constraint_space_));
+
+    // We need to recalculate the available_width as the float probably
+    // consumed space on the line.
+    *available_width = ComputeAvailableWidth(content_offset);
+  }
+
   // Floats are already positioned in the container_builder.
   item_results->pop_back();
   MoveToNextOf(item);
@@ -341,10 +454,11 @@
 // Handles when the last item overflows.
 // At this point, item_results does not fit into the current line, and there
 // are no break opportunities in item_results.back().
-void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
+void NGLineBreaker::HandleOverflow(LayoutUnit available_width,
+                                   NGLineInfo* line_info) {
   NGInlineItemResults* item_results = &line_info->Results();
   const Vector<NGInlineItem>& items = node_.Items();
-  LayoutUnit rewind_width = available_width_ - position_;
+  LayoutUnit rewind_width = available_width - position_;
   DCHECK_LT(rewind_width, 0);
 
   // Search for a break opportunity that can fit.
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h
index 2c6b2da..3db5221 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h
@@ -19,7 +19,7 @@
 class NGInlineBreakToken;
 class NGInlineItem;
 class NGInlineNode;
-class NGInlineLayoutAlgorithm;
+class NGFragmentBuilder;
 
 // Represents a line breaker.
 //
@@ -28,23 +28,24 @@
 class CORE_EXPORT NGLineBreaker {
  public:
   NGLineBreaker(NGInlineNode,
-                const NGConstraintSpace*,
-                NGInlineBreakToken* = nullptr);
+                NGConstraintSpace*,
+                NGFragmentBuilder*,
+                const NGInlineBreakToken* = nullptr);
   ~NGLineBreaker() {}
   STACK_ALLOCATED();
 
   // Compute the next line break point and produces NGInlineItemResults for
   // the line.
-  // TODO(kojii): NGInlineLayoutAlgorithm is needed because floats require
-  // not only constraint space but also container builder. Consider refactor
-  // not to require algorithm.
-  bool NextLine(NGLineInfo*, NGInlineLayoutAlgorithm*);
+  bool NextLine(NGLineInfo*, const NGLogicalOffset&);
 
   // Create an NGInlineBreakToken for the last line returned by NextLine().
   RefPtr<NGInlineBreakToken> CreateBreakToken() const;
 
  private:
-  void BreakLine(NGLineInfo*, NGInlineLayoutAlgorithm*);
+  void BreakLine(NGLineInfo*, const NGLogicalOffset&);
+
+  void ResolveBFCOffset();
+  LayoutUnit ComputeAvailableWidth(const NGLogicalOffset&) const;
 
   enum class LineBreakState {
     // The current position is not breakable.
@@ -57,7 +58,9 @@
     kForcedBreak
   };
 
-  LineBreakState HandleText(const NGInlineItem&, NGInlineItemResult*);
+  LineBreakState HandleText(const NGInlineItem&,
+                            LayoutUnit available_width,
+                            NGInlineItemResult*);
   void BreakText(NGInlineItemResult*,
                  const NGInlineItem&,
                  LayoutUnit available_width);
@@ -65,13 +68,14 @@
   LineBreakState HandleControlItem(const NGInlineItem&, NGInlineItemResult*);
   LineBreakState HandleAtomicInline(const NGInlineItem&, NGInlineItemResult*);
   void HandleFloat(const NGInlineItem&,
-                   NGInlineItemResults*,
-                   NGInlineLayoutAlgorithm*);
+                   const NGLogicalOffset&,
+                   WTF::Optional<LayoutUnit>* available_width,
+                   NGInlineItemResults*);
 
   void HandleOpenTag(const NGInlineItem&, NGInlineItemResult*);
   void HandleCloseTag(const NGInlineItem&, NGInlineItemResult*);
 
-  void HandleOverflow(NGLineInfo*);
+  void HandleOverflow(LayoutUnit available_width, NGLineInfo*);
   void Rewind(NGLineInfo*, unsigned new_end);
 
   void UpdateBreakIterator(const ComputedStyle&);
@@ -81,11 +85,11 @@
   void SkipCollapsibleWhitespaces();
 
   NGInlineNode node_;
-  const NGConstraintSpace* constraint_space_;
+  NGConstraintSpace* constraint_space_;
+  NGFragmentBuilder* container_builder_;
   const AtomicString locale_;
   unsigned item_index_;
   unsigned offset_;
-  LayoutUnit available_width_;
   LayoutUnit position_;
   LazyLineBreakIterator break_iterator_;
   HarfBuzzShaper shaper_;
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc
index 9332247a..25cf38f 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -35,11 +35,14 @@
         NGConstraintSpaceBuilder(NGWritingMode::kHorizontalTopBottom)
             .SetAvailableSize({available_width, NGSizeIndefinite})
             .ToConstraintSpace(NGWritingMode::kHorizontalTopBottom);
-    NGLineBreaker line_breaker(node, space.Get());
-    NGInlineLayoutAlgorithm algorithm(node, space.Get());
+
+    NGFragmentBuilder container_builder(
+        NGPhysicalFragment::NGFragmentType::kFragmentBox, node);
+
+    NGLineBreaker line_breaker(node, space.Get(), &container_builder);
     Vector<NGInlineItemResults> lines;
     NGLineInfo line_info;
-    while (line_breaker.NextLine(&line_info, &algorithm))
+    while (line_breaker.NextLine(&line_info, NGLogicalOffset()))
       lines.push_back(std::move(line_info.Results()));
     return lines;
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
index 8d088bf..59a32a2 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.cc
@@ -7,7 +7,6 @@
 #include "core/layout/LayoutBlock.h"
 #include "core/layout/LayoutView.h"
 #include "core/layout/ng/ng_constraint_space_builder.h"
-#include "core/layout/ng/ng_layout_opportunity_iterator.h"
 
 namespace blink {
 
@@ -50,8 +49,7 @@
       margin_strut_(margin_strut),
       bfc_offset_(bfc_offset),
       exclusions_(exclusions),
-      clearance_offset_(clearance_offset),
-      layout_opp_iter_(nullptr) {
+      clearance_offset_(clearance_offset) {
   unpositioned_floats_.swap(unpositioned_floats);
 }
 
@@ -130,26 +128,12 @@
 
 void NGConstraintSpace::AddExclusion(const NGExclusion& exclusion) {
   exclusions_->Add(exclusion);
-  // Invalidate the Layout Opportunity Iterator.
-  layout_opp_iter_.reset();
 }
 
 NGFragmentationType NGConstraintSpace::BlockFragmentationType() const {
   return static_cast<NGFragmentationType>(block_direction_fragmentation_type_);
 }
 
-NGLayoutOpportunityIterator* NGConstraintSpace::LayoutOpportunityIterator(
-    const NGLogicalOffset& iter_offset) {
-  if (layout_opp_iter_ && layout_opp_iter_->Offset() != iter_offset)
-    layout_opp_iter_.reset();
-
-  if (!layout_opp_iter_) {
-    layout_opp_iter_ = WTF::MakeUnique<NGLayoutOpportunityIterator>(
-        Exclusions().get(), AvailableSize(), iter_offset);
-  }
-  return layout_opp_iter_.get();
-}
-
 bool NGConstraintSpace::operator==(const NGConstraintSpace& other) const {
   // TODO(cbiesinger): For simplicity and performance, for now, we only
   // consider two constraint spaces equal if neither one has unpositioned
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
index 119b9a4..ae3eb064 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
@@ -11,7 +11,6 @@
 #include "core/layout/ng/geometry/ng_margin_strut.h"
 #include "core/layout/ng/geometry/ng_physical_size.h"
 #include "core/layout/ng/ng_exclusion.h"
-#include "core/layout/ng/ng_layout_opportunity_iterator.h"
 #include "core/layout/ng/ng_unpositioned_float.h"
 #include "core/layout/ng/ng_writing_mode.h"
 #include "platform/heap/Handle.h"
@@ -109,12 +108,6 @@
   // blockSize if possible.
   NGFragmentationType BlockFragmentationType() const;
 
-  // Returns a pointer to already existing Layout Opportunity iterator
-  // associated with this constraint space and {@code iter_offset} or creates a
-  // new one.
-  NGLayoutOpportunityIterator* LayoutOpportunityIterator(
-      const NGLogicalOffset& iter_offset);
-
   // Return true if this contraint space participates in a fragmentation
   // context.
   bool HasBlockFragmentation() const {
@@ -194,7 +187,6 @@
   NGLogicalOffset bfc_offset_;
   const std::shared_ptr<NGExclusions> exclusions_;
   WTF::Optional<LayoutUnit> clearance_offset_;
-  std::unique_ptr<NGLayoutOpportunityIterator> layout_opp_iter_;
   Vector<RefPtr<NGUnpositionedFloat>> unpositioned_floats_;
 };
 
diff --git a/third_party/WebKit/Source/modules/battery/NavigatorBattery.cpp b/third_party/WebKit/Source/modules/battery/NavigatorBattery.cpp
index a6c7351..5f6423f 100644
--- a/third_party/WebKit/Source/modules/battery/NavigatorBattery.cpp
+++ b/third_party/WebKit/Source/modules/battery/NavigatorBattery.cpp
@@ -4,10 +4,8 @@
 
 #include "modules/battery/NavigatorBattery.h"
 
-#include "core/dom/DOMException.h"
-#include "core/dom/Document.h"
-#include "core/dom/ExceptionCode.h"
-#include "core/frame/LocalDOMWindow.h"
+#include "core/dom/ExecutionContext.h"
+#include "core/frame/LocalFrame.h"
 #include "modules/battery/BatteryManager.h"
 
 namespace blink {
@@ -21,26 +19,10 @@
 }
 
 ScriptPromise NavigatorBattery::getBattery(ScriptState* script_state) {
-  ExecutionContext* execution_context = ExecutionContext::From(script_state);
-
-  // Check secure context.
-  String error_message;
-  if (!execution_context->IsSecureContext(error_message)) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state, DOMException::Create(kSecurityError, error_message));
+  if (!battery_manager_) {
+    battery_manager_ =
+        BatteryManager::Create(ExecutionContext::From(script_state));
   }
-
-  // Check top-level browsing context.
-  if (!ToDocument(execution_context)->domWindow()->GetFrame() ||
-      !ToDocument(execution_context)->GetFrame()->IsMainFrame()) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state, DOMException::Create(
-                          kSecurityError, "Not a top-level browsing context."));
-  }
-
-  if (!battery_manager_)
-    battery_manager_ = BatteryManager::Create(execution_context);
-
   return battery_manager_->StartRequest(script_state);
 }
 
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index b7f18d0..69d64ad 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -1441,8 +1441,6 @@
         fpixels1 = static_cast<float*>(vpointer);
         fpixels2 = static_cast<float*>(pixels_from_get_image_data);
         for (unsigned m = 0; m < data_length; m++) {
-          if (fpixels1[m] < 0)
-            fpixels1[m] = 0;
           if (fabs(fpixels1[m] - fpixels2[m]) > color_tolerance) {
             test_passed = false;
           }
@@ -1471,17 +1469,17 @@
 TEST_F(CanvasRenderingContext2DTest,
        ColorManagedPutImageDataOnLinearSRGBCanvas) {
   TestPutImageDataOnCanvasWithColorSpaceSettings(
-      CanvasElement(), CanvasColorSpaceSettings::CANVAS_LINEARSRGB, 0.15);
+      CanvasElement(), CanvasColorSpaceSettings::CANVAS_LINEARSRGB, 0.01);
 }
 
 TEST_F(CanvasRenderingContext2DTest, ColorManagedPutImageDataOnRec2020Canvas) {
   TestPutImageDataOnCanvasWithColorSpaceSettings(
-      CanvasElement(), CanvasColorSpaceSettings::CANVAS_REC2020, 0.1);
+      CanvasElement(), CanvasColorSpaceSettings::CANVAS_REC2020, 0.01);
 }
 
 TEST_F(CanvasRenderingContext2DTest, ColorManagedPutImageDataOnP3Canvas) {
   TestPutImageDataOnCanvasWithColorSpaceSettings(
-      CanvasElement(), CanvasColorSpaceSettings::CANVAS_P3, 0.1);
+      CanvasElement(), CanvasColorSpaceSettings::CANVAS_P3, 0.01);
 }
 
 void OverrideScriptEnabled(Settings& settings) {
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
index bdf5335..c4e1e4c 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.cpp
@@ -11,6 +11,7 @@
 #include "modules/serviceworkers/RespondWithObserver.h"
 #include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
 #include "modules/serviceworkers/ServiceWorkerWindowClientCallback.h"
+#include "platform/bindings/ScriptState.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/text/AtomicString.h"
 
@@ -53,8 +54,8 @@
   return method_data_;
 }
 
-void PaymentRequestEvent::total(PaymentItem& value) const {
-  value = total_;
+const ScriptValue PaymentRequestEvent::total(ScriptState* script_state) const {
+  return ScriptValue::From(script_state, total_);
 }
 
 const HeapVector<PaymentDetailsModifier>& PaymentRequestEvent::modifiers()
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h
index 28e364f6..9887c10 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.h
@@ -5,6 +5,7 @@
 #ifndef PaymentRequestEvent_h
 #define PaymentRequestEvent_h
 
+#include "bindings/core/v8/ScriptValue.h"
 #include "modules/EventModules.h"
 #include "modules/payments/PaymentRequestEventInit.h"
 #include "modules/serviceworkers/ExtendableEvent.h"
@@ -17,6 +18,7 @@
 namespace blink {
 
 class RespondWithObserver;
+class ScriptState;
 
 class MODULES_EXPORT PaymentRequestEvent final : public ExtendableEvent {
   DEFINE_WRAPPERTYPEINFO();
@@ -37,7 +39,7 @@
   const String& paymentRequestOrigin() const;
   const String& paymentRequestId() const;
   const HeapVector<PaymentMethodData>& methodData() const;
-  void total(PaymentItem& value) const;
+  const ScriptValue total(ScriptState*) const;
   const HeapVector<PaymentDetailsModifier>& modifiers() const;
   const String& instrumentKey() const;
 
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl
index c2c69af..b4d06c3 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequestEvent.idl
@@ -13,7 +13,7 @@
     readonly attribute USVString paymentRequestOrigin;
     readonly attribute DOMString paymentRequestId;
     readonly attribute FrozenArray<PaymentMethodData> methodData;
-    readonly attribute PaymentItem total;
+    [CallWith=ScriptState] readonly attribute object total;
     readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
     readonly attribute DOMString instrumentKey;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
index bcb2848..5cf7cd0c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -1664,6 +1664,8 @@
     bool is_web_history_inert_commit,
     bool is_reload,
     bool is_main_frame) {
+  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+               "RendererSchedulerImpl::OnDidCommitProvisionalLoad");
   // Initialize |max_queueing_time_metric| lazily so that
   // |SingleSampleMetricsFactory::SetFactory()| is called before
   // |SingleSampleMetricsFactory::Get()|
@@ -1677,9 +1679,7 @@
 
   // If this either isn't a history inert commit or it's a reload then we must
   // reset the task cost estimators.
-  if (is_main_frame && (is_web_history_inert_commit || is_reload)) {
-    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
-                 "RendererSchedulerImpl::OnDidCommitProvisionalLoad");
+  if (is_main_frame && (!is_web_history_inert_commit || is_reload)) {
     base::AutoLock lock(any_thread_lock_);
     ResetForNavigationLocked();
   }
@@ -1715,6 +1715,8 @@
 }
 
 void RendererSchedulerImpl::ResetForNavigationLocked() {
+  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+               "RendererSchedulerImpl::ResetForNavigationLocked");
   helper_.CheckOnValidThread();
   any_thread_lock_.AssertAcquired();
   GetAnyThread().user_model.Reset(helper_.scheduler_tqm_delegate()->NowTicks());
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index 5ca6012..124d320 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -241,6 +241,11 @@
     return GetAnyThread().begin_main_frame_on_critical_path;
   }
 
+  bool waiting_for_meaningful_paint() const {
+    base::AutoLock lock(any_thread_lock_);
+    return GetAnyThread().waiting_for_meaningful_paint;
+  }
+
   int update_policy_count_;
   std::vector<std::string> use_cases_;
 };
@@ -3997,5 +4002,60 @@
   scheduler_->DidCommitProvisionalLoad(false, false, false);
   tester.ExpectUniqueSample("RendererScheduler.MaxQueueingTime", 500, 1);
 }
+
+TEST_F(RendererSchedulerImplTest, DidCommitProvisionalLoad) {
+  scheduler_->OnFirstMeaningfulPaint();
+  EXPECT_FALSE(scheduler_->waiting_for_meaningful_paint());
+
+  // Check that we only clear state for main frame navigations that are either
+  // not history inert or are reloads.
+  scheduler_->DidCommitProvisionalLoad(false /* is_web_history_inert_commit */,
+                                       false /* is_reload */,
+                                       false /* is_main_frame */);
+  EXPECT_FALSE(scheduler_->waiting_for_meaningful_paint());
+
+  scheduler_->OnFirstMeaningfulPaint();
+  scheduler_->DidCommitProvisionalLoad(false /* is_web_history_inert_commit */,
+                                       false /* is_reload */,
+                                       true /* is_main_frame */);
+  EXPECT_TRUE(scheduler_->waiting_for_meaningful_paint());  // State cleared.
+
+  scheduler_->OnFirstMeaningfulPaint();
+  scheduler_->DidCommitProvisionalLoad(false /* is_web_history_inert_commit */,
+                                       true /* is_reload */,
+                                       false /* is_main_frame */);
+  EXPECT_FALSE(scheduler_->waiting_for_meaningful_paint());
+
+  scheduler_->OnFirstMeaningfulPaint();
+  scheduler_->DidCommitProvisionalLoad(false /* is_web_history_inert_commit */,
+                                       true /* is_reload */,
+                                       true /* is_main_frame */);
+  EXPECT_TRUE(scheduler_->waiting_for_meaningful_paint());  // State cleared.
+
+  scheduler_->OnFirstMeaningfulPaint();
+  scheduler_->DidCommitProvisionalLoad(true /* is_web_history_inert_commit */,
+                                       false /* is_reload */,
+                                       false /* is_main_frame */);
+  EXPECT_FALSE(scheduler_->waiting_for_meaningful_paint());
+
+  scheduler_->OnFirstMeaningfulPaint();
+  scheduler_->DidCommitProvisionalLoad(true /* is_web_history_inert_commit */,
+                                       false /* is_reload */,
+                                       true /* is_main_frame */);
+  EXPECT_FALSE(scheduler_->waiting_for_meaningful_paint());
+
+  scheduler_->OnFirstMeaningfulPaint();
+  scheduler_->DidCommitProvisionalLoad(true /* is_web_history_inert_commit */,
+                                       true /* is_reload */,
+                                       false /* is_main_frame */);
+  EXPECT_FALSE(scheduler_->waiting_for_meaningful_paint());
+
+  scheduler_->OnFirstMeaningfulPaint();
+  scheduler_->DidCommitProvisionalLoad(true /* is_web_history_inert_commit */,
+                                       true /* is_reload */,
+                                       true /* is_main_frame */);
+  EXPECT_TRUE(scheduler_->waiting_for_meaningful_paint());  // State cleared.
+}
+
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
index 3cb873d9..3961762 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl.cc
@@ -162,6 +162,8 @@
 void WebViewSchedulerImpl::Unregister(WebFrameSchedulerImpl* frame_scheduler) {
   DCHECK(frame_schedulers_.find(frame_scheduler) != frame_schedulers_.end());
   frame_schedulers_.erase(frame_scheduler);
+  provisional_loads_.erase(frame_scheduler);
+  expect_backward_forwards_navigation_.erase(frame_scheduler);
 }
 
 void WebViewSchedulerImpl::OnNavigation() {
diff --git a/tools/chrome_proxy/webdriver/lofi.py b/tools/chrome_proxy/webdriver/lofi.py
index 88cd1d8..5960ad0bc 100644
--- a/tools/chrome_proxy/webdriver/lofi.py
+++ b/tools/chrome_proxy/webdriver/lofi.py
@@ -183,5 +183,33 @@
       # Verify that responses were seen.
       self.assertNotEqual(0, responses)
 
+  # Checks that LoFi images are served and the force empty image experiment
+  # directive is provided when LoFi is always-on without Lite Pages enabled.
+  def testLoFiForcedExperiment(self):
+    # If it was attempted to run with another experiment, skip this test.
+    if common.ParseFlags().browser_args and ('--data-reduction-proxy-experiment'
+        in common.ParseFlags().browser_args):
+      self.skipTest('This test cannot be run with other experiments.')
+    with TestDriver() as test_driver:
+      test_driver.AddChromeArg('--enable-spdy-proxy-auth')
+      test_driver.AddChromeArg('--data-reduction-proxy-lo-fi=always-on')
+
+      test_driver.LoadURL('http://check.googlezip.net/static/index.html')
+
+      lofi_responses = 0
+      for response in test_driver.GetHTTPResponses():
+        self.assertIn('exp=force_page_policies_empty_image',
+          response.request_headers['chrome-proxy'])
+        if response.url.endswith('html'):
+          # TODO(dougarnett): Check page-policies response when server supports
+          continue
+        if response.url.endswith('png'):
+          # TODO(dougarnett): Set 4G ECT when server supports force empty image
+          self.checkLoFiResponse(response, True)
+          lofi_responses = lofi_responses + 1
+
+      # Verify that Lo-Fi responses were seen.
+      self.assertNotEqual(0, lofi_responses)
+
 if __name__ == '__main__':
   IntegrationTest.RunAllTests()
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 831235b..976db00 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -23606,6 +23606,13 @@
   </summary>
 </histogram>
 
+<histogram name="GPU.SwiftShaderLifetimeEvents" enum="GPUProcessLifetimeEvent">
+  <owner>capn@chromium.org</owner>
+  <summary>
+    Counts of the number of process launches and crashes (when running on s/w).
+  </summary>
+</histogram>
+
 <histogram name="GPU.TextureRG" enum="BooleanAvailable">
   <owner>reveman@chromium.org</owner>
   <summary>
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 78bc7f55..f263927 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -80,8 +80,7 @@
   settings.layers_always_allowed_lcd_text = true;
   // Use occlusion to allow more overlapping windows to take less memory.
   settings.use_occlusion_for_tile_prioritization = true;
-  refresh_rate_ = settings.renderer_settings.refresh_rate =
-      context_factory_->GetRefreshRate();
+  refresh_rate_ = context_factory_->GetRefreshRate();
   settings.main_frame_before_activation_enabled = false;
 
   if (command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders)) {
diff --git a/ui/compositor/compositor_util.cc b/ui/compositor/compositor_util.cc
index 63bc273..59631c6 100644
--- a/ui/compositor/compositor_util.cc
+++ b/ui/compositor/compositor_util.cc
@@ -46,6 +46,8 @@
   }
   renderer_settings.disallow_non_exact_resource_reuse =
       command_line->HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
+  renderer_settings.allow_antialiasing =
+      !command_line->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
 
   return renderer_settings;
 }