diff --git a/DEPS b/DEPS
index d98c6c5..c4afc11 100644
--- a/DEPS
+++ b/DEPS
@@ -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': '07c8f1ff81f52c25da9d6da6b94908958a0282da',
+  'catapult_revision': '94d724b18fcef3f8ab81ae9b0dd85466db68815d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index c0704532..2475e7b 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -535,8 +535,8 @@
     "renderer/aw_print_web_view_helper_delegate.h",
     "renderer/aw_render_frame_ext.cc",
     "renderer/aw_render_frame_ext.h",
-    "renderer/aw_render_process_observer.cc",
-    "renderer/aw_render_process_observer.h",
+    "renderer/aw_render_thread_observer.cc",
+    "renderer/aw_render_thread_observer.h",
     "renderer/aw_render_view_ext.cc",
     "renderer/aw_render_view_ext.h",
     "renderer/print_render_frame_observer.cc",
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 0ac4b865..246c9c1 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -425,8 +425,8 @@
         'renderer/aw_print_web_view_helper_delegate.h',
         'renderer/aw_render_frame_ext.cc',
         'renderer/aw_render_frame_ext.h',
-        'renderer/aw_render_process_observer.cc',
-        'renderer/aw_render_process_observer.h',
+        'renderer/aw_render_thread_observer.cc',
+        'renderer/aw_render_thread_observer.h',
         'renderer/aw_render_view_ext.cc',
         'renderer/aw_render_view_ext.h',
         'renderer/print_render_frame_observer.cc',
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index 2ed0a92..2436473 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -62,8 +62,8 @@
 
 void AwContentRendererClient::RenderThreadStarted() {
   RenderThread* thread = RenderThread::Get();
-  aw_render_process_observer_.reset(new AwRenderProcessObserver);
-  thread->AddObserver(aw_render_process_observer_.get());
+  aw_render_thread_observer_.reset(new AwRenderThreadObserver);
+  thread->AddObserver(aw_render_thread_observer_.get());
 
   visited_link_slave_.reset(new visitedlink::VisitedLinkSlave);
   thread->AddObserver(visited_link_slave_.get());
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index a443735..eaab5f7 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -9,7 +9,7 @@
 
 #include <stddef.h>
 
-#include "android_webview/renderer/aw_render_process_observer.h"
+#include "android_webview/renderer/aw_render_thread_observer.h"
 #include "base/compiler_specific.h"
 
 namespace visitedlink {
@@ -52,7 +52,7 @@
       blink::WebPageVisibilityState* override_state) override;
 
  private:
-  std::unique_ptr<AwRenderProcessObserver> aw_render_process_observer_;
+  std::unique_ptr<AwRenderThreadObserver> aw_render_thread_observer_;
   std::unique_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
   const bool disable_page_visibility_;
 };
diff --git a/android_webview/renderer/aw_render_process_observer.h b/android_webview/renderer/aw_render_process_observer.h
deleted file mode 100644
index 96bda4b..0000000
--- a/android_webview/renderer/aw_render_process_observer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_WEBVIEW_RENDERER_AW_RENDER_PROCESS_OBSERVER_H_
-#define ANDROID_WEBVIEW_RENDERER_AW_RENDER_PROCESS_OBSERVER_H_
-
-#include "content/public/renderer/render_process_observer.h"
-
-#include "base/compiler_specific.h"
-
-namespace android_webview {
-
-// A RenderProcessObserver implementation used for handling android_webview
-// specific render-process wide IPC messages.
-class AwRenderProcessObserver : public content::RenderProcessObserver {
- public:
-  AwRenderProcessObserver();
-  ~AwRenderProcessObserver() override;
-
-  // content::RenderProcessObserver implementation.
-  bool OnControlMessageReceived(const IPC::Message& message) override;
-
- private:
-  void OnClearCache();
-  void OnSetJsOnlineProperty(bool network_up);
-};
-
-}  // namespace android_webview
-
-#endif  // ANDROID_WEBVIEW_RENDERER_AW_RENDER_PROCESS_OBSERVER_H_
-
diff --git a/android_webview/renderer/aw_render_process_observer.cc b/android_webview/renderer/aw_render_thread_observer.cc
similarity index 67%
rename from android_webview/renderer/aw_render_process_observer.cc
rename to android_webview/renderer/aw_render_thread_observer.cc
index 4719239..9faf9f0 100644
--- a/android_webview/renderer/aw_render_process_observer.cc
+++ b/android_webview/renderer/aw_render_thread_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "android_webview/renderer/aw_render_process_observer.h"
+#include "android_webview/renderer/aw_render_thread_observer.h"
 
 #include "android_webview/common/render_view_messages.h"
 #include "ipc/ipc_message_macros.h"
@@ -11,16 +11,16 @@
 
 namespace android_webview {
 
-AwRenderProcessObserver::AwRenderProcessObserver() {
+AwRenderThreadObserver::AwRenderThreadObserver() {
 }
 
-AwRenderProcessObserver::~AwRenderProcessObserver() {
+AwRenderThreadObserver::~AwRenderThreadObserver() {
 }
 
-bool AwRenderProcessObserver::OnControlMessageReceived(
+bool AwRenderThreadObserver::OnControlMessageReceived(
     const IPC::Message& message) {
   bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(AwRenderProcessObserver, message)
+  IPC_BEGIN_MESSAGE_MAP(AwRenderThreadObserver, message)
     IPC_MESSAGE_HANDLER(AwViewMsg_ClearCache, OnClearCache)
     IPC_MESSAGE_HANDLER(AwViewMsg_SetJsOnlineProperty, OnSetJsOnlineProperty)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -28,11 +28,11 @@
   return handled;
 }
 
-void AwRenderProcessObserver::OnClearCache() {
+void AwRenderThreadObserver::OnClearCache() {
   blink::WebCache::clear();
 }
 
-void AwRenderProcessObserver::OnSetJsOnlineProperty(bool network_up) {
+void AwRenderThreadObserver::OnSetJsOnlineProperty(bool network_up) {
   blink::WebNetworkStateNotifier::setOnLine(network_up);
 }
 
diff --git a/android_webview/renderer/aw_render_thread_observer.h b/android_webview/renderer/aw_render_thread_observer.h
new file mode 100644
index 0000000..76cc5c6
--- /dev/null
+++ b/android_webview/renderer/aw_render_thread_observer.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_RENDERER_AW_RENDER_THREAD_OBSERVER_H_
+#define ANDROID_WEBVIEW_RENDERER_AW_RENDER_THREAD_OBSERVER_H_
+
+#include "content/public/renderer/render_thread_observer.h"
+
+#include "base/compiler_specific.h"
+
+namespace android_webview {
+
+// A RenderThreadObserver implementation used for handling android_webview
+// specific render-process wide IPC messages.
+class AwRenderThreadObserver : public content::RenderThreadObserver {
+ public:
+  AwRenderThreadObserver();
+  ~AwRenderThreadObserver() override;
+
+  // content::RenderThreadObserver implementation.
+  bool OnControlMessageReceived(const IPC::Message& message) override;
+
+ private:
+  void OnClearCache();
+  void OnSetJsOnlineProperty(bool network_up);
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_RENDERER_AW_RENDER_THREAD_OBSERVER_H_
+
diff --git a/blimp/engine/app/blimp_content_renderer_client.cc b/blimp/engine/app/blimp_content_renderer_client.cc
index 0ddf1c2..69703ad 100644
--- a/blimp/engine/app/blimp_content_renderer_client.cc
+++ b/blimp/engine/app/blimp_content_renderer_client.cc
@@ -7,7 +7,7 @@
 #include "blimp/common/compositor/blimp_image_serialization_processor.h"
 #include "blimp/engine/mojo/blob_channel.mojom.h"
 #include "blimp/engine/renderer/engine_image_serialization_processor.h"
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_render_thread_observer.h"
 #include "content/public/common/service_registry.h"
 #include "content/public/renderer/render_thread.h"
 
@@ -30,7 +30,7 @@
 BlimpContentRendererClient::~BlimpContentRendererClient() {}
 
 void BlimpContentRendererClient::RenderThreadStarted() {
-  web_cache_observer_.reset(new web_cache::WebCacheRenderProcessObserver());
+  web_cache_observer_.reset(new web_cache::WebCacheRenderThreadObserver());
   image_serialization_processor_.reset(
       new EngineImageSerializationProcessor(GetConnectedBlobChannel()));
 }
diff --git a/blimp/engine/app/blimp_content_renderer_client.h b/blimp/engine/app/blimp_content_renderer_client.h
index af568170..0e0fd54 100644
--- a/blimp/engine/app/blimp_content_renderer_client.h
+++ b/blimp/engine/app/blimp_content_renderer_client.h
@@ -11,7 +11,7 @@
 #include "content/public/renderer/content_renderer_client.h"
 
 namespace web_cache {
-class WebCacheRenderProcessObserver;
+class WebCacheRenderThreadObserver;
 }
 
 namespace blimp {
@@ -28,7 +28,7 @@
 
  private:
   // This observer manages the process-global web cache.
-  std::unique_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
+  std::unique_ptr<web_cache::WebCacheRenderThreadObserver> web_cache_observer_;
 
   // Provides the functionality to serialize images in SkPicture.
   std::unique_ptr<cc::ImageSerializationProcessor>
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index 9b2d73d3..3eab9e7 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -8,54 +8,10 @@
 #include "base/memory/ptr_util.h"
 #include "cc/animation/animation_host.h"
 #include "cc/animation/animation_player.h"
-#include "cc/animation/layer_animation_value_observer.h"
 #include "cc/trees/mutator_host_client.h"
 
 namespace cc {
 
-class ElementAnimations::ValueObserver : public LayerAnimationValueObserver {
- public:
-  ValueObserver(ElementAnimations* element_animation, LayerTreeType tree_type)
-      : element_animations_(element_animation), tree_type_(tree_type) {
-    DCHECK(element_animations_);
-  }
-
-  // LayerAnimationValueObserver implementation.
-  void OnFilterAnimated(const FilterOperations& filters) override {
-    element_animations_->SetFilterMutated(tree_type_, filters);
-  }
-
-  void OnOpacityAnimated(float opacity) override {
-    element_animations_->SetOpacityMutated(tree_type_, opacity);
-  }
-
-  void OnTransformAnimated(const gfx::Transform& transform) override {
-    element_animations_->SetTransformMutated(tree_type_, transform);
-  }
-
-  void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) override {
-    element_animations_->SetScrollOffsetMutated(tree_type_, scroll_offset);
-  }
-
-  void OnAnimationWaitingForDeletion() override {
-    // TODO(loyso): See Layer::OnAnimationWaitingForDeletion. But we always do
-    // PushProperties for AnimationTimelines for now.
-  }
-
-  void OnTransformIsPotentiallyAnimatingChanged(bool is_animating) override {
-    element_animations_->SetTransformIsPotentiallyAnimatingChanged(
-        tree_type_, is_animating);
-  }
-
-  bool IsActive() const override { return tree_type_ == LayerTreeType::ACTIVE; }
-
- private:
-  ElementAnimations* element_animations_;
-  const LayerTreeType tree_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(ValueObserver);
-};
-
 std::unique_ptr<ElementAnimations> ElementAnimations::Create(
     AnimationHost* host) {
   return base::WrapUnique(new ElementAnimations(host));
@@ -79,6 +35,7 @@
       animation_host_->GetAnimationControllerForId(layer_id);
   layer_animation_controller_->SetAnimationHost(animation_host_);
   layer_animation_controller_->set_layer_animation_delegate(this);
+  layer_animation_controller_->set_value_observer(this);
   layer_animation_controller_->set_value_provider(this);
 
   DCHECK(animation_host_->mutator_host_client());
@@ -93,16 +50,17 @@
 void ElementAnimations::DestroyLayerAnimationController() {
   DCHECK(animation_host_);
 
-  if (active_value_observer_)
-    SetTransformIsPotentiallyAnimatingChanged(LayerTreeType::ACTIVE, false);
-  if (pending_value_observer_)
-    SetTransformIsPotentiallyAnimatingChanged(LayerTreeType::PENDING, false);
+  if (needs_active_value_observations())
+    OnTransformIsPotentiallyAnimatingChanged(LayerTreeType::ACTIVE, false);
+  if (needs_pending_value_observations())
+    OnTransformIsPotentiallyAnimatingChanged(LayerTreeType::PENDING, false);
 
   DestroyPendingValueObserver();
   DestroyActiveValueObserver();
 
   if (layer_animation_controller_) {
     layer_animation_controller_->remove_value_provider(this);
+    layer_animation_controller_->set_value_observer(nullptr);
     layer_animation_controller_->remove_layer_animation_delegate(this);
     layer_animation_controller_->SetAnimationHost(nullptr);
     layer_animation_controller_ = nullptr;
@@ -113,13 +71,10 @@
   DCHECK(layer_animation_controller_);
   DCHECK_EQ(layer_animation_controller_->id(), layer_id);
 
-  if (tree_type == LayerTreeType::ACTIVE) {
-    if (!active_value_observer_)
-      CreateActiveValueObserver();
-  } else {
-    if (!pending_value_observer_)
-      CreatePendingValueObserver();
-  }
+  if (tree_type == LayerTreeType::ACTIVE)
+    layer_animation_controller_->set_needs_active_value_observations(true);
+  else
+    layer_animation_controller_->set_needs_pending_value_observations(true);
 }
 
 void ElementAnimations::LayerUnregistered(int layer_id,
@@ -198,7 +153,7 @@
   layer_animation_controller_->RemoveEventObserver(observer);
 }
 
-void ElementAnimations::SetFilterMutated(LayerTreeType tree_type,
+void ElementAnimations::OnFilterAnimated(LayerTreeType tree_type,
                                          const FilterOperations& filters) {
   DCHECK(layer_id());
   DCHECK(animation_host());
@@ -207,7 +162,7 @@
       layer_id(), tree_type, filters);
 }
 
-void ElementAnimations::SetOpacityMutated(LayerTreeType tree_type,
+void ElementAnimations::OnOpacityAnimated(LayerTreeType tree_type,
                                           float opacity) {
   DCHECK(layer_id());
   DCHECK(animation_host());
@@ -216,7 +171,7 @@
       layer_id(), tree_type, opacity);
 }
 
-void ElementAnimations::SetTransformMutated(LayerTreeType tree_type,
+void ElementAnimations::OnTransformAnimated(LayerTreeType tree_type,
                                             const gfx::Transform& transform) {
   DCHECK(layer_id());
   DCHECK(animation_host());
@@ -225,7 +180,7 @@
       layer_id(), tree_type, transform);
 }
 
-void ElementAnimations::SetScrollOffsetMutated(
+void ElementAnimations::OnScrollOffsetAnimated(
     LayerTreeType tree_type,
     const gfx::ScrollOffset& scroll_offset) {
   DCHECK(layer_id());
@@ -235,7 +190,12 @@
       layer_id(), tree_type, scroll_offset);
 }
 
-void ElementAnimations::SetTransformIsPotentiallyAnimatingChanged(
+void ElementAnimations::OnAnimationWaitingForDeletion() {
+  // TODO(loyso): See Layer::OnAnimationWaitingForDeletion. But we always do
+  // PushProperties for AnimationTimelines for now.
+}
+
+void ElementAnimations::OnTransformIsPotentiallyAnimatingChanged(
     LayerTreeType tree_type,
     bool is_animating) {
   DCHECK(layer_id());
@@ -249,32 +209,24 @@
 
 void ElementAnimations::CreateActiveValueObserver() {
   DCHECK(layer_animation_controller_);
-  DCHECK(!active_value_observer_);
-  active_value_observer_ =
-      base::WrapUnique(new ValueObserver(this, LayerTreeType::ACTIVE));
-  layer_animation_controller_->AddValueObserver(active_value_observer_.get());
+  DCHECK(!needs_active_value_observations());
+  layer_animation_controller_->set_needs_active_value_observations(true);
 }
 
 void ElementAnimations::DestroyActiveValueObserver() {
-  if (layer_animation_controller_ && active_value_observer_)
-    layer_animation_controller_->RemoveValueObserver(
-        active_value_observer_.get());
-  active_value_observer_ = nullptr;
+  if (layer_animation_controller_)
+    layer_animation_controller_->set_needs_active_value_observations(false);
 }
 
 void ElementAnimations::CreatePendingValueObserver() {
   DCHECK(layer_animation_controller_);
-  DCHECK(!pending_value_observer_);
-  pending_value_observer_ =
-      base::WrapUnique(new ValueObserver(this, LayerTreeType::PENDING));
-  layer_animation_controller_->AddValueObserver(pending_value_observer_.get());
+  DCHECK(!needs_pending_value_observations());
+  layer_animation_controller_->set_needs_pending_value_observations(true);
 }
 
 void ElementAnimations::DestroyPendingValueObserver() {
-  if (layer_animation_controller_ && pending_value_observer_)
-    layer_animation_controller_->RemoveValueObserver(
-        pending_value_observer_.get());
-  pending_value_observer_ = nullptr;
+  if (layer_animation_controller_)
+    layer_animation_controller_->set_needs_pending_value_observations(false);
 }
 
 void ElementAnimations::NotifyAnimationStarted(
diff --git a/cc/animation/element_animations.h b/cc/animation/element_animations.h
index 1f60958..bff3661b 100644
--- a/cc/animation/element_animations.h
+++ b/cc/animation/element_animations.h
@@ -13,6 +13,7 @@
 #include "cc/animation/animation_curve.h"
 #include "cc/animation/animation_delegate.h"
 #include "cc/animation/layer_animation_controller.h"
+#include "cc/animation/layer_animation_value_observer.h"
 #include "cc/animation/layer_animation_value_provider.h"
 #include "cc/base/cc_export.h"
 
@@ -37,6 +38,7 @@
 // This is a CC counterpart for blink::ElementAnimations (in 1:1 relationship).
 // No pointer to/from respective blink::ElementAnimations object for now.
 class CC_EXPORT ElementAnimations : public AnimationDelegate,
+                                    public LayerAnimationValueObserver,
                                     public LayerAnimationValueProvider {
  public:
   static std::unique_ptr<ElementAnimations> Create(AnimationHost* host);
@@ -56,11 +58,11 @@
   void LayerRegistered(int layer_id, LayerTreeType tree_type);
   void LayerUnregistered(int layer_id, LayerTreeType tree_type);
 
-  bool has_active_value_observer_for_testing() const {
-    return !!active_value_observer_;
+  bool needs_active_value_observations() const {
+    return layer_animation_controller_->needs_active_value_observations();
   }
-  bool has_pending_value_observer_for_testing() const {
-    return !!pending_value_observer_;
+  bool needs_pending_value_observations() const {
+    return layer_animation_controller_->needs_pending_value_observations();
   }
 
   void AddPlayer(AnimationPlayer* player);
@@ -96,15 +98,17 @@
 
   explicit ElementAnimations(AnimationHost* host);
 
-  void SetFilterMutated(LayerTreeType tree_type,
-                        const FilterOperations& filters);
-  void SetOpacityMutated(LayerTreeType tree_type, float opacity);
-  void SetTransformMutated(LayerTreeType tree_type,
-                           const gfx::Transform& transform);
-  void SetScrollOffsetMutated(LayerTreeType tree_type,
-                              const gfx::ScrollOffset& scroll_offset);
-  void SetTransformIsPotentiallyAnimatingChanged(LayerTreeType tree_type,
-                                                 bool is_animating);
+  // LayerAnimationValueObserver implementation.
+  void OnFilterAnimated(LayerTreeType tree_type,
+                        const FilterOperations& filters) override;
+  void OnOpacityAnimated(LayerTreeType tree_type, float opacity) override;
+  void OnTransformAnimated(LayerTreeType tree_type,
+                           const gfx::Transform& transform) override;
+  void OnScrollOffsetAnimated(LayerTreeType tree_type,
+                              const gfx::ScrollOffset& scroll_offset) override;
+  void OnAnimationWaitingForDeletion() override;
+  void OnTransformIsPotentiallyAnimatingChanged(LayerTreeType tree_type,
+                                                bool is_animating) override;
 
   void CreateActiveValueObserver();
   void DestroyActiveValueObserver();
@@ -132,10 +136,6 @@
 
   std::unique_ptr<PlayersList> players_list_;
 
-  class ValueObserver;
-  std::unique_ptr<ValueObserver> active_value_observer_;
-  std::unique_ptr<ValueObserver> pending_value_observer_;
-
   // LAC is owned by ElementAnimations (1:1 relationship).
   scoped_refptr<LayerAnimationController> layer_animation_controller_;
   AnimationHost* animation_host_;
diff --git a/cc/animation/element_animations_unittest.cc b/cc/animation/element_animations_unittest.cc
index 207dd35..ed51918 100644
--- a/cc/animation/element_animations_unittest.cc
+++ b/cc/animation/element_animations_unittest.cc
@@ -40,8 +40,8 @@
   ElementAnimations* element_animations = player_->element_animations();
   EXPECT_TRUE(element_animations);
 
-  EXPECT_TRUE(element_animations->has_active_value_observer_for_testing());
-  EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing());
+  EXPECT_TRUE(element_animations->needs_active_value_observations());
+  EXPECT_FALSE(element_animations->needs_pending_value_observations());
 
   host_->PushPropertiesTo(host_impl_);
 
@@ -51,16 +51,13 @@
       player_impl_->element_animations();
   EXPECT_TRUE(element_animations_impl);
 
-  EXPECT_FALSE(
-      element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_TRUE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_FALSE(element_animations_impl->needs_active_value_observations());
+  EXPECT_TRUE(element_animations_impl->needs_pending_value_observations());
 
   // Create the layer in the impl active tree.
   client_impl_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE);
-  EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_TRUE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_TRUE(element_animations_impl->needs_active_value_observations());
+  EXPECT_TRUE(element_animations_impl->needs_pending_value_observations());
 
   EXPECT_TRUE(client_impl_.IsLayerInTree(layer_id_, LayerTreeType::ACTIVE));
   EXPECT_TRUE(client_impl_.IsLayerInTree(layer_id_, LayerTreeType::PENDING));
@@ -68,38 +65,32 @@
   // kill layer on main thread.
   client_.UnregisterLayer(layer_id_, LayerTreeType::ACTIVE);
   EXPECT_EQ(element_animations, player_->element_animations());
-  EXPECT_FALSE(element_animations->has_active_value_observer_for_testing());
-  EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing());
+  EXPECT_FALSE(element_animations->needs_active_value_observations());
+  EXPECT_FALSE(element_animations->needs_pending_value_observations());
 
   // Sync doesn't detach LayerImpl.
   host_->PushPropertiesTo(host_impl_);
   EXPECT_EQ(element_animations_impl, player_impl_->element_animations());
-  EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_TRUE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_TRUE(element_animations_impl->needs_active_value_observations());
+  EXPECT_TRUE(element_animations_impl->needs_pending_value_observations());
 
   // Kill layer on impl thread in pending tree.
   client_impl_.UnregisterLayer(layer_id_, LayerTreeType::PENDING);
   EXPECT_EQ(element_animations_impl, player_impl_->element_animations());
-  EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_FALSE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_TRUE(element_animations_impl->needs_active_value_observations());
+  EXPECT_FALSE(element_animations_impl->needs_pending_value_observations());
 
   // Kill layer on impl thread in active tree.
   client_impl_.UnregisterLayer(layer_id_, LayerTreeType::ACTIVE);
   EXPECT_EQ(element_animations_impl, player_impl_->element_animations());
-  EXPECT_FALSE(
-      element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_FALSE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_FALSE(element_animations_impl->needs_active_value_observations());
+  EXPECT_FALSE(element_animations_impl->needs_pending_value_observations());
 
   // Sync doesn't change anything.
   host_->PushPropertiesTo(host_impl_);
   EXPECT_EQ(element_animations_impl, player_impl_->element_animations());
-  EXPECT_FALSE(
-      element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_FALSE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_FALSE(element_animations_impl->needs_active_value_observations());
+  EXPECT_FALSE(element_animations_impl->needs_pending_value_observations());
 
   player_->DetachLayer();
   EXPECT_FALSE(player_->element_animations());
@@ -121,8 +112,8 @@
   ElementAnimations* element_animations = player_->element_animations();
   EXPECT_TRUE(element_animations);
 
-  EXPECT_FALSE(element_animations->has_active_value_observer_for_testing());
-  EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing());
+  EXPECT_FALSE(element_animations->needs_active_value_observations());
+  EXPECT_FALSE(element_animations->needs_pending_value_observations());
 
   host_->PushPropertiesTo(host_impl_);
 
@@ -130,26 +121,21 @@
       player_impl_->element_animations();
   EXPECT_TRUE(element_animations_impl);
 
-  EXPECT_FALSE(
-      element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_FALSE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_FALSE(element_animations_impl->needs_active_value_observations());
+  EXPECT_FALSE(element_animations_impl->needs_pending_value_observations());
 
   // Create layer.
   client_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE);
-  EXPECT_TRUE(element_animations->has_active_value_observer_for_testing());
-  EXPECT_FALSE(element_animations->has_pending_value_observer_for_testing());
+  EXPECT_TRUE(element_animations->needs_active_value_observations());
+  EXPECT_FALSE(element_animations->needs_pending_value_observations());
 
   client_impl_.RegisterLayer(layer_id_, LayerTreeType::PENDING);
-  EXPECT_FALSE(
-      element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_TRUE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_FALSE(element_animations_impl->needs_active_value_observations());
+  EXPECT_TRUE(element_animations_impl->needs_pending_value_observations());
 
   client_impl_.RegisterLayer(layer_id_, LayerTreeType::ACTIVE);
-  EXPECT_TRUE(element_animations_impl->has_active_value_observer_for_testing());
-  EXPECT_TRUE(
-      element_animations_impl->has_pending_value_observer_for_testing());
+  EXPECT_TRUE(element_animations_impl->needs_active_value_observations());
+  EXPECT_TRUE(element_animations_impl->needs_pending_value_observations());
 }
 
 TEST_F(ElementAnimationsTest, AddRemovePlayers) {
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
index c373e1fdb..b2130b8 100644
--- a/cc/animation/layer_animation_controller.cc
+++ b/cc/animation/layer_animation_controller.cc
@@ -28,8 +28,11 @@
     : host_(0),
       id_(id),
       is_active_(false),
+      value_observer_(nullptr),
       value_provider_(nullptr),
       layer_animation_delegate_(nullptr),
+      needs_active_value_observations_(false),
+      needs_pending_value_observations_(false),
       needs_to_start_animations_(false),
       scroll_offset_animation_was_interrupted_(false),
       potentially_animating_transform_for_active_observers_(false),
@@ -485,17 +488,6 @@
   }
 }
 
-void LayerAnimationController::AddValueObserver(
-    LayerAnimationValueObserver* observer) {
-  if (!value_observers_.HasObserver(observer))
-    value_observers_.AddObserver(observer);
-}
-
-void LayerAnimationController::RemoveValueObserver(
-    LayerAnimationValueObserver* observer) {
-  value_observers_.RemoveObserver(observer);
-}
-
 void LayerAnimationController::AddEventObserver(
     LayerAnimationEventObserver* observer) {
   if (!event_observers_.HasObserver(observer))
@@ -1182,114 +1174,84 @@
     float opacity,
     bool notify_active_observers,
     bool notify_pending_observers) {
-  if (value_observers_.might_have_observers()) {
-    base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        &value_observers_);
-    LayerAnimationValueObserver* obs;
-    while ((obs = it.GetNext()) != nullptr) {
-      if ((notify_active_observers && notify_pending_observers) ||
-          (notify_active_observers && obs->IsActive()) ||
-          (notify_pending_observers && !obs->IsActive()))
-        obs->OnOpacityAnimated(opacity);
-    }
-  }
+  if (!value_observer_)
+    return;
+  if (notify_active_observers && needs_active_value_observations())
+    value_observer_->OnOpacityAnimated(LayerTreeType::ACTIVE, opacity);
+  if (notify_pending_observers && needs_pending_value_observations())
+    value_observer_->OnOpacityAnimated(LayerTreeType::PENDING, opacity);
 }
 
 void LayerAnimationController::NotifyObserversTransformAnimated(
     const gfx::Transform& transform,
     bool notify_active_observers,
     bool notify_pending_observers) {
-  if (value_observers_.might_have_observers()) {
-    base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        &value_observers_);
-    LayerAnimationValueObserver* obs;
-    while ((obs = it.GetNext()) != nullptr) {
-      if ((notify_active_observers && notify_pending_observers) ||
-          (notify_active_observers && obs->IsActive()) ||
-          (notify_pending_observers && !obs->IsActive()))
-        obs->OnTransformAnimated(transform);
-    }
-  }
+  if (!value_observer_)
+    return;
+  if (notify_active_observers && needs_active_value_observations())
+    value_observer_->OnTransformAnimated(LayerTreeType::ACTIVE, transform);
+  if (notify_pending_observers && needs_pending_value_observations())
+    value_observer_->OnTransformAnimated(LayerTreeType::PENDING, transform);
 }
 
 void LayerAnimationController::NotifyObserversFilterAnimated(
     const FilterOperations& filters,
     bool notify_active_observers,
     bool notify_pending_observers) {
-  if (value_observers_.might_have_observers()) {
-    base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        &value_observers_);
-    LayerAnimationValueObserver* obs;
-    while ((obs = it.GetNext()) != nullptr) {
-      if ((notify_active_observers && notify_pending_observers) ||
-          (notify_active_observers && obs->IsActive()) ||
-          (notify_pending_observers && !obs->IsActive()))
-        obs->OnFilterAnimated(filters);
-    }
-  }
+  if (!value_observer_)
+    return;
+  if (notify_active_observers && needs_active_value_observations())
+    value_observer_->OnFilterAnimated(LayerTreeType::ACTIVE, filters);
+  if (notify_pending_observers && needs_pending_value_observations())
+    value_observer_->OnFilterAnimated(LayerTreeType::PENDING, filters);
 }
 
 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
     const gfx::ScrollOffset& scroll_offset,
     bool notify_active_observers,
     bool notify_pending_observers) {
-  if (value_observers_.might_have_observers()) {
-    base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        &value_observers_);
-    LayerAnimationValueObserver* obs;
-    while ((obs = it.GetNext()) != nullptr) {
-      if ((notify_active_observers && notify_pending_observers) ||
-          (notify_active_observers && obs->IsActive()) ||
-          (notify_pending_observers && !obs->IsActive()))
-        obs->OnScrollOffsetAnimated(scroll_offset);
-    }
-  }
+  if (!value_observer_)
+    return;
+  if (notify_active_observers && needs_active_value_observations())
+    value_observer_->OnScrollOffsetAnimated(LayerTreeType::ACTIVE,
+                                            scroll_offset);
+  if (notify_pending_observers && needs_pending_value_observations())
+    value_observer_->OnScrollOffsetAnimated(LayerTreeType::PENDING,
+                                            scroll_offset);
 }
 
 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
-  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
-                    value_observers_,
-                    OnAnimationWaitingForDeletion());
+  if (value_observer_)
+    value_observer_->OnAnimationWaitingForDeletion();
 }
 
 void LayerAnimationController::
     NotifyObserversTransformIsPotentiallyAnimatingChanged(
         bool notify_active_observers,
         bool notify_pending_observers) {
-  if (value_observers_.might_have_observers()) {
-    base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        &value_observers_);
-    LayerAnimationValueObserver* obs;
-    while ((obs = it.GetNext()) != nullptr) {
-      if (notify_active_observers && obs->IsActive())
-        obs->OnTransformIsPotentiallyAnimatingChanged(
-            potentially_animating_transform_for_active_observers_);
-      else if (notify_pending_observers && !obs->IsActive())
-        obs->OnTransformIsPotentiallyAnimatingChanged(
-            potentially_animating_transform_for_pending_observers_);
-    }
-  }
+  if (!value_observer_)
+    return;
+  if (notify_active_observers && needs_active_value_observations())
+    value_observer_->OnTransformIsPotentiallyAnimatingChanged(
+        LayerTreeType::ACTIVE,
+        potentially_animating_transform_for_active_observers_);
+  if (notify_pending_observers && needs_pending_value_observations())
+    value_observer_->OnTransformIsPotentiallyAnimatingChanged(
+        LayerTreeType::PENDING,
+        potentially_animating_transform_for_pending_observers_);
 }
 
 bool LayerAnimationController::HasValueObserver() {
-  if (value_observers_.might_have_observers()) {
-    base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        &value_observers_);
-    return it.GetNext() != nullptr;
-  }
-  return false;
+  if (!value_observer_)
+    return false;
+  return needs_active_value_observations() ||
+         needs_pending_value_observations();
 }
 
 bool LayerAnimationController::HasActiveValueObserver() {
-  if (value_observers_.might_have_observers()) {
-    base::ObserverListBase<LayerAnimationValueObserver>::Iterator it(
-        &value_observers_);
-    LayerAnimationValueObserver* obs;
-    while ((obs = it.GetNext()) != nullptr)
-      if (obs->IsActive())
-        return true;
-  }
-  return false;
+  if (!value_observer_)
+    return false;
+  return needs_active_value_observations();
 }
 
 }  // namespace cc
diff --git a/cc/animation/layer_animation_controller.h b/cc/animation/layer_animation_controller.h
index 73c7d76..323a069 100644
--- a/cc/animation/layer_animation_controller.h
+++ b/cc/animation/layer_animation_controller.h
@@ -101,8 +101,25 @@
   void NotifyAnimationPropertyUpdate(const AnimationEvent& event);
   void NotifyAnimationTakeover(const AnimationEvent& event);
 
-  void AddValueObserver(LayerAnimationValueObserver* observer);
-  void RemoveValueObserver(LayerAnimationValueObserver* observer);
+  void set_value_observer(LayerAnimationValueObserver* observer) {
+    value_observer_ = observer;
+  }
+
+  bool needs_active_value_observations() const {
+    return needs_active_value_observations_;
+  }
+  bool needs_pending_value_observations() const {
+    return needs_pending_value_observations_;
+  }
+
+  void set_needs_active_value_observations(
+      bool needs_active_value_observations) {
+    needs_active_value_observations_ = needs_active_value_observations;
+  }
+  void set_needs_pending_value_observations(
+      bool needs_pending_value_observations) {
+    needs_pending_value_observations_ = needs_pending_value_observations;
+  }
 
   void AddEventObserver(LayerAnimationEventObserver* observer);
   void RemoveEventObserver(LayerAnimationEventObserver* observer);
@@ -235,13 +252,14 @@
 
   base::TimeTicks last_tick_time_;
 
-  base::ObserverList<LayerAnimationValueObserver> value_observers_;
   base::ObserverList<LayerAnimationEventObserver> event_observers_;
-
+  LayerAnimationValueObserver* value_observer_;
   LayerAnimationValueProvider* value_provider_;
-
   AnimationDelegate* layer_animation_delegate_;
 
+  bool needs_active_value_observations_;
+  bool needs_pending_value_observations_;
+
   // Only try to start animations when new animations are added or when the
   // previous attempt at starting animations failed to start all animations.
   bool needs_to_start_animations_;
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc
index 45fe726..cbea341 100644
--- a/cc/animation/layer_animation_controller_unittest.cc
+++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -48,11 +48,14 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller_impl->set_needs_active_value_observations(true);
 
   EXPECT_FALSE(controller_impl->GetAnimation(TargetProperty::OPACITY));
 
@@ -78,13 +81,16 @@
   FakeLayerAnimationValueProvider dummy_provider_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
   controller_impl->set_value_provider(&dummy_provider_impl);
+
   FakeLayerAnimationValueObserver dummy;
   FakeLayerAnimationValueProvider dummy_provider;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
   controller->set_value_provider(&dummy_provider);
 
   EXPECT_FALSE(controller_impl->GetAnimation(TargetProperty::SCROLL_OFFSET));
@@ -135,11 +141,14 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   EXPECT_FALSE(controller_impl->GetAnimation(TargetProperty::OPACITY));
 
@@ -174,11 +183,14 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   int animation_id =
       AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
@@ -225,11 +237,15 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
+
   std::unique_ptr<AnimationEvents> events = host->CreateEvents();
 
   controller->SetAnimationHost(host.get());
@@ -305,11 +321,14 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   EXPECT_FALSE(controller_impl->GetAnimation(TargetProperty::OPACITY));
 
@@ -346,8 +365,8 @@
   EXPECT_EQ(Animation::RUNNING,
             controller->GetAnimationById(animation_id)->run_state());
 
-  EXPECT_EQ(0.3f, dummy.opacity());
-  EXPECT_EQ(0.3f, dummy_impl.opacity());
+  EXPECT_EQ(0.3f, dummy.opacity(LayerTreeType::ACTIVE));
+  EXPECT_EQ(0.3f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 
   EXPECT_EQ(kInitialTickTime,
             controller->GetAnimationById(animation_id)->start_time());
@@ -373,19 +392,23 @@
             controller_impl->GetAnimationById(animation_id)->run_state());
 
   // Opacity value doesn't depend on time if paused at specified time offset.
-  EXPECT_EQ(0.4f, dummy.opacity());
-  EXPECT_EQ(0.4f, dummy_impl.opacity());
+  EXPECT_EQ(0.4f, dummy.opacity(LayerTreeType::ACTIVE));
+  EXPECT_EQ(0.4f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) {
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
+
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
 
@@ -439,8 +462,10 @@
       LayerAnimationController::Create(0));
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
 
   AddOpacityTransitionToController(controller.get(), 1.0, 0.0f, 1.0f, false);
   controller->Animate(kInitialTickTime);
@@ -511,7 +536,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   std::unique_ptr<Animation> to_add(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)),
@@ -524,13 +550,13 @@
   EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   // A non-impl-only animation should not generate property updates.
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
@@ -542,7 +568,8 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
 
   std::unique_ptr<Animation> to_add(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)),
@@ -553,7 +580,7 @@
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy_impl.opacity());
+  EXPECT_EQ(0.f, dummy_impl.opacity(LayerTreeType::ACTIVE));
   EXPECT_EQ(1u, events->events_.size());
   const AnimationEvent* start_opacity_event =
       GetMostRecentPropertyUpdateEvent(events.get());
@@ -562,7 +589,7 @@
   controller_impl->Animate(kInitialTickTime +
                            TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
-  EXPECT_EQ(1.f, dummy_impl.opacity());
+  EXPECT_EQ(1.f, dummy_impl.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
   EXPECT_EQ(2u, events->events_.size());
   const AnimationEvent* end_opacity_event =
@@ -576,7 +603,8 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
 
   // Choose different values for x and y to avoid coincidental values in the
   // observed transforms.
@@ -603,7 +631,7 @@
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(gfx::Transform(), dummy_impl.transform());
+  EXPECT_EQ(gfx::Transform(), dummy_impl.transform(LayerTreeType::ACTIVE));
   EXPECT_EQ(1u, events->events_.size());
   const AnimationEvent* start_transform_event =
       GetMostRecentPropertyUpdateEvent(events.get());
@@ -617,7 +645,7 @@
   controller_impl->Animate(kInitialTickTime +
                            TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
-  EXPECT_EQ(expected_transform, dummy_impl.transform());
+  EXPECT_EQ(expected_transform, dummy_impl.transform(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
   EXPECT_EQ(2u, events->events_.size());
   const AnimationEvent* end_transform_event =
@@ -632,7 +660,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   std::unique_ptr<KeyframedFilterAnimationCurve> curve(
       KeyframedFilterAnimationCurve::Create());
@@ -653,22 +682,22 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(start_filters, dummy.filters());
+  EXPECT_EQ(start_filters, dummy.filters(LayerTreeType::ACTIVE));
   // A non-impl-only animation should not generate property updates.
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(1u, dummy.filters().size());
+  EXPECT_EQ(1u, dummy.filters(LayerTreeType::ACTIVE).size());
   EXPECT_EQ(FilterOperation::CreateBrightnessFilter(1.5f),
-            dummy.filters().at(0));
+            dummy.filters(LayerTreeType::ACTIVE).at(0));
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(end_filters, dummy.filters());
+  EXPECT_EQ(end_filters, dummy.filters(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
@@ -680,7 +709,8 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
 
   std::unique_ptr<KeyframedFilterAnimationCurve> curve(
       KeyframedFilterAnimationCurve::Create());
@@ -704,7 +734,7 @@
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(start_filters, dummy_impl.filters());
+  EXPECT_EQ(start_filters, dummy_impl.filters(LayerTreeType::ACTIVE));
   EXPECT_EQ(1u, events->events_.size());
   const AnimationEvent* start_filter_event =
       GetMostRecentPropertyUpdateEvent(events.get());
@@ -715,7 +745,7 @@
   controller_impl->Animate(kInitialTickTime +
                            TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
-  EXPECT_EQ(end_filters, dummy_impl.filters());
+  EXPECT_EQ(end_filters, dummy_impl.filters(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
   EXPECT_EQ(2u, events->events_.size());
   const AnimationEvent* end_filter_event =
@@ -730,7 +760,9 @@
   FakeLayerAnimationValueProvider dummy_provider_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   controller_impl->set_value_provider(&dummy_provider_impl);
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
@@ -738,7 +770,8 @@
   FakeLayerAnimationValueProvider dummy_provider;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
   controller->set_value_provider(&dummy_provider);
 
   gfx::ScrollOffset initial_value(100.f, 300.f);
@@ -767,12 +800,12 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(initial_value, dummy.scroll_offset());
+  EXPECT_EQ(initial_value, dummy.scroll_offset(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(initial_value, dummy_impl.scroll_offset());
+  EXPECT_EQ(initial_value, dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   // Scroll offset animations should not generate property updates.
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
@@ -781,25 +814,27 @@
   controller->Animate(kInitialTickTime + duration / 2);
   controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f), dummy.scroll_offset());
+  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f),
+                      dummy.scroll_offset(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime + duration / 2);
   controller_impl->UpdateState(true, events.get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f),
-                      dummy_impl.scroll_offset());
+                      dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
   controller_impl->Animate(kInitialTickTime + duration);
   controller_impl->UpdateState(true, events.get());
-  EXPECT_VECTOR2DF_EQ(target_value, dummy_impl.scroll_offset());
+  EXPECT_VECTOR2DF_EQ(target_value,
+                      dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
   controller->Animate(kInitialTickTime + duration);
   controller->UpdateState(true, nullptr);
-  EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset());
+  EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -810,14 +845,17 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeLayerAnimationValueObserver dummy;
   FakeLayerAnimationValueProvider dummy_provider;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
   controller->set_value_provider(&dummy_provider);
 
   gfx::ScrollOffset initial_value(500.f, 100.f);
@@ -846,12 +884,12 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(initial_value, dummy.scroll_offset());
+  EXPECT_EQ(initial_value, dummy.scroll_offset(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(initial_value, dummy_impl.scroll_offset());
+  EXPECT_EQ(initial_value, dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   // Scroll offset animations should not generate property updates.
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
@@ -860,25 +898,27 @@
   controller->Animate(kInitialTickTime + duration / 2);
   controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(400.f, 150.f), dummy.scroll_offset());
+  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(400.f, 150.f),
+                      dummy.scroll_offset(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime + duration / 2);
   controller_impl->UpdateState(true, events.get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(400.f, 150.f),
-                      dummy_impl.scroll_offset());
+                      dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
   controller_impl->Animate(kInitialTickTime + duration);
   controller_impl->UpdateState(true, events.get());
-  EXPECT_VECTOR2DF_EQ(target_value, dummy_impl.scroll_offset());
+  EXPECT_VECTOR2DF_EQ(target_value,
+                      dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
   controller->Animate(kInitialTickTime + duration);
   controller->UpdateState(true, nullptr);
-  EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset());
+  EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -886,7 +926,8 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
 
@@ -906,7 +947,7 @@
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(initial_value, dummy_impl.scroll_offset());
+  EXPECT_EQ(initial_value, dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   // Scroll offset animations should not generate property updates.
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
@@ -917,13 +958,14 @@
   controller_impl->Animate(kInitialTickTime + duration / 2);
   controller_impl->UpdateState(true, events.get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f),
-                      dummy_impl.scroll_offset());
+                      dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
   controller_impl->Animate(kInitialTickTime + duration);
   controller_impl->UpdateState(true, events.get());
-  EXPECT_VECTOR2DF_EQ(target_value, dummy_impl.scroll_offset());
+  EXPECT_VECTOR2DF_EQ(target_value,
+                      dummy_impl.scroll_offset(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
@@ -934,7 +976,8 @@
   FakeLayerAnimationValueProvider dummy_provider_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
   controller_impl->set_value_provider(&dummy_provider_impl);
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
@@ -942,7 +985,8 @@
   FakeLayerAnimationValueProvider dummy_provider;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
   controller->set_value_provider(&dummy_provider);
 
   // First test the 1-argument version of RemoveAnimation.
@@ -1089,7 +1133,9 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeAnimationDelegate delegate;
@@ -1125,11 +1171,15 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
+
   FakeAnimationDelegate delegate;
   controller->set_layer_animation_delegate(&delegate);
 
@@ -1177,11 +1227,15 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
+
   FakeLayerAnimationEventObserver observer;
   controller->AddEventObserver(&observer);
 
@@ -1219,7 +1273,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   std::unique_ptr<Animation> to_add(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)),
@@ -1232,15 +1287,15 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   // Send the synchronized start time.
   controller->NotifyAnimationStarted(
@@ -1248,7 +1303,7 @@
                      kInitialTickTime + TimeDelta::FromMilliseconds(2000)));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(5000));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -1259,7 +1314,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
 
@@ -1279,7 +1335,7 @@
 
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
@@ -1287,10 +1343,10 @@
   EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
 
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(0.5f, dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -1301,14 +1357,16 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
+
   controller->AddAnimation(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)),
       1, TargetProperty::OPACITY));
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   std::unique_ptr<Animation> to_add(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)),
@@ -1321,10 +1379,10 @@
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1500));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(0.5f, dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -1336,7 +1394,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   controller->AddAnimation(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1)), 1,
@@ -1350,17 +1409,17 @@
 
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_TRUE(controller->HasActiveAnimation());
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   // Should not have started the float transition yet.
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   // The float animation should have started at time 1 and should be done.
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -1373,7 +1432,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   controller->AddAnimation(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeTransformTransition(2)), 1,
@@ -1389,7 +1449,7 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   // The opacity animation should have finished at time 1, but the group
   // of animations with id 1 don't finish until time 2 because of the length
   // of the transform animation.
@@ -1397,13 +1457,13 @@
   controller->UpdateState(true, events.get());
   // Should not have started the float transition yet.
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   // The second opacity animation should start at time 2 and should be done by
   // time 3.
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(0.5f, dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -1414,7 +1474,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   std::unique_ptr<Animation> to_add(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)),
@@ -1425,32 +1486,32 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.25f, dummy.opacity());
+  EXPECT_EQ(0.25f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.75f, dummy.opacity());
+  EXPECT_EQ(0.75f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.25f, dummy.opacity());
+  EXPECT_EQ(0.25f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.75f, dummy.opacity());
+  EXPECT_EQ(0.75f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   controller->UpdateState(true, events.get());
   EXPECT_FALSE(controller->HasActiveAnimation());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   // Just be extra sure.
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(4000));
   controller->UpdateState(true, events.get());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 // Test that an infinitely looping animation does indeed go until aborted.
@@ -1460,7 +1521,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   std::unique_ptr<Animation> to_add(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)),
@@ -1471,33 +1533,33 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.25f, dummy.opacity());
+  EXPECT_EQ(0.25f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.75f, dummy.opacity());
+  EXPECT_EQ(0.75f, dummy.opacity(LayerTreeType::ACTIVE));
 
   controller->Animate(kInitialTickTime +
                       TimeDelta::FromMilliseconds(1073741824250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.25f, dummy.opacity());
+  EXPECT_EQ(0.25f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime +
                       TimeDelta::FromMilliseconds(1073741824750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.75f, dummy.opacity());
+  EXPECT_EQ(0.75f, dummy.opacity(LayerTreeType::ACTIVE));
 
   EXPECT_TRUE(controller->GetAnimation(TargetProperty::OPACITY));
   controller->GetAnimation(TargetProperty::OPACITY)
       ->SetRunState(Animation::ABORTED,
                     kInitialTickTime + TimeDelta::FromMilliseconds(750));
   EXPECT_FALSE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.75f, dummy.opacity());
+  EXPECT_EQ(0.75f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 // Test that pausing and resuming work as expected.
@@ -1507,7 +1569,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   controller->AddAnimation(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)),
@@ -1516,11 +1579,11 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.5f, dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
 
   EXPECT_TRUE(controller->GetAnimation(TargetProperty::OPACITY));
   controller->GetAnimation(TargetProperty::OPACITY)
@@ -1530,7 +1593,7 @@
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1024000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.5f, dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
 
   EXPECT_TRUE(controller->GetAnimation(TargetProperty::OPACITY));
   controller->GetAnimation(TargetProperty::OPACITY)
@@ -1539,12 +1602,12 @@
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1024250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.75f, dummy.opacity());
+  EXPECT_EQ(0.75f, dummy.opacity(LayerTreeType::ACTIVE));
 
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1024500));
   controller->UpdateState(true, events.get());
   EXPECT_FALSE(controller->HasActiveAnimation());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, AbortAGroupedAnimation) {
@@ -1553,7 +1616,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   const int animation_id = 2;
   controller->AddAnimation(Animation::Create(
@@ -1569,11 +1633,11 @@
   controller->Animate(kInitialTickTime);
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.5f, dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
 
   EXPECT_TRUE(controller->GetAnimationById(animation_id));
   controller->GetAnimationById(animation_id)
@@ -1582,24 +1646,26 @@
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(!controller->HasActiveAnimation());
-  EXPECT_EQ(0.75f, dummy.opacity());
+  EXPECT_EQ(0.75f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, PushUpdatesWhenSynchronizedStartTimeNeeded) {
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   std::unique_ptr<Animation> to_add(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)),
@@ -1631,7 +1697,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   std::unique_ptr<Animation> first_animation(CreateAnimation(
       std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1)), 1,
@@ -1661,13 +1728,13 @@
 
   // The float transition should still be at its starting point.
   EXPECT_TRUE(controller->HasActiveAnimation());
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   controller->UpdateState(true, events.get());
 
   // The float tranisition should now be done.
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
@@ -1677,9 +1744,9 @@
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeLayerAnimationValueObserver dummy;
-  FakeInactiveLayerAnimationValueObserver pending_dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
+  controller->set_value_observer(&dummy);
 
   const int id = 1;
   controller->AddAnimation(CreateAnimation(
@@ -1694,7 +1761,7 @@
   EXPECT_EQ(Animation::WAITING_FOR_TARGET_AVAILABILITY,
             controller->GetAnimation(TargetProperty::OPACITY)->run_state());
 
-  controller->AddValueObserver(&pending_dummy);
+  controller->set_needs_pending_value_observations(true);
 
   // With only a pending observer, the animation should progress to the
   // STARTING state and get ticked at its starting point, but should not
@@ -1704,7 +1771,7 @@
   EXPECT_EQ(0u, events->events_.size());
   EXPECT_EQ(Animation::STARTING,
             controller->GetAnimation(TargetProperty::OPACITY)->run_state());
-  EXPECT_EQ(0.5f, pending_dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::PENDING));
 
   // Even when already in the STARTING state, the animation should stay
   // there, and shouldn't be ticked past its starting point.
@@ -1713,9 +1780,9 @@
   EXPECT_EQ(0u, events->events_.size());
   EXPECT_EQ(Animation::STARTING,
             controller->GetAnimation(TargetProperty::OPACITY)->run_state());
-  EXPECT_EQ(0.5f, pending_dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::PENDING));
 
-  controller->AddValueObserver(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   // Now that an active observer has been added, the animation should still
   // initially tick at its starting point, but should now progress to RUNNING.
@@ -1724,13 +1791,13 @@
   EXPECT_EQ(1u, events->events_.size());
   EXPECT_EQ(Animation::RUNNING,
             controller->GetAnimation(TargetProperty::OPACITY)->run_state());
-  EXPECT_EQ(0.5f, pending_dummy.opacity());
-  EXPECT_EQ(0.5f, dummy.opacity());
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
 
   // The animation should now tick past its starting point.
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3500));
-  EXPECT_NE(0.5f, pending_dummy.opacity());
-  EXPECT_NE(0.5f, dummy.opacity());
+  EXPECT_NE(0.5f, dummy.opacity(LayerTreeType::PENDING));
+  EXPECT_NE(0.5f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, TransformAnimationBounds) {
@@ -1809,7 +1876,8 @@
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   // Start with several animations, and allow some of them to reach the finished
   // state.
@@ -1856,11 +1924,13 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   int animation_id =
       AddOpacityTransitionToController(controller.get(), 1.0, 0.f, 1.f, false);
@@ -1891,11 +1961,13 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
   FakeAnimationDelegate delegate;
   controller->set_layer_animation_delegate(&delegate);
 
@@ -1946,11 +2018,13 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
   FakeAnimationDelegate delegate_impl;
   controller_impl->set_layer_animation_delegate(&delegate_impl);
   FakeAnimationDelegate delegate;
@@ -2014,7 +2088,8 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
 
   const int group_id = 1;
 
@@ -2071,7 +2146,8 @@
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
 
   // Add two animations with the same group id.
   std::unique_ptr<Animation> first_animation(CreateAnimation(
@@ -2561,15 +2637,16 @@
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeLayerAnimationValueObserver dummy_impl;
-  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
-  controller_impl->AddValueObserver(&pending_dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+  controller_impl->set_needs_pending_value_observations(true);
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
   int animation_id =
@@ -2599,8 +2676,8 @@
 
   // Since the animation hasn't been activated, only the pending observer
   // should have been ticked.
-  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
-  EXPECT_EQ(0.f, dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
   EXPECT_TRUE(controller_impl->GetAnimationById(animation_id)
@@ -2616,23 +2693,25 @@
   // RUNNING state and the active observer should start to get ticked.
   EXPECT_EQ(Animation::RUNNING,
             controller_impl->GetAnimationById(animation_id)->run_state());
-  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
-  EXPECT_EQ(0.5f, dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, ActivationBetweenAnimateAndUpdateState) {
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeLayerAnimationValueObserver dummy_impl;
-  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
-  controller_impl->AddValueObserver(&pending_dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+  controller_impl->set_needs_pending_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   int animation_id =
       AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, true);
@@ -2651,8 +2730,8 @@
 
   // Since the animation hasn't been activated, only the pending observer
   // should have been ticked.
-  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
-  EXPECT_EQ(0.f, dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
   EXPECT_TRUE(controller_impl->GetAnimationById(animation_id)
@@ -2670,39 +2749,41 @@
   controller_impl->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
 
   // Both observers should have been ticked.
-  EXPECT_EQ(0.75f, pending_dummy_impl.opacity());
-  EXPECT_EQ(0.75f, dummy_impl.opacity());
+  EXPECT_EQ(0.75f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.75f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest,
      ObserverNotifiedWhenTransformIsPotentiallyAnimatingChanges) {
   AnimationEvents events;
-  FakeLayerAnimationValueObserver active_dummy_impl;
-  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+  FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&active_dummy_impl);
-  controller_impl->AddValueObserver(&pending_dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+  controller_impl->set_needs_pending_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
-  EXPECT_FALSE(dummy.transform_is_animating());
-  EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
-  EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+  EXPECT_FALSE(dummy.transform_is_animating(LayerTreeType::ACTIVE));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   // Case 1: An animation that's allowed to run until its finish point.
   AddAnimatedTransformToController(controller.get(), 1.0, 1, 1);
-  EXPECT_TRUE(dummy.transform_is_animating());
+  EXPECT_TRUE(dummy.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
-  EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
-  EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
-  EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
-  EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, &events);
@@ -2713,19 +2794,19 @@
   // Finish the animation.
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, nullptr);
-  EXPECT_FALSE(dummy.transform_is_animating());
+  EXPECT_FALSE(dummy.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
 
   // controller_impl hasn't yet ticked at/past the end of the animation.
-  EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
-  EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime +
                            TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, &events);
-  EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
-  EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller->NotifyAnimationFinished(events.events_[0]);
   events.events_.clear();
@@ -2733,15 +2814,15 @@
   // Case 2: An animation that's removed before it finishes.
   int animation_id =
       AddAnimatedTransformToController(controller.get(), 10.0, 2, 2);
-  EXPECT_TRUE(dummy.transform_is_animating());
+  EXPECT_TRUE(dummy.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
-  EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
-  EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
-  EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
-  EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime +
                            TimeDelta::FromMilliseconds(2000));
@@ -2751,27 +2832,27 @@
   events.events_.clear();
 
   controller->RemoveAnimation(animation_id);
-  EXPECT_FALSE(dummy.transform_is_animating());
+  EXPECT_FALSE(dummy.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
-  EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
-  EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
-  EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
-  EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   // Case 3: An animation that's aborted before it finishes.
   animation_id = AddAnimatedTransformToController(controller.get(), 10.0, 3, 3);
-  EXPECT_TRUE(dummy.transform_is_animating());
+  EXPECT_TRUE(dummy.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
-  EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
-  EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
-  EXPECT_TRUE(pending_dummy_impl.transform_is_animating());
-  EXPECT_TRUE(active_dummy_impl.transform_is_animating());
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_TRUE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime +
                            TimeDelta::FromMilliseconds(3000));
@@ -2781,62 +2862,66 @@
   events.events_.clear();
 
   controller_impl->AbortAnimations(TargetProperty::TRANSFORM);
-  EXPECT_FALSE(pending_dummy_impl.transform_is_animating());
-  EXPECT_FALSE(active_dummy_impl.transform_is_animating());
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::PENDING));
+  EXPECT_FALSE(dummy_impl.transform_is_animating(LayerTreeType::ACTIVE));
 
   controller_impl->Animate(kInitialTickTime +
                            TimeDelta::FromMilliseconds(4000));
   controller_impl->UpdateState(true, &events);
 
   controller->NotifyAnimationAborted(events.events_[0]);
-  EXPECT_FALSE(dummy.transform_is_animating());
+  EXPECT_FALSE(dummy.transform_is_animating(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, ClippedOpacityValues) {
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   AddOpacityTransitionToController(controller.get(), 1, 1.f, 2.f, true);
 
   controller->Animate(kInitialTickTime);
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   // Opacity values are clipped [0,1]
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, ClippedNegativeOpacityValues) {
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   AddOpacityTransitionToController(controller.get(), 1, 0.f, -2.f, true);
 
   controller->Animate(kInitialTickTime);
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   // Opacity values are clipped [0,1]
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, PushedDeletedAnimationWaitsForActivation) {
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeLayerAnimationValueObserver dummy_impl;
-  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
-  controller_impl->AddValueObserver(&pending_dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+  controller_impl->set_needs_pending_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   int animation_id =
       AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, true);
@@ -2847,8 +2932,8 @@
   controller_impl->UpdateState(true, events.get());
   EXPECT_EQ(Animation::RUNNING,
             controller_impl->GetAnimationById(animation_id)->run_state());
-  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
-  EXPECT_EQ(0.5f, dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 
   EXPECT_TRUE(controller_impl->GetAnimationById(animation_id)
                   ->affects_pending_observers());
@@ -2870,8 +2955,8 @@
   controller_impl->UpdateState(true, events.get());
 
   // Only the active observer should have been ticked.
-  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
-  EXPECT_EQ(0.75f, dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.75f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
 
@@ -2885,15 +2970,17 @@
   std::unique_ptr<AnimationEvents> events(
       base::WrapUnique(new AnimationEvents));
   FakeLayerAnimationValueObserver dummy_impl;
-  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
-  controller_impl->AddValueObserver(&dummy_impl);
-  controller_impl->AddValueObserver(&pending_dummy_impl);
+  controller_impl->set_value_observer(&dummy_impl);
+  controller_impl->set_needs_active_value_observations(true);
+  controller_impl->set_needs_pending_value_observations(true);
+
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   int first_animation_id =
       AddOpacityTransitionToController(controller.get(), 1, 0.f, 1.f, true);
@@ -2935,8 +3022,8 @@
 
   // The active observer should have been ticked by the original animation,
   // and the pending observer should have been ticked by the new animation.
-  EXPECT_EQ(1.f, pending_dummy_impl.opacity());
-  EXPECT_EQ(0.5f, dummy_impl.opacity());
+  EXPECT_EQ(1.f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(0.5f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 
   controller_impl->ActivateAnimations();
 
@@ -2957,15 +3044,16 @@
   EXPECT_EQ(
       Animation::RUNNING,
       controller_impl->GetAnimationById(second_animation_id)->run_state());
-  EXPECT_EQ(1.f, pending_dummy_impl.opacity());
-  EXPECT_EQ(1.f, dummy_impl.opacity());
+  EXPECT_EQ(1.f, dummy_impl.opacity(LayerTreeType::PENDING));
+  EXPECT_EQ(1.f, dummy_impl.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, TestIsCurrentlyAnimatingProperty) {
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   // Create an animation that initially affects only pending observers.
   std::unique_ptr<Animation> animation(CreateAnimation(
@@ -3018,7 +3106,7 @@
   EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
       TargetProperty::FILTER, LayerAnimationController::ObserverType::ACTIVE));
 
-  EXPECT_EQ(0.f, dummy.opacity());
+  EXPECT_EQ(0.f, dummy.opacity(LayerTreeType::ACTIVE));
 
   // Tick past the end of the animation.
   controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1100));
@@ -3034,14 +3122,15 @@
   EXPECT_FALSE(controller->IsCurrentlyAnimatingProperty(
       TargetProperty::FILTER, LayerAnimationController::ObserverType::ACTIVE));
 
-  EXPECT_EQ(1.f, dummy.opacity());
+  EXPECT_EQ(1.f, dummy.opacity(LayerTreeType::ACTIVE));
 }
 
 TEST(LayerAnimationControllerTest, TestIsAnimatingPropertyTimeOffsetFillMode) {
   FakeLayerAnimationValueObserver dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
+  controller->set_value_observer(&dummy);
+  controller->set_needs_active_value_observations(true);
 
   // Create an animation that initially affects only pending observers, and has
   // a start delay of 2 seconds.
diff --git a/cc/animation/layer_animation_value_observer.h b/cc/animation/layer_animation_value_observer.h
index 092b53b..5228356 100644
--- a/cc/animation/layer_animation_value_observer.h
+++ b/cc/animation/layer_animation_value_observer.h
@@ -6,6 +6,7 @@
 #define CC_ANIMATION_LAYER_ANIMATION_VALUE_OBSERVER_H_
 
 #include "cc/base/cc_export.h"
+#include "cc/trees/mutator_host_client.h"
 
 namespace gfx {
 class ScrollOffset;
@@ -20,14 +21,17 @@
  public:
   virtual ~LayerAnimationValueObserver() {}
 
-  virtual void OnFilterAnimated(const FilterOperations& filters) = 0;
-  virtual void OnOpacityAnimated(float opacity) = 0;
-  virtual void OnTransformAnimated(const gfx::Transform& transform) = 0;
+  virtual void OnFilterAnimated(LayerTreeType tree_type,
+                                const FilterOperations& filters) = 0;
+  virtual void OnOpacityAnimated(LayerTreeType tree_type, float opacity) = 0;
+  virtual void OnTransformAnimated(LayerTreeType tree_type,
+                                   const gfx::Transform& transform) = 0;
   virtual void OnScrollOffsetAnimated(
+      LayerTreeType tree_type,
       const gfx::ScrollOffset& scroll_offset) = 0;
   virtual void OnAnimationWaitingForDeletion() = 0;
-  virtual void OnTransformIsPotentiallyAnimatingChanged(bool is_animating) = 0;
-  virtual bool IsActive() const = 0;
+  virtual void OnTransformIsPotentiallyAnimatingChanged(LayerTreeType tree_type,
+                                                        bool is_animating) = 0;
 };
 
 }  // namespace cc
diff --git a/cc/raster/bitmap_tile_task_worker_pool.cc b/cc/raster/bitmap_tile_task_worker_pool.cc
index a24b1a2..7a29df2 100644
--- a/cc/raster/bitmap_tile_task_worker_pool.cc
+++ b/cc/raster/bitmap_tile_task_worker_pool.cc
@@ -16,7 +16,6 @@
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/debug/traced_value.h"
 #include "cc/playback/raster_source.h"
-#include "cc/raster/raster_buffer.h"
 #include "cc/resources/platform_color.h"
 #include "cc/resources/resource.h"
 
@@ -133,6 +132,10 @@
   return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
 }
 
+RasterBufferProvider* BitmapTileTaskWorkerPool::AsRasterBufferProvider() {
+  return this;
+}
+
 std::unique_ptr<RasterBuffer> BitmapTileTaskWorkerPool::AcquireBufferForRaster(
     const Resource* resource,
     uint64_t resource_content_id,
diff --git a/cc/raster/bitmap_tile_task_worker_pool.h b/cc/raster/bitmap_tile_task_worker_pool.h
index 4f6d99d..0a492a9b 100644
--- a/cc/raster/bitmap_tile_task_worker_pool.h
+++ b/cc/raster/bitmap_tile_task_worker_pool.h
@@ -23,7 +23,7 @@
 
 class CC_EXPORT BitmapTileTaskWorkerPool : public TileTaskWorkerPool,
                                            public TileTaskRunner,
-                                           public TileTaskClient {
+                                           public RasterBufferProvider {
  public:
   ~BitmapTileTaskWorkerPool() override;
 
@@ -41,8 +41,9 @@
   void CheckForCompletedTasks() override;
   ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
+  RasterBufferProvider* AsRasterBufferProvider() override;
 
-  // Overridden from TileTaskClient:
+  // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t resource_content_id,
diff --git a/cc/raster/gpu_tile_task_worker_pool.cc b/cc/raster/gpu_tile_task_worker_pool.cc
index 858094e..f34cf7af 100644
--- a/cc/raster/gpu_tile_task_worker_pool.cc
+++ b/cc/raster/gpu_tile_task_worker_pool.cc
@@ -13,7 +13,6 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/playback/raster_source.h"
 #include "cc/raster/gpu_rasterizer.h"
-#include "cc/raster/raster_buffer.h"
 #include "cc/raster/scoped_gpu_raster.h"
 #include "cc/resources/resource.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -168,6 +167,10 @@
   return false;
 }
 
+RasterBufferProvider* GpuTileTaskWorkerPool::AsRasterBufferProvider() {
+  return this;
+}
+
 void GpuTileTaskWorkerPool::CompleteTasks(const Task::Vector& tasks) {
   for (auto& task : tasks) {
     TileTask* tile_task = static_cast<TileTask*>(task.get());
diff --git a/cc/raster/gpu_tile_task_worker_pool.h b/cc/raster/gpu_tile_task_worker_pool.h
index 6943a271..5ebd623 100644
--- a/cc/raster/gpu_tile_task_worker_pool.h
+++ b/cc/raster/gpu_tile_task_worker_pool.h
@@ -18,7 +18,7 @@
 
 class CC_EXPORT GpuTileTaskWorkerPool : public TileTaskWorkerPool,
                                         public TileTaskRunner,
-                                        public TileTaskClient {
+                                        public RasterBufferProvider {
  public:
   ~GpuTileTaskWorkerPool() override;
 
@@ -39,8 +39,9 @@
   void CheckForCompletedTasks() override;
   ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
+  RasterBufferProvider* AsRasterBufferProvider() override;
 
-  // Overridden from TileTaskClient:
+  // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t resource_content_id,
diff --git a/cc/raster/one_copy_tile_task_worker_pool.cc b/cc/raster/one_copy_tile_task_worker_pool.cc
index 47e4c01c..1c14fb94 100644
--- a/cc/raster/one_copy_tile_task_worker_pool.cc
+++ b/cc/raster/one_copy_tile_task_worker_pool.cc
@@ -12,7 +12,6 @@
 
 #include "base/macros.h"
 #include "cc/base/math_util.h"
-#include "cc/raster/raster_buffer.h"
 #include "cc/raster/staging_buffer_pool.h"
 #include "cc/resources/platform_color.h"
 #include "cc/resources/resource_format.h"
@@ -172,6 +171,10 @@
   return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
 }
 
+RasterBufferProvider* OneCopyTileTaskWorkerPool::AsRasterBufferProvider() {
+  return this;
+}
+
 std::unique_ptr<RasterBuffer> OneCopyTileTaskWorkerPool::AcquireBufferForRaster(
     const Resource* resource,
     uint64_t resource_content_id,
diff --git a/cc/raster/one_copy_tile_task_worker_pool.h b/cc/raster/one_copy_tile_task_worker_pool.h
index e362bdd..5d6162d 100644
--- a/cc/raster/one_copy_tile_task_worker_pool.h
+++ b/cc/raster/one_copy_tile_task_worker_pool.h
@@ -20,7 +20,7 @@
 
 class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool,
                                             public TileTaskRunner,
-                                            public TileTaskClient {
+                                            public RasterBufferProvider {
  public:
   ~OneCopyTileTaskWorkerPool() override;
 
@@ -43,8 +43,9 @@
   void CheckForCompletedTasks() override;
   ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
+  RasterBufferProvider* AsRasterBufferProvider() override;
 
-  // Overridden from TileTaskClient:
+  // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t resource_content_id,
diff --git a/cc/raster/raster_buffer.h b/cc/raster/raster_buffer.h
index 04972f9d..54c5b9e 100644
--- a/cc/raster/raster_buffer.h
+++ b/cc/raster/raster_buffer.h
@@ -12,6 +12,20 @@
 #include "ui/gfx/geometry/rect.h"
 
 namespace cc {
+class RasterBuffer;
+class Resource;
+
+class CC_EXPORT RasterBufferProvider {
+ public:
+  virtual std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
+      const Resource* resource,
+      uint64_t resource_content_id,
+      uint64_t previous_content_id) = 0;
+  virtual void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) = 0;
+
+ protected:
+  virtual ~RasterBufferProvider() {}
+};
 
 class CC_EXPORT RasterBuffer {
  public:
diff --git a/cc/raster/tile_task_runner.h b/cc/raster/tile_task_runner.h
index fe04575..dc1586a 100644
--- a/cc/raster/tile_task_runner.h
+++ b/cc/raster/tile_task_runner.h
@@ -10,33 +10,18 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "cc/raster/raster_buffer.h"
 #include "cc/raster/task_graph_runner.h"
 #include "cc/resources/resource_format.h"
 
 namespace cc {
-class ImageDecodeTask;
-class RasterTask;
-class Resource;
-class RasterBuffer;
-
-class CC_EXPORT TileTaskClient {
- public:
-  virtual std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
-      const Resource* resource,
-      uint64_t resource_content_id,
-      uint64_t previous_content_id) = 0;
-  virtual void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) = 0;
-
- protected:
-  virtual ~TileTaskClient() {}
-};
 
 class CC_EXPORT TileTask : public Task {
  public:
   typedef std::vector<scoped_refptr<TileTask>> Vector;
 
-  virtual void ScheduleOnOriginThread(TileTaskClient* client) = 0;
-  virtual void CompleteOnOriginThread(TileTaskClient* client) = 0;
+  virtual void ScheduleOnOriginThread(RasterBufferProvider* provider) = 0;
+  virtual void CompleteOnOriginThread(RasterBufferProvider* provider) = 0;
 
   void WillSchedule();
   void DidSchedule();
@@ -116,6 +101,9 @@
   // Determine if the resource requires swizzling.
   virtual bool GetResourceRequiresSwizzle(bool must_support_alpha) const = 0;
 
+  // Downcasting routine for RasterBufferProvider interface.
+  virtual RasterBufferProvider* AsRasterBufferProvider() = 0;
+
  protected:
   // Check if resource format matches output format.
   static bool ResourceFormatRequiresSwizzle(ResourceFormat format);
diff --git a/cc/raster/tile_task_worker_pool.cc b/cc/raster/tile_task_worker_pool.cc
index 9333d5a..1e41942 100644
--- a/cc/raster/tile_task_worker_pool.cc
+++ b/cc/raster/tile_task_worker_pool.cc
@@ -19,8 +19,9 @@
 TileTaskWorkerPool::~TileTaskWorkerPool() {}
 
 // static
-void TileTaskWorkerPool::ScheduleTasksOnOriginThread(TileTaskClient* client,
-                                                     TaskGraph* graph) {
+void TileTaskWorkerPool::ScheduleTasksOnOriginThread(
+    RasterBufferProvider* provider,
+    TaskGraph* graph) {
   TRACE_EVENT0("cc", "TileTaskWorkerPool::ScheduleTasksOnOriginThread");
 
   for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin();
@@ -30,7 +31,7 @@
 
     if (!task->HasBeenScheduled()) {
       task->WillSchedule();
-      task->ScheduleOnOriginThread(client);
+      task->ScheduleOnOriginThread(provider);
       task->DidSchedule();
     }
   }
diff --git a/cc/raster/tile_task_worker_pool.h b/cc/raster/tile_task_worker_pool.h
index e56807f..e05256ef 100644
--- a/cc/raster/tile_task_worker_pool.h
+++ b/cc/raster/tile_task_worker_pool.h
@@ -26,7 +26,7 @@
 
   // Utility function that can be used to call ::ScheduleOnOriginThread() for
   // each task in |graph|.
-  static void ScheduleTasksOnOriginThread(TileTaskClient* client,
+  static void ScheduleTasksOnOriginThread(RasterBufferProvider* provider,
                                           TaskGraph* graph);
 
   // Utility function that will create a temporary bitmap and copy pixels to
diff --git a/cc/raster/tile_task_worker_pool_perftest.cc b/cc/raster/tile_task_worker_pool_perftest.cc
index d2c7e6c5..2335ca7 100644
--- a/cc/raster/tile_task_worker_pool_perftest.cc
+++ b/cc/raster/tile_task_worker_pool_perftest.cc
@@ -15,7 +15,6 @@
 #include "cc/raster/gpu_rasterizer.h"
 #include "cc/raster/gpu_tile_task_worker_pool.h"
 #include "cc/raster/one_copy_tile_task_worker_pool.h"
-#include "cc/raster/raster_buffer.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
 #include "cc/raster/tile_task_runner.h"
 #include "cc/raster/tile_task_worker_pool.h"
@@ -132,8 +131,10 @@
   void RunOnWorkerThread() override {}
 
   // Overridden from TileTask:
-  void ScheduleOnOriginThread(TileTaskClient* client) override {}
-  void CompleteOnOriginThread(TileTaskClient* client) override { Reset(); }
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {}
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {
+    Reset();
+  }
 
   void Reset() {
     did_run_ = false;
@@ -157,12 +158,12 @@
   void RunOnWorkerThread() override {}
 
   // Overridden from TileTask:
-  void ScheduleOnOriginThread(TileTaskClient* client) override {
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {
     // No tile ids are given to support partial updates.
-    raster_buffer_ = client->AcquireBufferForRaster(resource_.get(), 0, 0);
+    raster_buffer_ = provider->AcquireBufferForRaster(resource_.get(), 0, 0);
   }
-  void CompleteOnOriginThread(TileTaskClient* client) override {
-    client->ReleaseBufferForRaster(std::move(raster_buffer_));
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {
+    provider->ReleaseBufferForRaster(std::move(raster_buffer_));
     Reset();
   }
 
diff --git a/cc/raster/tile_task_worker_pool_unittest.cc b/cc/raster/tile_task_worker_pool_unittest.cc
index 919a885..e3d2ab5d 100644
--- a/cc/raster/tile_task_worker_pool_unittest.cc
+++ b/cc/raster/tile_task_worker_pool_unittest.cc
@@ -22,7 +22,6 @@
 #include "cc/raster/gpu_rasterizer.h"
 #include "cc/raster/gpu_tile_task_worker_pool.h"
 #include "cc/raster/one_copy_tile_task_worker_pool.h"
-#include "cc/raster/raster_buffer.h"
 #include "cc/raster/synchronous_task_graph_runner.h"
 #include "cc/raster/tile_task_runner.h"
 #include "cc/raster/zero_copy_tile_task_worker_pool.h"
@@ -73,13 +72,13 @@
   }
 
   // Overridden from TileTask:
-  void ScheduleOnOriginThread(TileTaskClient* client) override {
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {
     // The raster buffer has no tile ids associated with it for partial update,
     // so doesn't need to provide a valid dirty rect.
-    raster_buffer_ = client->AcquireBufferForRaster(resource_, 0, 0);
+    raster_buffer_ = provider->AcquireBufferForRaster(resource_, 0, 0);
   }
-  void CompleteOnOriginThread(TileTaskClient* client) override {
-    client->ReleaseBufferForRaster(std::move(raster_buffer_));
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {
+    provider->ReleaseBufferForRaster(std::move(raster_buffer_));
     reply_.Run(!HasFinishedRunning());
   }
 
diff --git a/cc/raster/zero_copy_tile_task_worker_pool.cc b/cc/raster/zero_copy_tile_task_worker_pool.cc
index 203415a..afbf04f 100644
--- a/cc/raster/zero_copy_tile_task_worker_pool.cc
+++ b/cc/raster/zero_copy_tile_task_worker_pool.cc
@@ -14,7 +14,6 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/debug/traced_value.h"
-#include "cc/raster/raster_buffer.h"
 #include "cc/resources/platform_color.h"
 #include "cc/resources/resource.h"
 #include "ui/gfx/buffer_format_util.h"
@@ -141,6 +140,10 @@
   return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
 }
 
+RasterBufferProvider* ZeroCopyTileTaskWorkerPool::AsRasterBufferProvider() {
+  return this;
+}
+
 std::unique_ptr<RasterBuffer>
 ZeroCopyTileTaskWorkerPool::AcquireBufferForRaster(
     const Resource* resource,
diff --git a/cc/raster/zero_copy_tile_task_worker_pool.h b/cc/raster/zero_copy_tile_task_worker_pool.h
index d8d99481..b5c31b15 100644
--- a/cc/raster/zero_copy_tile_task_worker_pool.h
+++ b/cc/raster/zero_copy_tile_task_worker_pool.h
@@ -24,7 +24,7 @@
 
 class CC_EXPORT ZeroCopyTileTaskWorkerPool : public TileTaskWorkerPool,
                                              public TileTaskRunner,
-                                             public TileTaskClient {
+                                             public RasterBufferProvider {
  public:
   ~ZeroCopyTileTaskWorkerPool() override;
 
@@ -43,8 +43,9 @@
   void CheckForCompletedTasks() override;
   ResourceFormat GetResourceFormat(bool must_support_alpha) const override;
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override;
+  RasterBufferProvider* AsRasterBufferProvider() override;
 
-  // Overridden from TileTaskClient:
+  // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t resource_content_id,
diff --git a/cc/test/animation_test_common.cc b/cc/test/animation_test_common.cc
index 58d737e..48a515b 100644
--- a/cc/test/animation_test_common.cc
+++ b/cc/test/animation_test_common.cc
@@ -211,30 +211,50 @@
   return (1.0 - progress) * from_ + progress * to_;
 }
 
+gfx::ScrollOffset FakeLayerAnimationValueProvider::ScrollOffsetForAnimation()
+    const {
+  return scroll_offset_;
+}
+
 FakeLayerAnimationValueObserver::FakeLayerAnimationValueObserver()
-    : opacity_(0.0f),
-      animation_waiting_for_deletion_(false),
-      transform_is_animating_(false) {}
+    : animation_waiting_for_deletion_(false) {
+  opacity_[ToIndex(LayerTreeType::ACTIVE)] = 0.0f;
+  opacity_[ToIndex(LayerTreeType::PENDING)] = 0.0f;
+
+  transform_is_animating_[ToIndex(LayerTreeType::ACTIVE)] = false;
+  transform_is_animating_[ToIndex(LayerTreeType::PENDING)] = false;
+}
 
 FakeLayerAnimationValueObserver::~FakeLayerAnimationValueObserver() {}
 
-void FakeLayerAnimationValueObserver::OnFilterAnimated(
-    const FilterOperations& filters) {
-  filters_ = filters;
+int FakeLayerAnimationValueObserver::ToIndex(LayerTreeType tree_type) {
+  int index = static_cast<int>(tree_type);
+  DCHECK_GE(index, 0);
+  DCHECK_LE(index, 1);
+  return index;
 }
 
-void FakeLayerAnimationValueObserver::OnOpacityAnimated(float opacity) {
-  opacity_ = opacity;
+void FakeLayerAnimationValueObserver::OnFilterAnimated(
+    LayerTreeType tree_type,
+    const FilterOperations& filters) {
+  filters_[ToIndex(tree_type)] = filters;
+}
+
+void FakeLayerAnimationValueObserver::OnOpacityAnimated(LayerTreeType tree_type,
+                                                        float opacity) {
+  opacity_[ToIndex(tree_type)] = opacity;
 }
 
 void FakeLayerAnimationValueObserver::OnTransformAnimated(
+    LayerTreeType tree_type,
     const gfx::Transform& transform) {
-  transform_ = transform;
+  transform_[ToIndex(tree_type)] = transform;
 }
 
 void FakeLayerAnimationValueObserver::OnScrollOffsetAnimated(
+    LayerTreeType tree_type,
     const gfx::ScrollOffset& scroll_offset) {
-  scroll_offset_ = scroll_offset;
+  scroll_offset_[ToIndex(tree_type)] = scroll_offset;
 }
 
 void FakeLayerAnimationValueObserver::OnAnimationWaitingForDeletion() {
@@ -242,21 +262,9 @@
 }
 
 void FakeLayerAnimationValueObserver::OnTransformIsPotentiallyAnimatingChanged(
+    LayerTreeType tree_type,
     bool is_animating) {
-  transform_is_animating_ = is_animating;
-}
-
-bool FakeLayerAnimationValueObserver::IsActive() const {
-  return true;
-}
-
-bool FakeInactiveLayerAnimationValueObserver::IsActive() const {
-  return false;
-}
-
-gfx::ScrollOffset FakeLayerAnimationValueProvider::ScrollOffsetForAnimation()
-    const {
-  return scroll_offset_;
+  transform_is_animating_[ToIndex(tree_type)] = is_animating;
 }
 
 std::unique_ptr<AnimationCurve> FakeFloatTransition::Clone() const {
diff --git a/cc/test/animation_test_common.h b/cc/test/animation_test_common.h
index b63010e..4d0b779 100644
--- a/cc/test/animation_test_common.h
+++ b/cc/test/animation_test_common.h
@@ -81,39 +81,48 @@
   FakeLayerAnimationValueObserver();
   ~FakeLayerAnimationValueObserver() override;
 
-  // LayerAnimationValueObserver implementation
-  void OnFilterAnimated(const FilterOperations& filters) override;
-  void OnOpacityAnimated(float opacity) override;
-  void OnTransformAnimated(const gfx::Transform& transform) override;
-  void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) override;
+  // LayerAnimationValueObserver implementation.
+  void OnFilterAnimated(LayerTreeType tree_type,
+                        const FilterOperations& filters) override;
+  void OnOpacityAnimated(LayerTreeType tree_type, float opacity) override;
+  void OnTransformAnimated(LayerTreeType tree_type,
+                           const gfx::Transform& transform) override;
+  void OnScrollOffsetAnimated(LayerTreeType tree_type,
+                              const gfx::ScrollOffset& scroll_offset) override;
   void OnAnimationWaitingForDeletion() override;
-  void OnTransformIsPotentiallyAnimatingChanged(bool is_animating) override;
-  bool IsActive() const override;
+  void OnTransformIsPotentiallyAnimatingChanged(LayerTreeType tree_type,
+                                                bool is_animating) override;
 
-  const FilterOperations& filters() const { return filters_; }
-  float opacity() const  { return opacity_; }
-  const gfx::Transform& transform() const { return transform_; }
-  gfx::ScrollOffset scroll_offset() { return scroll_offset_; }
+  const FilterOperations& filters(LayerTreeType tree_type) const {
+    return filters_[ToIndex(tree_type)];
+  }
+  float opacity(LayerTreeType tree_type) const {
+    return opacity_[ToIndex(tree_type)];
+  }
+  const gfx::Transform& transform(LayerTreeType tree_type) const {
+    return transform_[ToIndex(tree_type)];
+  }
+  gfx::ScrollOffset scroll_offset(LayerTreeType tree_type) {
+    return scroll_offset_[ToIndex(tree_type)];
+  }
 
   bool animation_waiting_for_deletion() {
     return animation_waiting_for_deletion_;
   }
 
-  bool transform_is_animating() { return transform_is_animating_; }
+  bool transform_is_animating(LayerTreeType tree_type) {
+    return transform_is_animating_[ToIndex(tree_type)];
+  }
 
  private:
-  FilterOperations filters_;
-  float opacity_;
-  gfx::Transform transform_;
-  gfx::ScrollOffset scroll_offset_;
-  bool animation_waiting_for_deletion_;
-  bool transform_is_animating_;
-};
+  static int ToIndex(LayerTreeType tree_type);
 
-class FakeInactiveLayerAnimationValueObserver
-    : public FakeLayerAnimationValueObserver {
- public:
-  bool IsActive() const override;
+  FilterOperations filters_[2];
+  float opacity_[2];
+  gfx::Transform transform_[2];
+  gfx::ScrollOffset scroll_offset_[2];
+  bool animation_waiting_for_deletion_;
+  bool transform_is_animating_[2];
 };
 
 class FakeLayerAnimationValueProvider : public LayerAnimationValueProvider {
diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc
index b76cd176..ebc0b70a 100644
--- a/cc/test/fake_tile_manager.cc
+++ b/cc/test/fake_tile_manager.cc
@@ -19,7 +19,8 @@
 
 namespace {
 
-class FakeTileTaskRunnerImpl : public TileTaskRunner, public TileTaskClient {
+class FakeTileTaskRunnerImpl : public TileTaskRunner,
+                               public RasterBufferProvider {
  public:
   // Overridden from TileTaskRunner:
   void Shutdown() override {}
@@ -52,8 +53,9 @@
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override {
     return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
   }
+  RasterBufferProvider* AsRasterBufferProvider() override { return this; }
 
-  // Overridden from TileTaskClient:
+  // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t resource_content_id,
diff --git a/cc/tiles/gpu_image_decode_controller.cc b/cc/tiles/gpu_image_decode_controller.cc
index 91f0a33e..ab683d6 100644
--- a/cc/tiles/gpu_image_decode_controller.cc
+++ b/cc/tiles/gpu_image_decode_controller.cc
@@ -77,8 +77,8 @@
   }
 
   // Overridden from TileTask:
-  void ScheduleOnOriginThread(TileTaskClient* client) override {}
-  void CompleteOnOriginThread(TileTaskClient* client) override {
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {}
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {
     controller_->DecodeTaskCompleted(image_);
   }
 
@@ -118,8 +118,8 @@
     controller_->UploadImage(image_);
   }
 
-  void ScheduleOnOriginThread(TileTaskClient* client) override {}
-  void CompleteOnOriginThread(TileTaskClient* client) override {
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {}
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {
     controller_->UploadTaskCompleted(image_);
   }
 
diff --git a/cc/tiles/software_image_decode_controller.cc b/cc/tiles/software_image_decode_controller.cc
index 5f19a38e..f05bb5d 100644
--- a/cc/tiles/software_image_decode_controller.cc
+++ b/cc/tiles/software_image_decode_controller.cc
@@ -77,8 +77,8 @@
   }
 
   // Overridden from TileTask:
-  void ScheduleOnOriginThread(TileTaskClient* client) override {}
-  void CompleteOnOriginThread(TileTaskClient* client) override {
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {}
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {
     controller_->RemovePendingTask(image_key_);
   }
 
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index cabc5d286..cec859ff 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -98,13 +98,13 @@
   }
 
   // Overridden from TileTask:
-  void ScheduleOnOriginThread(TileTaskClient* client) override {
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {
     DCHECK(!raster_buffer_);
-    raster_buffer_ = client->AcquireBufferForRaster(
+    raster_buffer_ = provider->AcquireBufferForRaster(
         resource_, resource_content_id_, previous_content_id_);
   }
-  void CompleteOnOriginThread(TileTaskClient* client) override {
-    client->ReleaseBufferForRaster(std::move(raster_buffer_));
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {
+    provider->ReleaseBufferForRaster(std::move(raster_buffer_));
     reply_.Run(!HasFinishedRunning());
   }
 
@@ -252,8 +252,8 @@
   }
 
   // Overridden from TileTask:
-  void ScheduleOnOriginThread(TileTaskClient* client) override {}
-  void CompleteOnOriginThread(TileTaskClient* client) override {}
+  void ScheduleOnOriginThread(RasterBufferProvider* provider) override {}
+  void CompleteOnOriginThread(RasterBufferProvider* provider) override {}
 
  protected:
   ~TaskSetFinishedTaskImpl() override {}
diff --git a/cc/tiles/tile_manager_perftest.cc b/cc/tiles/tile_manager_perftest.cc
index d4ef597..e5c7106 100644
--- a/cc/tiles/tile_manager_perftest.cc
+++ b/cc/tiles/tile_manager_perftest.cc
@@ -37,7 +37,8 @@
 static const int kWarmupRuns = 5;
 static const int kTimeCheckInterval = 10;
 
-class FakeTileTaskRunnerImpl : public TileTaskRunner, public TileTaskClient {
+class FakeTileTaskRunnerImpl : public TileTaskRunner,
+                               public RasterBufferProvider {
  public:
   // Overridden from TileTaskRunner:
   void Shutdown() override {}
@@ -69,8 +70,9 @@
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override {
     return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha));
   }
+  RasterBufferProvider* AsRasterBufferProvider() override { return this; }
 
-  // Overridden from TileTaskClient:
+  // Overridden from RasterBufferProvider:
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t new_content_id,
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index 7a12156..2da6e3e 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -1828,7 +1828,7 @@
 }
 
 // Fake TileTaskRunner that just no-ops all calls.
-class FakeTileTaskRunner : public TileTaskRunner, public TileTaskClient {
+class FakeTileTaskRunner : public TileTaskRunner, public RasterBufferProvider {
  public:
   FakeTileTaskRunner() {}
   ~FakeTileTaskRunner() override {}
@@ -1842,10 +1842,11 @@
   bool GetResourceRequiresSwizzle(bool must_support_alpha) const override {
     return false;
   }
+  RasterBufferProvider* AsRasterBufferProvider() override { return this; }
 
   void ScheduleTasks(TaskGraph* graph) override {}
 
-  // TileTaskClient methods.
+  // RasterBufferProvider methods.
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t resource_content_id,
@@ -1949,7 +1950,7 @@
     }
   }
 
-  // TileTaskClient methods.
+  // RasterBufferProvider methods.
   std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
       const Resource* resource,
       uint64_t resource_content_id,
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index 30715fb..9547562 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1069,26 +1069,26 @@
   void DidCommit() override {
     switch (layer_tree_host()->source_frame_number()) {
       case 0:
-        EXPECT_TRUE(player_->element_animations()
-                        ->has_active_value_observer_for_testing());
-        EXPECT_FALSE(player_->element_animations()
-                         ->has_pending_value_observer_for_testing());
+        EXPECT_TRUE(
+            player_->element_animations()->needs_active_value_observations());
+        EXPECT_FALSE(
+            player_->element_animations()->needs_pending_value_observations());
         EXPECT_TRUE(layer_tree_host()->animation_host()->NeedsAnimateLayers());
         break;
       case 1:
         layer_->RemoveFromParent();
-        EXPECT_FALSE(player_->element_animations()
-                         ->has_active_value_observer_for_testing());
-        EXPECT_FALSE(player_->element_animations()
-                         ->has_pending_value_observer_for_testing());
+        EXPECT_FALSE(
+            player_->element_animations()->needs_active_value_observations());
+        EXPECT_FALSE(
+            player_->element_animations()->needs_pending_value_observations());
         EXPECT_TRUE(layer_tree_host()->animation_host()->NeedsAnimateLayers());
         break;
       case 2:
         layer_tree_host()->root_layer()->AddChild(layer_);
-        EXPECT_TRUE(player_->element_animations()
-                        ->has_active_value_observer_for_testing());
-        EXPECT_FALSE(player_->element_animations()
-                         ->has_pending_value_observer_for_testing());
+        EXPECT_TRUE(
+            player_->element_animations()->needs_active_value_observations());
+        EXPECT_FALSE(
+            player_->element_animations()->needs_pending_value_observations());
         EXPECT_TRUE(layer_tree_host()->animation_host()->NeedsAnimateLayers());
         break;
     }
@@ -1103,17 +1103,17 @@
     switch (host_impl->active_tree()->source_frame_number()) {
       case 0:
         EXPECT_TRUE(player_impl->element_animations()
-                        ->has_active_value_observer_for_testing());
+                        ->needs_active_value_observations());
         EXPECT_TRUE(host_impl->animation_host()->NeedsAnimateLayers());
         break;
       case 1:
         EXPECT_FALSE(player_impl->element_animations()
-                         ->has_active_value_observer_for_testing());
+                         ->needs_active_value_observations());
         EXPECT_TRUE(host_impl->animation_host()->NeedsAnimateLayers());
         break;
       case 2:
         EXPECT_TRUE(player_impl->element_animations()
-                        ->has_active_value_observer_for_testing());
+                        ->needs_active_value_observations());
         EXPECT_TRUE(host_impl->animation_host()->NeedsAnimateLayers());
         EndTest();
         break;
diff --git a/chrome/VERSION b/chrome/VERSION
index fd788fa..5c6acd7 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=52
 MINOR=0
-BUILD=2711
+BUILD=2712
 PATCH=0
diff --git a/chrome/android/java/res/drawable/bg_ntp_search_box.xml b/chrome/android/java/res/drawable/bg_ntp_search_box.xml
index e487ebb6..c30801dc 100644
--- a/chrome/android/java/res/drawable/bg_ntp_search_box.xml
+++ b/chrome/android/java/res/drawable/bg_ntp_search_box.xml
@@ -11,7 +11,7 @@
         android:width="1px"
         android:color="#b26d6d6d" />
     <solid
-        android:color="@android:color/transparent" />
+        android:color="@color/ntp_bg" />
     <padding
         android:left="1px"
         android:top="1px"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index dd0955ea..651d186 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -415,8 +415,15 @@
         // percentage if some basic view properties are sane.
         View wrapperView = mUseCardsUi ? mRecyclerView : mScrollView;
         if (wrapperView.getHeight() != 0 && mSearchBoxView.getTop() != 0) {
-            int scrollY = getVerticalScroll();
-            percentage = Math.max(0f, Math.min(1f, scrollY / (float) mSearchBoxView.getTop()));
+            // getVerticalScroll is valid only for the RecyclerView if the first item is visible.
+            // Luckily, if the first item is not visible, we know the toolbar transition should
+            // be 100%.
+            if (mUseCardsUi && !mRecyclerView.isFirstItemVisible()) {
+                percentage = 1f;
+            } else {
+                int scrollY = getVerticalScroll();
+                percentage = Math.max(0f, Math.min(1f, scrollY / (float) mSearchBoxView.getTop()));
+            }
         }
 
         updateVisualsForToolbarTransition(percentage);
@@ -427,12 +434,63 @@
     }
 
     private void initializeSearchBoxRecyclerViewScrollHandling() {
+        final Runnable mSnapScrollRunnable = new Runnable() {
+            @Override
+            public void run() {
+                assert mPendingSnapScroll;
+
+                // These calculations only work if the first item is visible (since
+                // computeVerticalScrollOffset only takes into account visible items).
+                // Luckily, we only need to perform the calculations if the first item is visible.
+                if (!mRecyclerView.isFirstItemVisible()) return;
+                int currentScroll = mRecyclerView.computeVerticalScrollOffset();
+
+                // Scroll to hide all of content view off the top of the page.
+                // We subtract mContentView.getPaddingTop() to offset the contents below the
+                // search box.
+                int targetScroll = mContentView.getHeight() - mContentView.getPaddingTop();
+
+                if (currentScroll > 0 && currentScroll < targetScroll) {
+                    if (currentScroll < mSearchBoxView.getTop()) {
+                        // Scroll to the top.
+                        mRecyclerView.smoothScrollBy(0, -currentScroll);
+                    } else {
+                        // Scroll to the articles.
+                        mRecyclerView.smoothScrollBy(0, targetScroll - currentScroll);
+                    }
+                }
+
+                mPendingSnapScroll = false;
+            }
+        };
+
         mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
             @Override
             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+                if (mPendingSnapScroll) {
+                    mRecyclerView.removeCallbacks(mSnapScrollRunnable);
+                    mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
+                }
                 updateSearchBoxOnScroll();
             }
         });
+
+        mRecyclerView.setOnTouchListener(new OnTouchListener() {
+            @Override
+            @SuppressLint("ClickableViewAccessibility")
+            public boolean onTouch(View v, MotionEvent event) {
+                mRecyclerView.removeCallbacks(mSnapScrollRunnable);
+
+                if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
+                        || event.getActionMasked() == MotionEvent.ACTION_UP) {
+                    mPendingSnapScroll = true;
+                    mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
+                } else {
+                    mPendingSnapScroll = false;
+                }
+                return false;
+            }
+        });
     }
 
     private void initializeSearchBoxScrollHandling() {
@@ -462,7 +520,6 @@
             @Override
             @SuppressLint("ClickableViewAccessibility")
             public boolean onTouch(View v, MotionEvent event) {
-                if (mScrollView.getHandler() == null) return false;
                 mScrollView.removeCallbacks(mSnapScrollRunnable);
 
                 if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
index eb1397a..ac67695 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
@@ -5,7 +5,9 @@
 package org.chromium.chrome.browser.ntp.cards;
 
 import android.content.Context;
+import android.graphics.PointF;
 import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.LinearSmoothScroller;
 import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
@@ -19,19 +21,8 @@
  * New Tab page receives focus when clicked.
  */
 public class NewTabPageRecyclerView extends RecyclerView {
-    /**
-     * Listener for scroll changes.
-     */
-    public interface OnScrollListener {
-        /**
-         * Triggered when the scroll changes.  See ScrollView#onScrollChanged for more
-         * details.
-         */
-        void onScrollChanged(int l, int t, int oldl, int oldt);
-    }
-
     private GestureDetector mGestureDetector;
-    private OnScrollListener mOnScrollListener;
+    private LinearLayoutManagerWithSmoothScroller mLayoutManager;
 
     /**
      * Constructor needed to inflate from XML.
@@ -48,7 +39,12 @@
                         return retVal;
                     }
                 });
-        setLayoutManager(new LinearLayoutManager(getContext()));
+        mLayoutManager = new LinearLayoutManagerWithSmoothScroller(getContext());
+        setLayoutManager(mLayoutManager);
+    }
+
+    public boolean isFirstItemVisible() {
+        return mLayoutManager.findFirstVisibleItemPosition() == 0;
     }
 
     @Override
@@ -66,20 +62,6 @@
         return super.onTouchEvent(ev);
     }
 
-    /**
-     * Sets the listener to be notified of scroll changes.
-     * @param listener The listener to be updated on scroll changes.
-     */
-    public void setOnScrollListener(OnScrollListener listener) {
-        mOnScrollListener = listener;
-    }
-
-    @Override
-    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
-        super.onScrollChanged(l, t, oldl, oldt);
-        if (mOnScrollListener != null) mOnScrollListener.onScrollChanged(l, t, oldl, oldt);
-    }
-
     @Override
     public void focusableViewAvailable(View v) {
         // To avoid odd jumps during NTP animation transitions, we do not attempt to give focus
@@ -90,8 +72,36 @@
 
     @Override
     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
-        // Fixes lanscape transitions when unfocusing the URL bar: crbug.com/288546
+        // Fixes landscape transitions when unfocusing the URL bar: crbug.com/288546
         outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
         return super.onCreateInputConnection(outAttrs);
     }
+
+    private static class LinearLayoutManagerWithSmoothScroller extends LinearLayoutManager {
+        private final Context mContext;
+
+        public LinearLayoutManagerWithSmoothScroller(Context context) {
+            super(context);
+            mContext = context;
+        }
+
+        @Override
+        public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
+                                           int position) {
+            LinearSmoothScroller scroller = new LinearSmoothScroller(mContext) {
+                @Override
+                public PointF computeScrollVectorForPosition(int targetPosition) {
+                    return LinearLayoutManagerWithSmoothScroller.this
+                            .computeScrollVectorForPosition(targetPosition);
+                }
+
+                @Override
+                protected int getVerticalSnapPreference() {
+                    return SNAP_TO_START;
+                }
+            };
+            scroller.setTargetPosition(position);
+            startSmoothScroll(scroller);
+        }
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkUtilsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkUtilsTest.java
index e6013d4..b3cc006 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkUtilsTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkUtilsTest.java
@@ -12,6 +12,7 @@
 import android.content.Intent;
 
 import org.chromium.base.BaseChromiumApplication;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.bookmarks.BookmarkType;
@@ -41,8 +42,13 @@
         MockitoAnnotations.initMocks(this);
     }
 
-    @Test
-    @Feature({"Bookmark"})
+
+    /*
+    * @Test
+    * @Feature({"Bookmark"})
+    * Bug=crbug.com/604025
+    */
+    @DisabledTest
     public void testStartEditActivityWithoutWebContents() {
         BookmarkId bookmarkId = new BookmarkId(12345L, BookmarkType.NORMAL);
         BookmarkUtils.startEditActivity(mContext, bookmarkId, null /* webContents */);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index de1ef4f..97758e22c 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7344,6 +7344,18 @@
         <message name="IDS_PASSWORD_MANAGER_TOOLTIP_MANAGE" desc="Text for the 'Manage Passwords' icon's 'saving passwords' state">
           Manage your passwords
         </message>
+        <message name="IDS_PASSWORD_MANAGER_IMPORT_BUTTON" desc="The label of the button for importing passwords. The button appears next to the list of saved passwords in Chrome's settings.">
+          Import
+        </message>
+        <message name="IDS_PASSWORD_MANAGER_EXPORT_BUTTON" desc="The label of the button for exporting passwords. The button appears next to the list of saved passwords in Chrome's settings.">
+          Export
+        </message>
+        <message name="IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE" desc="The Title of the file selection dialog for importing password">
+          Import Passwords To Chrome
+        </message>
+        <message name="IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE" desc="The Title of the file selection dialog for exporting password">
+          Export Passwords From Chrome
+        </message>
       </if>
       <if expr="is_android">
         <message name="IDS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Mobile: Button text for the 'Save Password' infobar's 'Remember password' option">
diff --git a/chrome/browser/android/ntp/most_visited_sites.cc b/chrome/browser/android/ntp/most_visited_sites.cc
index 25fb37c..6a42bd4 100644
--- a/chrome/browser/android/ntp/most_visited_sites.cc
+++ b/chrome/browser/android/ntp/most_visited_sites.cc
@@ -162,6 +162,40 @@
   return url1.host() == url2.host() && url1.path() == url2.path();
 }
 
+class JavaObserverBridge : public MostVisitedSitesObserver {
+ public:
+  JavaObserverBridge(JNIEnv* env, const JavaParamRef<jobject>& obj)
+      : observer_(env, obj) {}
+
+  void OnMostVisitedURLsAvailable(
+      const std::vector<base::string16>& titles,
+      const std::vector<std::string>& urls,
+      const std::vector<std::string>& whitelist_icon_paths) override {
+    JNIEnv* env = AttachCurrentThread();
+    DCHECK_EQ(titles.size(), urls.size());
+    Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable(
+        env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(),
+        ToJavaArrayOfStrings(env, urls).obj(),
+        ToJavaArrayOfStrings(env, whitelist_icon_paths).obj());
+  }
+
+  void OnPopularURLsAvailable(
+      const std::vector<std::string>& urls,
+      const std::vector<std::string>& favicon_urls,
+      const std::vector<std::string>& large_icon_urls) override {
+    JNIEnv* env = AttachCurrentThread();
+    Java_MostVisitedURLsObserver_onPopularURLsAvailable(
+        env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(),
+        ToJavaArrayOfStrings(env, favicon_urls).obj(),
+        ToJavaArrayOfStrings(env, large_icon_urls).obj());
+  }
+
+ private:
+  ScopedJavaGlobalRef<jobject> observer_;
+
+  DISALLOW_COPY_AND_ASSIGN(JavaObserverBridge);
+};
+
 }  // namespace
 
 MostVisitedSites::Suggestion::Suggestion() : provider_index(-1) {}
@@ -215,7 +249,15 @@
     const JavaParamRef<jobject>& obj,
     const JavaParamRef<jobject>& j_observer,
     jint num_sites) {
-  observer_.Reset(env, j_observer);
+  SetMostVisitedURLsObserver(
+      std::unique_ptr<MostVisitedSitesObserver>(
+          new JavaObserverBridge(env, j_observer)),
+      num_sites);
+}
+
+void MostVisitedSites::SetMostVisitedURLsObserver(
+      std::unique_ptr<MostVisitedSitesObserver> observer, int num_sites) {
+  observer_ = std::move(observer);
   num_sites_ = num_sites;
 
   if (ShouldShowPopularSites() &&
@@ -256,30 +298,39 @@
   suggestions_service->FetchSuggestionsData();
 }
 
+static void CallJavaWithBitmap(
+    std::unique_ptr<ScopedJavaGlobalRef<jobject>> j_callback,
+    bool is_local_thumbnail,
+    const SkBitmap* bitmap);
+
 void MostVisitedSites::GetURLThumbnail(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     const JavaParamRef<jstring>& j_url,
     const JavaParamRef<jobject>& j_callback_obj) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::unique_ptr<ScopedJavaGlobalRef<jobject>> j_callback(
-      new ScopedJavaGlobalRef<jobject>());
-  j_callback->Reset(env, j_callback_obj);
-
+      new ScopedJavaGlobalRef<jobject>(env, j_callback_obj));
+  auto callback = base::Bind(&CallJavaWithBitmap, base::Passed(&j_callback));
   GURL url(ConvertJavaStringToUTF8(env, j_url));
+  GetURLThumbnail(url, callback);
+}
+
+void MostVisitedSites::GetURLThumbnail(
+    const GURL& url,
+    const ThumbnailCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_refptr<TopSites> top_sites(TopSitesFactory::GetForProfile(profile_));
 
   BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::DB, FROM_HERE,
       base::Bind(&MaybeFetchLocalThumbnail, url, top_sites),
       base::Bind(&MostVisitedSites::OnLocalThumbnailFetched,
-                 weak_ptr_factory_.GetWeakPtr(), url,
-                 base::Passed(&j_callback)));
+                 weak_ptr_factory_.GetWeakPtr(), url, callback));
 }
 
 void MostVisitedSites::OnLocalThumbnailFetched(
     const GURL& url,
-    std::unique_ptr<ScopedJavaGlobalRef<jobject>> j_callback,
+    const ThumbnailCallback& callback,
     std::unique_ptr<SkBitmap> bitmap) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!bitmap.get()) {
@@ -301,26 +352,31 @@
         return suggestions_service->GetPageThumbnailWithURL(
             url, it->thumbnail_url,
             base::Bind(&MostVisitedSites::OnObtainedThumbnail,
-                       weak_ptr_factory_.GetWeakPtr(), false,
-                       base::Passed(&j_callback)));
+                       weak_ptr_factory_.GetWeakPtr(), false, callback));
       }
     }
     if (mv_source_ == SUGGESTIONS_SERVICE) {
       return suggestions_service->GetPageThumbnail(
           url, base::Bind(&MostVisitedSites::OnObtainedThumbnail,
-                          weak_ptr_factory_.GetWeakPtr(), false,
-                          base::Passed(&j_callback)));
+                          weak_ptr_factory_.GetWeakPtr(), false, callback));
     }
   }
-  OnObtainedThumbnail(true, std::move(j_callback), url, bitmap.get());
+  OnObtainedThumbnail(true, callback, url, bitmap.get());
 }
 
 void MostVisitedSites::OnObtainedThumbnail(
     bool is_local_thumbnail,
-    std::unique_ptr<ScopedJavaGlobalRef<jobject>> j_callback,
+    const ThumbnailCallback& callback,
     const GURL& url,
     const SkBitmap* bitmap) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  callback.Run(is_local_thumbnail, bitmap);
+}
+
+static void CallJavaWithBitmap(
+    std::unique_ptr<ScopedJavaGlobalRef<jobject>> j_callback,
+    bool is_local_thumbnail,
+    const SkBitmap* bitmap) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> j_bitmap;
   if (bitmap)
@@ -335,7 +391,11 @@
     const JavaParamRef<jstring>& j_url,
     jboolean add_url) {
   GURL url(ConvertJavaStringToUTF8(env, j_url));
+  AddOrRemoveBlacklistedUrl(url, add_url);
+}
 
+void MostVisitedSites::AddOrRemoveBlacklistedUrl(
+    const GURL& url, bool add_url) {
   // Always blacklist in the local TopSites.
   scoped_refptr<TopSites> top_sites = TopSitesFactory::GetForProfile(profile_);
   if (top_sites) {
@@ -363,7 +423,11 @@
   std::vector<int> tile_types;
   base::android::JavaIntArrayToIntVector(env, jtile_types, &tile_types);
   DCHECK_EQ(current_suggestions_.size(), tile_types.size());
+  RecordTileTypeMetrics(tile_types);
+}
 
+void MostVisitedSites::RecordTileTypeMetrics(
+    const std::vector<int>& tile_types) {
   int counts_per_type[NUM_TILE_TYPES] = {0};
   for (size_t i = 0; i < tile_types.size(); ++i) {
     int tile_type = tile_types[i];
@@ -387,6 +451,10 @@
     const JavaParamRef<jobject>& obj,
     jint index,
     jint tile_type) {
+  RecordOpenedMostVisitedItem(index, tile_type);
+}
+
+void MostVisitedSites::RecordOpenedMostVisitedItem(int index, int tile_type) {
   DCHECK_GE(index, 0);
   DCHECK_LT(index, static_cast<int>(current_suggestions_.size()));
   std::string histogram = base::StringPrintf(
@@ -804,7 +872,7 @@
     recorded_uma_ = true;
   }
 
-  if (observer_.is_null())
+  if (!observer_)
     return;
 
   std::vector<base::string16> titles;
@@ -817,12 +885,8 @@
     urls.push_back(suggestion->url.spec());
     whitelist_icon_paths.push_back(suggestion->whitelist_icon_path.value());
   }
-  JNIEnv* env = AttachCurrentThread();
-  DCHECK_EQ(titles.size(), urls.size());
-  Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable(
-      env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(),
-      ToJavaArrayOfStrings(env, urls).obj(),
-      ToJavaArrayOfStrings(env, whitelist_icon_paths).obj());
+
+  observer_->OnMostVisitedURLsAvailable(titles, urls, whitelist_icon_paths);
 }
 
 void MostVisitedSites::OnPopularSitesAvailable(bool success) {
@@ -833,7 +897,7 @@
     return;
   }
 
-  if (observer_.is_null())
+  if (!observer_)
     return;
 
   std::vector<std::string> urls;
@@ -844,11 +908,7 @@
     favicon_urls.push_back(popular_site.favicon_url.spec());
     large_icon_urls.push_back(popular_site.large_icon_url.spec());
   }
-  JNIEnv* env = AttachCurrentThread();
-  Java_MostVisitedURLsObserver_onPopularURLsAvailable(
-      env, observer_.obj(), ToJavaArrayOfStrings(env, urls).obj(),
-      ToJavaArrayOfStrings(env, favicon_urls).obj(),
-      ToJavaArrayOfStrings(env, large_icon_urls).obj());
+  observer_->OnPopularURLsAvailable(urls, favicon_urls, large_icon_urls);
   QueryMostVisitedURLs();
 }
 
diff --git a/chrome/browser/android/ntp/most_visited_sites.h b/chrome/browser/android/ntp/most_visited_sites.h
index 548db8c3..f16b5ea 100644
--- a/chrome/browser/android/ntp/most_visited_sites.h
+++ b/chrome/browser/android/ntp/most_visited_sites.h
@@ -37,22 +37,41 @@
 class PopularSites;
 class Profile;
 
+// The observer to be notified when the list of most visited sites changes.
+class MostVisitedSitesObserver {
+ public:
+  virtual ~MostVisitedSitesObserver() {}
+
+  virtual void OnMostVisitedURLsAvailable(
+      const std::vector<base::string16>& titles,
+      const std::vector<std::string>& urls,
+      const std::vector<std::string>& whitelist_icon_paths) = 0;
+  virtual void OnPopularURLsAvailable(
+      const std::vector<std::string>& urls,
+      const std::vector<std::string>& favicon_urls,
+      const std::vector<std::string>& large_icon_urls) = 0;
+};
+
 // Provides the list of most visited sites and their thumbnails to Java.
 class MostVisitedSites : public history::TopSitesObserver,
                          public SupervisedUserServiceObserver {
  public:
   explicit MostVisitedSites(Profile* profile);
   void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+
+  // Java methods
+
   void SetMostVisitedURLsObserver(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
       const base::android::JavaParamRef<jobject>& j_observer,
       jint num_sites);
-  void GetURLThumbnail(JNIEnv* env,
-                       const base::android::JavaParamRef<jobject>& obj,
-                       const base::android::JavaParamRef<jstring>& url,
-                       const base::android::JavaParamRef<jobject>& j_callback);
 
+  void GetURLThumbnail(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& url,
+      const base::android::JavaParamRef<jobject>& j_callback);
   void AddOrRemoveBlacklistedUrl(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
@@ -68,6 +87,18 @@
       jint index,
       jint tile_type);
 
+  // C++ methods
+
+  void SetMostVisitedURLsObserver(
+      std::unique_ptr<MostVisitedSitesObserver> observer, int num_sites);
+
+  using ThumbnailCallback = base::Callback<
+      void(bool /* is_local_thumbnail */, const SkBitmap* /* bitmap */)>;
+  void GetURLThumbnail(const GURL& url, const ThumbnailCallback& callback);
+  void AddOrRemoveBlacklistedUrl(const GURL& url, bool add_url);
+  void RecordTileTypeMetrics(const std::vector<int>& tile_types);
+  void RecordOpenedMostVisitedItem(int index, int tile_type);
+
   // SupervisedUserServiceObserver implementation.
   void OnURLFilterChanged() override;
 
@@ -173,7 +204,7 @@
       SuggestionsVector* src_suggestions,
       SuggestionsVector* dst_suggestions);
 
-  // Notifies the Java side observer about the availability of suggestions.
+  // Notifies the observer about the availability of suggestions.
   // Also records impressions UMA if not done already.
   void NotifyMostVisitedURLsObserver();
 
@@ -182,14 +213,14 @@
   // Runs on the UI Thread.
   void OnLocalThumbnailFetched(
       const GURL& url,
-      std::unique_ptr<base::android::ScopedJavaGlobalRef<jobject>> j_callback,
+      const ThumbnailCallback& callback,
       std::unique_ptr<SkBitmap> bitmap);
 
   // Callback for when the thumbnail lookup is complete.
   // Runs on the UI Thread.
   void OnObtainedThumbnail(
       bool is_local_thumbnail,
-      std::unique_ptr<base::android::ScopedJavaGlobalRef<jobject>> j_callback,
+      const ThumbnailCallback& callback,
       const GURL& url,
       const SkBitmap* bitmap);
 
@@ -207,8 +238,7 @@
   // The profile whose most visited sites will be queried.
   Profile* profile_;
 
-  // The observer to be notified when the list of most visited sites changes.
-  base::android::ScopedJavaGlobalRef<jobject> observer_;
+  std::unique_ptr<MostVisitedSitesObserver> observer_;
 
   // The maximum number of most visited sites to return.
   int num_sites_;
diff --git a/chrome/browser/browsing_data/browsing_data_filter_builder.cc b/chrome/browser/browsing_data/browsing_data_filter_builder.cc
index 06f78fc..58bb7777 100644
--- a/chrome/browser/browsing_data/browsing_data_filter_builder.cc
+++ b/chrome/browser/browsing_data/browsing_data_filter_builder.cc
@@ -7,12 +7,6 @@
 
 #include "base/bind.h"
 #include "chrome/browser/browsing_data/browsing_data_filter_builder.h"
-#include "components/content_settings/core/common/content_settings_pattern.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-
-using net::registry_controlled_domains::GetDomainAndRegistry;
-using net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES;
-using Relation = ContentSettingsPattern::Relation;
 
 namespace {
 
@@ -26,115 +20,15 @@
 
 BrowsingDataFilterBuilder::~BrowsingDataFilterBuilder() {}
 
-void BrowsingDataFilterBuilder::AddRegisterableDomain(
-    const std::string& domain) {
-  // We check that the domain we're given is actually a eTLD+1, or an IP
-  // address.
-  DCHECK(GetDomainAndRegistry("www." + domain, INCLUDE_PRIVATE_REGISTRIES) ==
-             domain ||
-         GURL("http://" + domain).HostIsIPAddress());
-  domain_list_.insert(domain);
-}
-
 void BrowsingDataFilterBuilder::SetMode(Mode mode) {
   mode_ = mode;
 }
 
 bool BrowsingDataFilterBuilder::IsEmptyBlacklist() const {
-  return mode_ == Mode::BLACKLIST && domain_list_.empty();
-}
-
-base::Callback<bool(const GURL&)>
-BrowsingDataFilterBuilder::BuildSameDomainFilter() const {
-  std::set<std::string>* domains = new std::set<std::string>(domain_list_);
-  return base::Bind(&BrowsingDataFilterBuilder::MatchesURL,
-                    base::Owned(domains), mode_);
-}
-
-base::Callback<bool(const ContentSettingsPattern& pattern)>
-BrowsingDataFilterBuilder::BuildWebsiteSettingsPatternMatchesFilter() const {
-  std::vector<ContentSettingsPattern>* patterns_from_domains =
-      new std::vector<ContentSettingsPattern>();
-  patterns_from_domains->reserve(domain_list_.size());
-
-  std::unique_ptr<ContentSettingsPattern::BuilderInterface> builder(
-      ContentSettingsPattern::CreateBuilder(/* use_legacy_validate */ false));
-  for (const std::string& domain : domain_list_) {
-    builder->WithSchemeWildcard()
-        ->WithPortWildcard()
-        ->WithPathWildcard()
-        ->WithHost(domain);
-    if (!GURL("http://" + domain).HostIsIPAddress()) {
-      builder->WithDomainWildcard();
-    }
-    patterns_from_domains->push_back(builder->Build());
-  }
-
-  for (const ContentSettingsPattern& domain : *patterns_from_domains) {
-    DCHECK(domain.IsValid());
-  }
-
-  return base::Bind(&BrowsingDataFilterBuilder::MatchesWebsiteSettingsPattern,
-                    base::Owned(patterns_from_domains), mode_);
-}
-
-base::Callback<bool(const net::CanonicalCookie& pattern)>
-BrowsingDataFilterBuilder::BuildDomainCookieFilter() const {
-  std::set<std::string>* domains_and_ips =
-      new std::set<std::string>(domain_list_);
-  return base::Bind(
-      &BrowsingDataFilterBuilder::MatchesCookieForRegisterableDomainsAndIPs,
-      base::Owned(domains_and_ips), mode_);
+  return mode_ == Mode::BLACKLIST && IsEmpty();
 }
 
 // static
 base::Callback<bool(const GURL&)> BrowsingDataFilterBuilder::BuildNoopFilter() {
   return base::Bind(&NoopFilter);
 }
-
-// static
-bool BrowsingDataFilterBuilder::MatchesURL(
-    std::set<std::string>* registerable_domains,
-    Mode mode,
-    const GURL& url) {
-  std::string url_registerable_domain =
-      GetDomainAndRegistry(url, INCLUDE_PRIVATE_REGISTRIES);
-  return (registerable_domains->find(url_registerable_domain) !=
-              registerable_domains->end() ||
-          (url.HostIsIPAddress() && (registerable_domains->find(url.host()) !=
-                                     registerable_domains->end()))) ==
-         (mode == WHITELIST);
-}
-
-// static
-bool BrowsingDataFilterBuilder::MatchesWebsiteSettingsPattern(
-    std::vector<ContentSettingsPattern>* domain_patterns,
-    Mode mode,
-    const ContentSettingsPattern& pattern) {
-  for (const ContentSettingsPattern& domain : *domain_patterns) {
-    DCHECK(domain.IsValid());
-    Relation relation = pattern.Compare(domain);
-    if (relation == Relation::IDENTITY || relation == Relation::PREDECESSOR)
-      return mode == WHITELIST;
-  }
-  return mode != WHITELIST;
-}
-
-// static
-bool BrowsingDataFilterBuilder::MatchesCookieForRegisterableDomainsAndIPs(
-    std::set<std::string>* domains_and_ips,
-    Mode mode,
-    const net::CanonicalCookie& cookie) {
-  if (domains_and_ips->empty())
-    return mode == BLACKLIST;
-  std::string cookie_domain = cookie.Domain();
-  if (cookie.IsDomainCookie())
-    cookie_domain = cookie_domain.substr(1);
-  std::string parsed_cookie_domain =
-      GetDomainAndRegistry(cookie_domain, INCLUDE_PRIVATE_REGISTRIES);
-  // This means we're an IP address.
-  if (parsed_cookie_domain.empty())
-    parsed_cookie_domain = cookie_domain;
-  return (mode == WHITELIST) == (domains_and_ips->find(parsed_cookie_domain) !=
-                                 domains_and_ips->end());
-}
diff --git a/chrome/browser/browsing_data/browsing_data_filter_builder.h b/chrome/browser/browsing_data/browsing_data_filter_builder.h
index 8c07503..74b2149 100644
--- a/chrome/browser/browsing_data/browsing_data_filter_builder.h
+++ b/chrome/browser/browsing_data/browsing_data_filter_builder.h
@@ -10,28 +10,23 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "net/cookies/canonical_cookie.h"
-#include "url/gurl.h"
-#include "url/origin.h"
 
 class ContentSettingsPattern;
+class GURL;
 
-// A class that constructs URL deletion filters (represented as GURL->bool
-// predicates) that match registerable domains - which is basically an eTLD + 1.
-// We use registerable domains as our filter because of the cookie visibility
-// model. This means that we ignore schemes and subdomains.
+namespace net {
+class CanonicalCookie;
+}
+
+// An abstract class that builds GURL->bool predicates to filter browsing data.
+// These filters can be of two modes - a whitelist or a blacklist. Different
+// subclasses can have different ways of defining the set of URLs - for example,
+// as domains or origins.
 //
-// Cookies are domain-scoped, and websites often rely on cookies that are living
-// on various subdomains. For example, plus.google.com relies on google.com
-// cookies, which eventually talks to account.google.com cookies for GAIA
-// account auth. This means that when we save cookies for an origin, we need
-// to save all cookies for the TLD+1. This means blacklisting (or whitelisting)
-// https://plus.google.com will have us save (or delete) any cookies for
-// *.google.com (http://www.google.com, https://accounts.google.com, etc). For
-// this reason we don't use origins, and instead use registerable domains.
-//
-// See net/base/registry_controlled_domains/registry_controlled_domain.h for
-// more details on registrable domains and the current list of effective eTLDs.
+// This class defines interface to build filters for various kinds of browsing
+// data. |BuildGeneralFilter()| is useful for most browsing data storage
+// backends, but some backends, such as website settings and cookies, use
+// other formats of filter.
 class BrowsingDataFilterBuilder {
  public:
   enum Mode {
@@ -46,72 +41,38 @@
 
   ~BrowsingDataFilterBuilder();
 
-  // Adds a registerable domain to the (white- or black-) list. This is expected
-  // to not include subdomains, so basically tld+1. This can also be an IP
-  // address.
-  // Refer to net/base/registry_controlled_domains/registry_controlled_domain.h
-  // for more details on registrable domains and the current list of effective.
-  // TLDs. We expect a string that would be returned by
-  // net::registry_controlled_domains::GetDomainAndRegistry.
-  void AddRegisterableDomain(const std::string& domain);
-
   // Sets the |mode| of the filter.
   void SetMode(Mode mode);
 
   // Returns true if we're an empty blacklist, where we delete everything.
   bool IsEmptyBlacklist() const;
 
-  // Builds a filter that matches URLs whose origins or domains are in the
-  // whitelist, or aren't in the blacklist.
-  base::Callback<bool(const GURL&)> BuildSameDomainFilter() const;
+  // Builds a filter that matches URLs that are in the whitelist,
+  // or aren't in the blacklist.
+  virtual base::Callback<bool(const GURL&)> BuildGeneralFilter() const = 0;
 
-  // Builds a filter that calls ContentSettingsPattern::Compare on the given
-  // pattern and a new pattern constructed by each domain in this filter. The
-  // domain pattern A and given pattern B match when A.Compare(B) is IDENTITY
-  // or PREDECESSOR. This means we only match patterns that are the same pattern
-  // or a more specific pattern than our domain (so we shouldn't be matching
-  // wildcard patterns like "*" or "*:80").
-  base::Callback<bool(const ContentSettingsPattern& pattern)>
-  BuildWebsiteSettingsPatternMatchesFilter() const;
+  // Builds a filter that matches website settings patterns that contain
+  // data for URLs in the whitelist, or don't contain data for URLs in the
+  // blacklist.
+  virtual base::Callback<bool(const ContentSettingsPattern& pattern)>
+      BuildWebsiteSettingsPatternMatchesFilter() const = 0;
 
-  // We do a direct comparison to the registerable domain of the cookie. A
-  // whitelist filter will return true if any of its domains match the cookie,
-  // and a blacklist filter will return true only if none of its domains match
-  // the cookie.
-  base::Callback<bool(const net::CanonicalCookie& pattern)>
-  BuildDomainCookieFilter() const;
+  // Builds a filter that matches cookies whose sources are in the whitelist,
+  // or aren't in the blacklist.
+  virtual base::Callback<bool(const net::CanonicalCookie& pattern)>
+      BuildCookieFilter() const = 0;
 
   // A convenience method to produce an empty blacklist, a filter that matches
   // everything.
   static base::Callback<bool(const GURL&)> BuildNoopFilter();
 
+ protected:
+  Mode mode() const { return mode_; }
+
+  // Whether or not any URLs have been added to this builder.
+  virtual bool IsEmpty() const = 0;
+
  private:
-  // True if the origin or domain of |url| is in the whitelist, or isn't in the
-  // blacklist.
-  // The whitelist or blacklist is represented as |origins| and |mode|.
-  static bool MatchesURL(std::set<std::string>* registerable_domains,
-                         Mode mode,
-                         const GURL& url);
-
-  // True if the pattern something in the whitelist, or doesn't match something
-  // in the blacklist.
-  // The whitelist or blacklist is represented as |origins|,  and |mode|.
-  static bool MatchesWebsiteSettingsPattern(
-      std::vector<ContentSettingsPattern>* domain_patterns,
-      Mode mode,
-      const ContentSettingsPattern& pattern);
-
-  // True if no origins can see the given cookie and we're a blacklist, or any
-  // origins can see the cookie and we're a whitelist.
-  // The whitelist or blacklist is represented as |origins| and |mode|.
-  static bool MatchesCookieForRegisterableDomainsAndIPs(
-      std::set<std::string>* domains_and_ips,
-      Mode mode,
-      const net::CanonicalCookie& cookie);
-
-  // The list of domains and whether they should be interpreted as a whitelist
-  // or blacklist.
-  std::set<std::string> domain_list_;
   Mode mode_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowsingDataFilterBuilder);
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index 82ad90e..dd96d388 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/browsing_data/browsing_data_filter_builder.h"
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "chrome/browser/browsing_data/browsing_data_remover_factory.h"
+#include "chrome/browser/browsing_data/registrable_domain_filter_builder.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/domain_reliability/service_factory.h"
@@ -353,7 +354,11 @@
 void BrowsingDataRemover::Remove(const TimeRange& time_range,
                                  int remove_mask,
                                  int origin_type_mask) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::BLACKLIST);
+  // Any instance of BrowsingDataFilterBuilder that |IsEmptyBlacklist()|
+  // is OK to pass here.
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::BLACKLIST);
+  DCHECK(builder.IsEmptyBlacklist());
   RemoveImpl(time_range, remove_mask, builder, origin_type_mask);
 }
 
@@ -361,8 +366,8 @@
     const TimeRange& time_range,
     int remove_mask,
     int origin_type_mask,
-    const BrowsingDataFilterBuilder& origin_filter) {
-  RemoveImpl(time_range, remove_mask, origin_filter, origin_type_mask);
+    const BrowsingDataFilterBuilder& filter_builder) {
+  RemoveImpl(time_range, remove_mask, filter_builder, origin_type_mask);
 }
 
 void BrowsingDataRemover::RemoveImpl(
@@ -382,8 +387,8 @@
   remove_mask_ = remove_mask;
   origin_type_mask_ = origin_type_mask;
 
-  base::Callback<bool(const GURL& url)> same_domain_filter =
-      filter_builder.BuildSameDomainFilter();
+  base::Callback<bool(const GURL& url)> filter =
+      filter_builder.BuildGeneralFilter();
   base::Callback<bool(const ContentSettingsPattern& url)> same_pattern_filter =
       filter_builder.BuildWebsiteSettingsPatternMatchesFilter();
 
@@ -614,7 +619,7 @@
     content::RecordAction(UserMetricsAction("ClearBrowsingData_Downloads"));
     content::DownloadManager* download_manager =
         BrowserContext::GetDownloadManager(profile_);
-    download_manager->RemoveDownloadsByURLAndTime(same_domain_filter,
+    download_manager->RemoveDownloadsByURLAndTime(filter,
                                                   delete_begin_, delete_end_);
     DownloadPrefs* download_prefs = DownloadPrefs::FromDownloadManager(
         download_manager);
@@ -658,7 +663,7 @@
           BrowserThread::PostTask(
               BrowserThread::IO, FROM_HERE,
               base::Bind(&ClearCookiesWithPredicateOnIOThread, delete_begin_,
-                         delete_end_, filter_builder.BuildDomainCookieFilter(),
+                         delete_end_, filter_builder.BuildCookieFilter(),
                          base::RetainedRef(std::move(sb_context)),
                          UIThreadTrampoline(
                              base::Bind(&BrowsingDataRemover::OnClearedCookies,
@@ -765,7 +770,7 @@
           base::Bind(&BrowsingDataRemover::OnClearedPasswords,
                      weak_ptr_factory_.GetWeakPtr());
       password_store->RemoveLoginsByURLAndTime(
-          same_domain_filter, delete_begin_, delete_end_, on_cleared_passwords);
+          filter, delete_begin_, delete_end_, on_cleared_passwords);
     }
   }
 
@@ -904,12 +909,11 @@
 
     content::StoragePartition::CookieMatcherFunction cookie_matcher;
     if (!filter_builder.IsEmptyBlacklist()) {
-      cookie_matcher = filter_builder.BuildDomainCookieFilter();
+      cookie_matcher = filter_builder.BuildCookieFilter();
     }
     storage_partition->ClearData(
         storage_partition_remove_mask, quota_storage_remove_mask,
-        base::Bind(&DoesOriginMatchMaskAndUrls, origin_type_mask_,
-                   same_domain_filter),
+        base::Bind(&DoesOriginMatchMaskAndUrls, origin_type_mask_, filter),
         cookie_matcher, delete_begin_, delete_end_,
         base::Bind(&BrowsingDataRemover::OnClearedStoragePartitionData,
                    weak_ptr_factory_.GetWeakPtr()));
@@ -994,7 +998,7 @@
     waiting_for_clear_offline_page_data_ = true;
     offline_pages::OfflinePageModelFactory::GetForBrowserContext(profile_)
         ->DeletePagesByURLPredicate(
-            same_domain_filter,
+            filter,
             base::Bind(&BrowsingDataRemover::OnClearedOfflinePageData,
                        weak_ptr_factory_.GetWeakPtr()));
   }
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
index 8db87b9..538eec2 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "chrome/browser/browsing_data/browsing_data_remover_factory.h"
 #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h"
+#include "chrome/browser/browsing_data/registrable_domain_filter_builder.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/domain_reliability/service_factory.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
@@ -1201,7 +1202,8 @@
 }
 
 TEST_F(BrowsingDataRemoverTest, RemoveCookiesDomainBlacklist) {
-  BrowsingDataFilterBuilder filter(BrowsingDataFilterBuilder::BLACKLIST);
+  RegistrableDomainFilterBuilder filter(
+      RegistrableDomainFilterBuilder::BLACKLIST);
   filter.AddRegisterableDomain(kTestRegisterableDomain1);
   filter.AddRegisterableDomain(kTestRegisterableDomain3);
   BlockUntilOriginDataRemoved(BrowsingDataRemover::LAST_HOUR,
@@ -1268,7 +1270,8 @@
 
   tester.AddCookie();
   ASSERT_TRUE(tester.ContainsCookie());
-  BrowsingDataFilterBuilder filter(BrowsingDataFilterBuilder::BLACKLIST);
+  RegistrableDomainFilterBuilder filter(
+      RegistrableDomainFilterBuilder::BLACKLIST);
   filter.AddRegisterableDomain(kTestRegisterableDomain1);
   BlockUntilOriginDataRemoved(BrowsingDataRemover::EVERYTHING,
                               BrowsingDataRemover::REMOVE_COOKIES, filter);
@@ -1277,7 +1280,8 @@
   EXPECT_EQ(BrowsingDataHelper::UNPROTECTED_WEB, GetOriginTypeMask());
   EXPECT_TRUE(tester.ContainsCookie());
 
-  BrowsingDataFilterBuilder filter2(BrowsingDataFilterBuilder::WHITELIST);
+  RegistrableDomainFilterBuilder filter2(
+      RegistrableDomainFilterBuilder::WHITELIST);
   filter2.AddRegisterableDomain(kTestRegisterableDomain1);
   BlockUntilOriginDataRemoved(BrowsingDataRemover::EVERYTHING,
                               BrowsingDataRemover::REMOVE_COOKIES, filter2);
@@ -1743,7 +1747,8 @@
 }
 
 TEST_F(BrowsingDataRemoverTest, RemoveQuotaManagedDataForeverSpecificOrigin) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::WHITELIST);
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::WHITELIST);
   builder.AddRegisterableDomain(kTestRegisterableDomain1);
   // Remove Origin 1.
   BlockUntilOriginDataRemoved(BrowsingDataRemover::EVERYTHING,
@@ -1915,7 +1920,8 @@
   policy->AddProtected(kOrigin1.GetOrigin());
 #endif
 
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::WHITELIST);
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::WHITELIST);
   builder.AddRegisterableDomain(kTestRegisterableDomain1);
 
   // Try to remove kOrigin1. Expect failure.
@@ -2061,7 +2067,8 @@
   ASSERT_TRUE(tester.HistoryContainsURL(kOrigin1));
   ASSERT_TRUE(tester.HistoryContainsURL(kOrigin2));
 
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::BLACKLIST);
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::BLACKLIST);
   BlockUntilOriginDataRemoved(BrowsingDataRemover::LAST_HOUR,
                               BrowsingDataRemover::REMOVE_HISTORY, builder);
 
@@ -2310,9 +2317,10 @@
 
 TEST_F(BrowsingDataRemoverTest, RemoveDownloadsByOrigin) {
   RemoveDownloadsTester tester(GetProfile());
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::WHITELIST);
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::WHITELIST);
   builder.AddRegisterableDomain(kTestRegisterableDomain1);
-  base::Callback<bool(const GURL&)> filter = builder.BuildSameDomainFilter();
+  base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter();
 
   EXPECT_CALL(
       *tester.download_manager(),
@@ -2346,9 +2354,10 @@
 
 TEST_F(BrowsingDataRemoverTest, RemovePasswordsByOrigin) {
   RemovePasswordsTester tester(GetProfile());
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::WHITELIST);
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::WHITELIST);
   builder.AddRegisterableDomain(kTestRegisterableDomain1);
-  base::Callback<bool(const GURL&)> filter = builder.BuildSameDomainFilter();
+  base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter();
 
   EXPECT_CALL(*tester.store(),
               RemoveLoginsByURLAndTimeImpl(ProbablySameFilter(filter), _, _))
@@ -2399,7 +2408,8 @@
       new base::DictionaryValue());
 
   // Clear all except for origin1 and origin3.
-  BrowsingDataFilterBuilder filter(BrowsingDataFilterBuilder::BLACKLIST);
+  RegistrableDomainFilterBuilder filter(
+      RegistrableDomainFilterBuilder::BLACKLIST);
   filter.AddRegisterableDomain(kTestRegisterableDomain1);
   filter.AddRegisterableDomain(kTestRegisterableDomain3);
   BlockUntilOriginDataRemoved(BrowsingDataRemover::LAST_HOUR,
diff --git a/chrome/browser/browsing_data/origin_filter_builder.cc b/chrome/browser/browsing_data/origin_filter_builder.cc
index 900b01831..26a5c2f 100644
--- a/chrome/browser/browsing_data/origin_filter_builder.cc
+++ b/chrome/browser/browsing_data/origin_filter_builder.cc
@@ -8,17 +8,20 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
+
+using Relation = ContentSettingsPattern::Relation;
 
 namespace {
 
-bool NoopFilter(const GURL& url) {
-  return true;
+bool DontDeleteCookiesFilter(const net::CanonicalCookie& cookie) {
+  return false;
 }
 
 }  // namespace
 
 OriginFilterBuilder::OriginFilterBuilder(Mode mode)
-    : mode_(mode) {
+    : BrowsingDataFilterBuilder(mode) {
 }
 
 OriginFilterBuilder::~OriginFilterBuilder() {
@@ -43,27 +46,53 @@
   origin_list_.insert(origin);
 }
 
-void OriginFilterBuilder::SetMode(Mode mode) {
-  mode_ = mode;
-}
-
 base::Callback<bool(const GURL&)>
-    OriginFilterBuilder::BuildSameOriginFilter() const {
+    OriginFilterBuilder::BuildGeneralFilter() const {
   std::set<url::Origin>* origins = new std::set<url::Origin>(origin_list_);
   return base::Bind(&OriginFilterBuilder::MatchesURL,
-                    base::Owned(origins), mode_);
+                    base::Owned(origins), mode());
 }
 
-base::Callback<bool(const GURL&)>
-    OriginFilterBuilder::BuildDomainFilter() const {
-  std::set<url::Origin>* origins = new std::set<url::Origin>(origin_list_);
-  return base::Bind(&OriginFilterBuilder::MatchesURLWithSubdomains,
-                    base::Owned(origins), mode_);
+base::Callback<bool(const ContentSettingsPattern& pattern)>
+    OriginFilterBuilder::BuildWebsiteSettingsPatternMatchesFilter() const {
+  std::vector<ContentSettingsPattern>* patterns_from_origins =
+      new std::vector<ContentSettingsPattern>();
+  patterns_from_origins->reserve(origin_list_.size());
+
+  for (const url::Origin& origin : origin_list_) {
+    patterns_from_origins->push_back(
+        ContentSettingsPattern::FromURLNoWildcard(GURL(origin.Serialize())));
+    DCHECK(patterns_from_origins->back().IsValid());
+  }
+
+  return base::Bind(&OriginFilterBuilder::MatchesWebsiteSettingsPattern,
+                    base::Owned(patterns_from_origins), mode());
+}
+
+base::Callback<bool(const net::CanonicalCookie& cookie)>
+OriginFilterBuilder::BuildCookieFilter() const {
+  NOTREACHED() <<
+      "Origin-based deletion is not suitable for cookies. Please use "
+      "different scoping, such as RegistrableDomainFilterBuilder.";
+  return base::Bind(DontDeleteCookiesFilter);
+}
+
+bool OriginFilterBuilder::IsEmpty() const {
+  return origin_list_.empty();
 }
 
 // static
-base::Callback<bool(const GURL&)> OriginFilterBuilder::BuildNoopFilter() {
-  return base::Bind(&NoopFilter);
+bool OriginFilterBuilder::MatchesWebsiteSettingsPattern(
+    std::vector<ContentSettingsPattern>* origin_patterns,
+    Mode mode,
+    const ContentSettingsPattern& pattern) {
+  for (const ContentSettingsPattern& origin : *origin_patterns) {
+    DCHECK(origin.IsValid());
+    Relation relation = pattern.Compare(origin);
+    if (relation == Relation::IDENTITY)
+      return mode == WHITELIST;
+  }
+  return mode != WHITELIST;
 }
 
 // static
@@ -72,40 +101,3 @@
   return ((origins->find(url::Origin(url)) != origins->end()) ==
           (mode == WHITELIST));
 }
-
-// static
-bool OriginFilterBuilder::MatchesURLWithSubdomains(
-    std::set<url::Origin>* origins, Mode mode, const GURL& url) {
-  if (origins->empty())
-    return mode == BLACKLIST;
-
-  // If there is no concept of subdomains, simply delegate to MatchesURL().
-  if (url.HostIsIPAddress())
-    return MatchesURL(origins, mode, url);
-
-  // TODO(msramek): We do not expect filters to be particularly large.
-  // If they are, replace std::set with a trie for faster searching.
-  int port = url.EffectiveIntPort();
-  base::StringPiece host_piece = url.host_piece();
-  for (size_t i = 0; i < host_piece.length(); ++i) {
-    if (i != 0 && host_piece[i - 1] != '.')
-      continue;
-
-    url::Origin origin_with_removed_subdomain =
-        url::Origin::UnsafelyCreateOriginWithoutNormalization(
-            url.scheme_piece(),
-            host_piece.substr(i),
-            port);
-
-    // If we recognize the origin, return true for whitelist and false
-    // for blacklist.
-    if (origins->find(url::Origin(origin_with_removed_subdomain))
-        != origins->end()) {
-      return mode == WHITELIST;
-    }
-  }
-
-  // We do not recognize the URL. Return false for whitelist mode and true
-  // for blacklist mode.
-  return mode == BLACKLIST;
-}
diff --git a/chrome/browser/browsing_data/origin_filter_builder.h b/chrome/browser/browsing_data/origin_filter_builder.h
index 092ec42..565f78df 100644
--- a/chrome/browser/browsing_data/origin_filter_builder.h
+++ b/chrome/browser/browsing_data/origin_filter_builder.h
@@ -10,18 +10,19 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "chrome/browser/browsing_data/browsing_data_filter_builder.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
 // A class that constructs URL deletion filters (represented as GURL->bool
 // predicates) that match certain origins.
-class OriginFilterBuilder {
+//
+// IMPORTANT NOTE: While this class does define a cookie filtering method, as
+// required by the BrowsingDataFilterBuilder interface, it is not suitable for
+// cookie deletion (BrowsingDataRemover::REMOVE_COOKIES). Instead, use
+// RegistrableDomainFilterBuilder and see its documenation for more details.
+class OriginFilterBuilder : public BrowsingDataFilterBuilder {
  public:
-  enum Mode {
-    WHITELIST,
-    BLACKLIST
-  };
-
   // Constructs a filter with the given |mode| - whitelist or blacklist.
   explicit OriginFilterBuilder(Mode mode);
 
@@ -30,21 +31,28 @@
   // Adds the |origin| to the (white- or black-) list.
   void AddOrigin(const url::Origin& origin);
 
-  // Sets the |mode| of the filter.
-  void SetMode(Mode mode);
-
   // Builds a filter that matches URLs whose origins are in the whitelist,
   // or aren't in the blacklist.
-  base::Callback<bool(const GURL&)> BuildSameOriginFilter() const;
+  base::Callback<bool(const GURL&)> BuildGeneralFilter() const override;
 
-  // Build a filter that matches URLs whose origins, or origins obtained by
-  // replacing the host with any superdomain, are listed in the whitelist,
-  // or are not listed in the blacklist.
-  base::Callback<bool(const GURL&)> BuildDomainFilter() const;
+  // Builds a filter that calls ContentSettingsPattern::Compare on the given
+  // pattern and a new pattern constructed by each origin in this filter. The
+  // domain pattern A and given pattern B match when A.Compare(B) is IDENTITY.
+  // This is sufficient, because website settings should only ever store
+  // origin-scoped patterns. Furthermore, website settings patterns support
+  // paths, but only for the file:// scheme, which is in turn not supported
+  // by OriginFilterBuilder.
+  base::Callback<bool(const ContentSettingsPattern& pattern)>
+      BuildWebsiteSettingsPatternMatchesFilter() const override;
 
-  // A convenience method to produce an empty blacklist, a filter that matches
-  // everything.
-  static base::Callback<bool(const GURL&)> BuildNoopFilter();
+  // Cookie filter is not implemented in this subclass. Please use
+  // a BrowsingDataFilterBuilder with different scoping,
+  // such as RegistrableDomainFilterBuilder.
+  base::Callback<bool(const net::CanonicalCookie& cookie)>
+      BuildCookieFilter() const override;
+
+ protected:
+  bool IsEmpty() const override;
 
  private:
   // True if the origin of |url| is in the whitelist, or isn't in the blacklist.
@@ -52,12 +60,11 @@
   static bool MatchesURL(
       std::set<url::Origin>* origins, Mode mode, const GURL& url);
 
-  // True if any origin [scheme, host, port], such that |url| has the same
-  // scheme and port, and |url|'s host is the same or a subdomain of that host,
-  // is in the whitelist, or isn't in the blacklist. The whitelist or blacklist
-  // is represented as |origins| and |mode|.
-  static bool MatchesURLWithSubdomains(
-      std::set<url::Origin>* origins, Mode mode, const GURL& url);
+  // True if the |pattern| is identical to one of the |origin_patterns|.
+  static bool MatchesWebsiteSettingsPattern(
+      std::vector<ContentSettingsPattern>* origin_patterns,
+      Mode mode,
+      const ContentSettingsPattern& pattern);
 
   // The list of origins and whether they should be interpreted as a whitelist
   // or blacklist.
diff --git a/chrome/browser/browsing_data/origin_filter_builder_unittest.cc b/chrome/browser/browsing_data/origin_filter_builder_unittest.cc
index 32fef25..842f4c2 100644
--- a/chrome/browser/browsing_data/origin_filter_builder_unittest.cc
+++ b/chrome/browser/browsing_data/origin_filter_builder_unittest.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -30,6 +31,15 @@
     EXPECT_FALSE(filter.Run(GURL(test_case.url)));
 }
 
+void RunTestCase(
+    TestCase test_case,
+    const base::Callback<bool(const ContentSettingsPattern&)>& filter) {
+  ContentSettingsPattern pattern =
+      ContentSettingsPattern::FromString(test_case.url);
+  EXPECT_TRUE(pattern.IsValid()) << test_case.url << " is not valid.";
+  EXPECT_EQ(test_case.should_match, filter.Run(pattern)) << pattern.ToString();
+}
+
 }  // namespace
 
 TEST(OriginFilterBuilderTest, Noop) {
@@ -51,7 +61,7 @@
   OriginFilterBuilder builder(OriginFilterBuilder::WHITELIST);
   builder.AddOrigin(Origin(GURL("https://www.google.com")));
   builder.AddOrigin(Origin(GURL("http://www.example.com")));
-  base::Callback<bool(const GURL&)> filter = builder.BuildSameOriginFilter();
+  base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter();
 
   TestCase test_cases[] = {
       // Whitelist matches any URL on the specified origins.
@@ -81,7 +91,7 @@
   OriginFilterBuilder builder(OriginFilterBuilder::BLACKLIST);
   builder.AddOrigin(Origin(GURL("https://www.google.com")));
   builder.AddOrigin(Origin(GURL("http://www.example.com")));
-  base::Callback<bool(const GURL&)> filter = builder.BuildSameOriginFilter();
+  base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter();
 
   TestCase test_cases[] = {
       // URLS on explicitly specified origins are not matched.
@@ -108,29 +118,92 @@
     RunTestCase(test_case, filter);
 }
 
-TEST(OriginFilterBuilderTest, MatchesURLWithSubdomain) {
+TEST(OriginFilterBuilderTest, WhitelistWebsiteSettings) {
   OriginFilterBuilder builder(OriginFilterBuilder::WHITELIST);
   builder.AddOrigin(Origin(GURL("https://www.google.com")));
-  base::Callback<bool(const GURL&)> filter = builder.BuildDomainFilter();
+  builder.AddOrigin(Origin(GURL("http://www.example.com")));
+  base::Callback<bool(const ContentSettingsPattern&)> filter =
+      builder.BuildWebsiteSettingsPatternMatchesFilter();
 
   TestCase test_cases[] = {
-      // Any URL on the specified origin is matched.
-      { "https://www.google.com", true },
-      { "https://www.google.com/test.html", true },
+      // Patterns of the same origins are matched.
+      {"https://www.google.com:443", true},
+      {"http://www.example.com:80", true},
 
-      // Subdomains are also matched.
-      { "https://foo.www.google.com", true },
-      { "https://foo.www.google.com/?q=test", true },
-      { "https://foo.bar.www.google.com", true },
-      { "https://foo.bar.www.google.com/test.html", true },
-      { "https://foo.bar.baz.www.google.com", true },
+      // Paths are always ignored during the website setting pattern creation.
+      {"https://www.google.com:443/index.html?q=abc", true},
+      {"http://www.example.com:80/foo/bar", true},
 
-      // Superdomains are not matched.
-      { "https://google.com", false },
+      // Subdomains are different origins.
+      { "https://test.www.google.com", false },
 
-      // Different hosts are not matched.
-      { "https://www.chrome.com", false },
+      // Different scheme or port is a different origin.
+      { "https://www.google.com:8000", false },
+      { "https://www.example.com/index.html", false },
+
+      // No port means port wildcard.
+      {"https://www.google.com", false},
+      {"http://www.example.com", false},
+
+      // Different host is a different origin.
       { "https://www.youtube.com", false },
+      { "https://www.chromium.org", false },
+
+      // Nonstandard patterns are not matched. Note that this only documents the
+      // current behavior of OriginFilterBuilder. Website settings deleted
+      // by BrowsingDataRemover never use patterns scoped broader than origin.
+      {"https://[*.]google.com", false},
+      {"*://google.com", false},
+      {"https://google.com:*", false},
+      {"https://*", false},
+      {"http://*", false},
+      {"*", false},
+  };
+
+  for (TestCase test_case : test_cases)
+    RunTestCase(test_case, filter);
+}
+
+TEST(OriginFilterBuilderTest, BlacklistWebsiteSettings) {
+  OriginFilterBuilder builder(OriginFilterBuilder::BLACKLIST);
+  builder.AddOrigin(Origin(GURL("https://www.google.com")));
+  builder.AddOrigin(Origin(GURL("http://www.example.com")));
+  base::Callback<bool(const ContentSettingsPattern&)> filter =
+      builder.BuildWebsiteSettingsPatternMatchesFilter();
+
+  TestCase test_cases[] = {
+      // Patterns of the same origins are matched.
+      {"https://www.google.com:443", false},
+      {"http://www.example.com:80", false},
+
+      // Paths are always ignored during the website setting pattern creation.
+      {"https://www.google.com:443/index.html?q=abc", false},
+      {"http://www.example.com:80/foo/bar", false},
+
+      // Subdomains are different origins.
+      { "https://test.www.google.com", true },
+
+      // Different scheme or port is a different origin.
+      { "https://www.google.com:8000", true },
+      { "https://www.example.com/index.html", true },
+
+      // No port means port wildcard.
+      {"https://www.google.com", true},
+      {"http://www.example.com", true},
+
+      // Different host is a different origin.
+      { "https://www.youtube.com", true },
+      { "https://www.chromium.org", true },
+
+      // Nonstandard patterns are matched. Note that this only documents the
+      // current behavior of OriginFilterBuilder. Website settings deleted
+      // by BrowsingDataRemover never use patterns scoped broader than origin.
+      {"https://[*.]google.com", true},
+      {"*://google.com", true},
+      {"https://google.com:*", true},
+      {"https://*", true},
+      {"http://*", true},
+      {"*", true},
   };
 
   for (TestCase test_case : test_cases)
diff --git a/chrome/browser/browsing_data/registrable_domain_filter_builder.cc b/chrome/browser/browsing_data/registrable_domain_filter_builder.cc
new file mode 100644
index 0000000..209c2ee
--- /dev/null
+++ b/chrome/browser/browsing_data/registrable_domain_filter_builder.cc
@@ -0,0 +1,130 @@
+// Copyright 2016 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 "chrome/browser/browsing_data/registrable_domain_filter_builder.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cookies/canonical_cookie.h"
+
+using net::registry_controlled_domains::GetDomainAndRegistry;
+using net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES;
+using Relation = ContentSettingsPattern::Relation;
+
+RegistrableDomainFilterBuilder::RegistrableDomainFilterBuilder(Mode mode)
+    : BrowsingDataFilterBuilder(mode) {
+}
+
+RegistrableDomainFilterBuilder::~RegistrableDomainFilterBuilder() {}
+
+void RegistrableDomainFilterBuilder::AddRegisterableDomain(
+    const std::string& domain) {
+  // We check that the domain we're given is actually a eTLD+1, or an IP
+  // address.
+  DCHECK(GetDomainAndRegistry("www." + domain, INCLUDE_PRIVATE_REGISTRIES) ==
+             domain ||
+         GURL("http://" + domain).HostIsIPAddress());
+  domain_list_.insert(domain);
+}
+
+base::Callback<bool(const GURL&)>
+RegistrableDomainFilterBuilder::BuildGeneralFilter() const {
+  std::set<std::string>* domains = new std::set<std::string>(domain_list_);
+  return base::Bind(&RegistrableDomainFilterBuilder::MatchesURL,
+                    base::Owned(domains), mode());
+}
+
+base::Callback<bool(const ContentSettingsPattern& pattern)>
+RegistrableDomainFilterBuilder
+    ::BuildWebsiteSettingsPatternMatchesFilter() const {
+  std::vector<ContentSettingsPattern>* patterns_from_domains =
+      new std::vector<ContentSettingsPattern>();
+  patterns_from_domains->reserve(domain_list_.size());
+
+  std::unique_ptr<ContentSettingsPattern::BuilderInterface> builder(
+      ContentSettingsPattern::CreateBuilder(/* use_legacy_validate */ false));
+  for (const std::string& domain : domain_list_) {
+    builder->WithSchemeWildcard()
+        ->WithPortWildcard()
+        ->WithPathWildcard()
+        ->WithHost(domain);
+    if (!GURL("http://" + domain).HostIsIPAddress()) {
+      builder->WithDomainWildcard();
+    }
+    patterns_from_domains->push_back(builder->Build());
+  }
+
+  for (const ContentSettingsPattern& domain : *patterns_from_domains) {
+    DCHECK(domain.IsValid());
+  }
+
+  return base::Bind(
+      &RegistrableDomainFilterBuilder::MatchesWebsiteSettingsPattern,
+      base::Owned(patterns_from_domains), mode());
+}
+
+base::Callback<bool(const net::CanonicalCookie& cookie)>
+RegistrableDomainFilterBuilder::BuildCookieFilter() const {
+  std::set<std::string>* domains_and_ips =
+      new std::set<std::string>(domain_list_);
+  return base::Bind(
+      &RegistrableDomainFilterBuilder
+          ::MatchesCookieForRegisterableDomainsAndIPs,
+      base::Owned(domains_and_ips), mode());
+}
+
+bool RegistrableDomainFilterBuilder::IsEmpty() const {
+  return domain_list_.empty();
+}
+
+// static
+bool RegistrableDomainFilterBuilder::MatchesURL(
+    std::set<std::string>* registerable_domains,
+    Mode mode,
+    const GURL& url) {
+  std::string url_registerable_domain =
+      GetDomainAndRegistry(url, INCLUDE_PRIVATE_REGISTRIES);
+  return (registerable_domains->find(url_registerable_domain) !=
+              registerable_domains->end() ||
+          (url.HostIsIPAddress() && (registerable_domains->find(url.host()) !=
+                                     registerable_domains->end()))) ==
+         (mode == WHITELIST);
+}
+
+// static
+bool RegistrableDomainFilterBuilder::MatchesWebsiteSettingsPattern(
+    std::vector<ContentSettingsPattern>* domain_patterns,
+    Mode mode,
+    const ContentSettingsPattern& pattern) {
+  for (const ContentSettingsPattern& domain : *domain_patterns) {
+    DCHECK(domain.IsValid());
+    Relation relation = pattern.Compare(domain);
+    if (relation == Relation::IDENTITY || relation == Relation::PREDECESSOR)
+      return mode == WHITELIST;
+  }
+  return mode != WHITELIST;
+}
+
+// static
+bool RegistrableDomainFilterBuilder::MatchesCookieForRegisterableDomainsAndIPs(
+    std::set<std::string>* domains_and_ips,
+    Mode mode,
+    const net::CanonicalCookie& cookie) {
+  if (domains_and_ips->empty())
+    return mode == BLACKLIST;
+  std::string cookie_domain = cookie.Domain();
+  if (cookie.IsDomainCookie())
+    cookie_domain = cookie_domain.substr(1);
+  std::string parsed_cookie_domain =
+      GetDomainAndRegistry(cookie_domain, INCLUDE_PRIVATE_REGISTRIES);
+  // This means we're an IP address.
+  if (parsed_cookie_domain.empty())
+    parsed_cookie_domain = cookie_domain;
+  return (mode == WHITELIST) == (domains_and_ips->find(parsed_cookie_domain) !=
+                                 domains_and_ips->end());
+}
diff --git a/chrome/browser/browsing_data/registrable_domain_filter_builder.h b/chrome/browser/browsing_data/registrable_domain_filter_builder.h
new file mode 100644
index 0000000..5a6a73a
--- /dev/null
+++ b/chrome/browser/browsing_data/registrable_domain_filter_builder.h
@@ -0,0 +1,103 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BROWSING_DATA_REGISTRABLE_DOMAIN_FILTER_BUILDER_H_
+#define CHROME_BROWSER_BROWSING_DATA_REGISTRABLE_DOMAIN_FILTER_BUILDER_H_
+
+#include <ostream>
+#include <set>
+#include <vector>
+
+#include "base/callback.h"
+#include "chrome/browser/browsing_data/browsing_data_filter_builder.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+// A class that constructs URL deletion filters (represented as GURL->bool
+// predicates) that match registerable domains - which is basically an eTLD + 1.
+// This means that we ignore schemes and subdomains. This is particularly
+// suitable for cookie filtering because of the cookie visibility model.
+//
+// Cookies are domain-scoped, and websites often rely on cookies that are living
+// on various subdomains. For example, plus.google.com relies on google.com
+// cookies, which eventually talks to account.google.com cookies for GAIA
+// account auth. This means that when we save cookies for an origin, we need
+// to save all cookies for the eTLD+1. This means blacklisting (or whitelisting)
+// https://plus.google.com will have us save (or delete) any cookies for
+// *.google.com (http://www.google.com, https://accounts.google.com, etc). For
+// this reason we don't use origins, and instead use registerable domains.
+//
+// See net/base/registry_controlled_domains/registry_controlled_domain.h for
+// more details on registrable domains and the current list of effective eTLDs.
+class RegistrableDomainFilterBuilder : public BrowsingDataFilterBuilder {
+ public:
+  // Constructs a filter with the given |mode| - whitelist or blacklist.
+  explicit RegistrableDomainFilterBuilder(Mode mode);
+
+  ~RegistrableDomainFilterBuilder();
+
+  // Adds a registerable domain to the (white- or black-) list. This is expected
+  // to not include subdomains, so basically tld+1. This can also be an IP
+  // address.
+  // Refer to net/base/registry_controlled_domains/registry_controlled_domain.h
+  // for more details on registrable domains and the current list of effective.
+  // TLDs. We expect a string that would be returned by
+  // net::registry_controlled_domains::GetDomainAndRegistry.
+  void AddRegisterableDomain(const std::string& domain);
+
+  // Builds a filter that matches URLs whose origins or domains are in the
+  // whitelist, or aren't in the blacklist.
+  base::Callback<bool(const GURL&)> BuildGeneralFilter() const override;
+
+  // Builds a filter that calls ContentSettingsPattern::Compare on the given
+  // pattern and a new pattern constructed by each domain in this filter. The
+  // domain pattern A and given pattern B match when A.Compare(B) is IDENTITY
+  // or PREDECESSOR. This means we only match patterns that are the same pattern
+  // or a more specific pattern than our domain (so we shouldn't be matching
+  // wildcard patterns like "*" or "*:80").
+  base::Callback<bool(const ContentSettingsPattern& pattern)>
+      BuildWebsiteSettingsPatternMatchesFilter() const override;
+
+  // We do a direct comparison to the registerable domain of the cookie. A
+  // whitelist filter will return true if any of its domains match the cookie,
+  // and a blacklist filter will return true only if none of its domains match
+  // the cookie.
+  base::Callback<bool(const net::CanonicalCookie& cookie)>
+      BuildCookieFilter() const override;
+
+ protected:
+  bool IsEmpty() const override;
+
+ private:
+  // True if the origin or domain of |url| is in the whitelist, or isn't in the
+  // blacklist.
+  // The whitelist or blacklist is represented as |origins| and |mode|.
+  static bool MatchesURL(std::set<std::string>* registerable_domains,
+                         Mode mode,
+                         const GURL& url);
+
+  // True if the pattern something in the whitelist, or doesn't match something
+  // in the blacklist.
+  // The whitelist or blacklist is represented as |origins|,  and |mode|.
+  static bool MatchesWebsiteSettingsPattern(
+      std::vector<ContentSettingsPattern>* patterns,
+      Mode mode,
+      const ContentSettingsPattern& pattern);
+
+  // True if no origins can see the given cookie and we're a blacklist, or any
+  // origins can see the cookie and we're a whitelist.
+  // The whitelist or blacklist is represented as |origins| and |mode|.
+  static bool MatchesCookieForRegisterableDomainsAndIPs(
+      std::set<std::string>* domains_and_ips,
+      Mode mode,
+      const net::CanonicalCookie& cookie);
+
+  // The list of domains and whether they should be interpreted as a whitelist
+  // or blacklist.
+  std::set<std::string> domain_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(RegistrableDomainFilterBuilder);
+};
+
+#endif  // CHROME_BROWSER_BROWSING_DATA_REGISTRABLE_DOMAIN_FILTER_BUILDER_H_
diff --git a/chrome/browser/browsing_data/browsing_data_filter_builder_unittest.cc b/chrome/browser/browsing_data/registrable_domain_filter_builder_unittest.cc
similarity index 88%
rename from chrome/browser/browsing_data/browsing_data_filter_builder_unittest.cc
rename to chrome/browser/browsing_data/registrable_domain_filter_builder_unittest.cc
index 635f4a8..172f0100 100644
--- a/chrome/browser/browsing_data/browsing_data_filter_builder_unittest.cc
+++ b/chrome/browser/browsing_data/registrable_domain_filter_builder_unittest.cc
@@ -2,14 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/browsing_data/browsing_data_filter_builder.h"
+#include "chrome/browser/browsing_data/registrable_domain_filter_builder.h"
 
 #include <algorithm>
 #include <string>
 #include <vector>
 
 #include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
+#include "net/cookies/canonical_cookie.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -83,10 +85,10 @@
 
 }  // namespace
 
-TEST(BrowsingDataFilterBuilderTest, Noop) {
+TEST(RegistrableDomainFilterBuilderTest, Noop) {
   // An no-op filter matches everything.
   base::Callback<bool(const GURL&)> filter =
-      BrowsingDataFilterBuilder::BuildNoopFilter();
+      RegistrableDomainFilterBuilder::BuildNoopFilter();
 
   TestCase test_cases[] = {
       {"https://www.google.com", true},
@@ -99,12 +101,13 @@
     RunTestCase(test_case, filter);
 }
 
-TEST(BrowsingDataFilterBuilderTest, GURLWhitelist) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::WHITELIST);
+TEST(RegistrableDomainFilterBuilderTest, GURLWhitelist) {
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::WHITELIST);
   builder.AddRegisterableDomain(std::string(kGoogleDomain));
   builder.AddRegisterableDomain(std::string(kLongETLDDomain));
   builder.AddRegisterableDomain(std::string(kIPAddress));
-  base::Callback<bool(const GURL&)> filter = builder.BuildSameDomainFilter();
+  base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter();
 
   TestCase test_cases[] = {
       // We matche any URL on the specified domains.
@@ -130,12 +133,13 @@
     RunTestCase(test_case, filter);
 }
 
-TEST(BrowsingDataFilterBuilderTest, GURLBlacklist) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::BLACKLIST);
+TEST(RegistrableDomainFilterBuilderTest, GURLBlacklist) {
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::BLACKLIST);
   builder.AddRegisterableDomain(std::string(kGoogleDomain));
   builder.AddRegisterableDomain(std::string(kLongETLDDomain));
   builder.AddRegisterableDomain(std::string(kIPAddress));
-  base::Callback<bool(const GURL&)> filter = builder.BuildSameDomainFilter();
+  base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter();
 
   TestCase test_cases[] = {
       // We matches any URL that are not on the specified domains.
@@ -161,8 +165,9 @@
     RunTestCase(test_case, filter);
 }
 
-TEST(BrowsingDataFilterBuilderTest, WhitelistContentSettings) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::WHITELIST);
+TEST(RegistrableDomainFilterBuilderTest, WhitelistContentSettings) {
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::WHITELIST);
   builder.AddRegisterableDomain(std::string(kGoogleDomain));
   builder.AddRegisterableDomain(std::string(kLongETLDDomain));
   builder.AddRegisterableDomain(std::string(kIPAddress));
@@ -210,8 +215,9 @@
     RunTestCase(test_case, filter);
 }
 
-TEST(BrowsingDataFilterBuilderTest, BlacklistContentSettings) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::BLACKLIST);
+TEST(RegistrableDomainFilterBuilderTest, BlacklistContentSettings) {
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::BLACKLIST);
   builder.AddRegisterableDomain(std::string(kGoogleDomain));
   builder.AddRegisterableDomain(std::string(kLongETLDDomain));
   builder.AddRegisterableDomain(std::string(kIPAddress));
@@ -259,13 +265,14 @@
     RunTestCase(test_case, filter);
 }
 
-TEST(BrowsingDataFilterBuilderTest, MatchesCookiesWhitelist) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::WHITELIST);
+TEST(RegistrableDomainFilterBuilderTest, MatchesCookiesWhitelist) {
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::WHITELIST);
   builder.AddRegisterableDomain(std::string(kGoogleDomain));
   builder.AddRegisterableDomain(std::string(kLongETLDDomain));
   builder.AddRegisterableDomain(std::string(kIPAddress));
   base::Callback<bool(const net::CanonicalCookie&)> filter =
-      builder.BuildDomainCookieFilter();
+      builder.BuildCookieFilter();
 
   TestCase test_cases[] = {
       // Any cookie with the same registerable domain as the origins is matched.
@@ -296,13 +303,14 @@
     RunTestCase(test_case, filter);
 }
 
-TEST(BrowsingDataFilterBuilderTest, MatchesCookiesBlacklist) {
-  BrowsingDataFilterBuilder builder(BrowsingDataFilterBuilder::BLACKLIST);
+TEST(RegistrableDomainFilterBuilderTest, MatchesCookiesBlacklist) {
+  RegistrableDomainFilterBuilder builder(
+      RegistrableDomainFilterBuilder::BLACKLIST);
   builder.AddRegisterableDomain(std::string(kGoogleDomain));
   builder.AddRegisterableDomain(std::string(kLongETLDDomain));
   builder.AddRegisterableDomain(std::string(kIPAddress));
   base::Callback<bool(const net::CanonicalCookie&)> filter =
-      builder.BuildDomainCookieFilter();
+      builder.BuildCookieFilter();
 
   TestCase test_cases[] = {
       // Any cookie that doesn't have the same registerable domain is matched.
diff --git a/chrome/browser/resources/options/password_manager.css b/chrome/browser/resources/options/password_manager.css
index fe210f30..18314ef 100644
--- a/chrome/browser/resources/options/password_manager.css
+++ b/chrome/browser/resources/options/password_manager.css
@@ -25,4 +25,4 @@
 
 #passwords-title {
   display: inline-block;
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/resources/options/password_manager.html b/chrome/browser/resources/options/password_manager.html
index 3e258457..81ff66b 100644
--- a/chrome/browser/resources/options/password_manager.html
+++ b/chrome/browser/resources/options/password_manager.html
@@ -2,38 +2,50 @@
   <div class="close-button"></div>
   <h1 i18n-content="passwordsPage"></h1>
   <div class="content-area">
-    <div id="auto-signin-block" class="checkbox" hidden>
-      <label>
-        <input pref="credentials_enable_autosignin" type="checkbox">
-        <span i18n-content="autoSigninTitle"></span>
-      </label>
-      <div class="setting-extra-description">
-        <span i18n-content="autoSigninDescription"></span>
+    <div class="password-manager-home">
+      <div id="auto-signin-block" class="checkbox" hidden>
+        <label>
+          <input pref="credentials_enable_autosignin" type="checkbox">
+          <span i18n-content="autoSigninTitle"></span>
+        </label>
+        <div class="setting-extra-description">
+          <span i18n-content="autoSigninDescription"></span>
+        </div>
       </div>
-    </div>
-    <div id="password-list-headers">
-      <div id="passwords-title">
-        <h3 i18n-content="savedPasswordsTitle"></h3>
+      <div id="password-list-headers">
+        <div id="passwords-title">
+          <h3 i18n-content="savedPasswordsTitle"></h3>
+        </div>
+        <div id="password-search-column">
+          <input id="password-search-box" type="search"
+              i18n-values="placeholder:passwordSearchPlaceholder" incremental>
+        </div>
       </div>
-      <div id="password-search-column">
-        <input id="password-search-box" type="search"
-            i18n-values="placeholder:passwordSearchPlaceholder" incremental>
+      <list id="saved-passwords-list" class="settings-list"></list>
+      <div id="saved-passwords-list-empty-placeholder"
+           class="settings-list-empty" hidden>
+        <span i18n-content="passwordsNoPasswordsDescription"></span>
+        <a target="_blank" i18n-content="learnMore"
+           i18n-values="href:passwordManagerLearnMoreURL"></a>
       </div>
-    </div>
-    <list id="saved-passwords-list" class="settings-list"></list>
-    <div id="saved-passwords-list-empty-placeholder"
-         class="settings-list-empty" hidden>
-      <span i18n-content="passwordsNoPasswordsDescription"></span>
-      <a target="_blank" i18n-content="learnMore"
-         i18n-values="href:passwordManagerLearnMoreURL"></a>
-    </div>
-    <h3 i18n-content="passwordExceptionsTitle"></h3>
-    <list id="password-exceptions-list" class="settings-list"></list>
-    <div id="password-exceptions-list-empty-placeholder" hidden
-         class="settings-list-empty">
-      <span i18n-content="passwordsNoExceptionsDescription"></span>
-      <a id="exceptions-learn-more" target="_blank" i18n-content="learnMore"
-         i18n-values="href:passwordManagerLearnMoreURL"></a>
+      <div class="action-area">
+        <div class="button-strip">
+          <button id="password-manager-import" class="password-manager-home"
+              i18n-content="passwordManagerImportPasswordButtonText" hidden>
+          </button>
+          <button id="password-manager-export" class="password-manager-home"
+              i18n-content="passwordManagerExportPasswordButtonText" hidden>
+          </button>
+        </div>
+      </div>
+      <h3 i18n-content="passwordExceptionsTitle"></h3>
+      <list id="password-exceptions-list" class="settings-list"></list>
+      <div id="password-exceptions-list-empty-placeholder" hidden
+           class="settings-list-empty">
+        <span i18n-content="passwordsNoExceptionsDescription"></span>
+        <a id="exceptions-learn-more" target="_blank" i18n-content="learnMore"
+           i18n-values="href:passwordManagerLearnMoreURL"></a>
+      </div>
     </div>
   </div>
   <div class="action-area">
@@ -46,7 +58,8 @@
     </span>
     <div class="spacer-div"></div>
     <div class="button-strip">
-      <button id="password-manager-confirm" i18n-content="done"></button>
+      <button id="password-manager-confirm" class="password-manager-home"
+          i18n-content="done"></button>
     </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/password_manager.js b/chrome/browser/resources/options/password_manager.js
index a6ee22c..b577701 100644
--- a/chrome/browser/resources/options/password_manager.js
+++ b/chrome/browser/resources/options/password_manager.js
@@ -66,6 +66,14 @@
         PageManager.closeOverlay();
       };
 
+      $('password-manager-import').onclick = function() {
+        chrome.send('importPassword');
+      };
+
+      $('password-manager-export').onclick = function() {
+        chrome.send('exportPassword');
+      };
+
       $('password-search-box').addEventListener('search',
           this.handleSearchQueryChange_.bind(this));
 
@@ -270,6 +278,19 @@
       var item = this.savedPasswordsList_.getListItemByIndex(index);
       item.showPassword(password);
     },
+
+    /**
+     * @param {boolean} visible Whether the link should be visible.
+     * @private
+     */
+    setManageAccountLinkVisibility_: function(visible) {
+      $('manage-passwords-span').hidden = !visible;
+    },
+
+    showImportExportButton_: function() {
+      $('password-manager-import').hidden = false;
+      $('password-manager-export').hidden = false;
+    },
   };
 
   /**
@@ -277,9 +298,9 @@
    * @param {number} rowIndex indicating the row to remove.
    */
   PasswordManager.removeSavedPassword = function(rowIndex) {
-      chrome.send('removeSavedPassword', [String(rowIndex)]);
-      chrome.send('coreOptionsUserMetricsAction',
-                  ['Options_PasswordManagerDeletePassword']);
+    chrome.send('removeSavedPassword', [String(rowIndex)]);
+    chrome.send('coreOptionsUserMetricsAction',
+                ['Options_PasswordManagerDeletePassword']);
   };
 
   /**
@@ -287,7 +308,7 @@
    * @param {number} rowIndex indicating the row to remove.
    */
   PasswordManager.removePasswordException = function(rowIndex) {
-      chrome.send('removePasswordException', [String(rowIndex)]);
+    chrome.send('removePasswordException', [String(rowIndex)]);
   };
 
   PasswordManager.requestShowPassword = function(index) {
@@ -298,7 +319,8 @@
   cr.makePublic(PasswordManager, [
     'setSavedPasswordsList',
     'setPasswordExceptionsList',
-    'showPassword'
+    'showImportExportButton',
+    'showPassword',
   ]);
 
   // Export
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index b9d1732c..9512433 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1276,7 +1276,8 @@
 }
 
 void Browser::HideValidationMessage(content::WebContents* web_contents) {
-  validation_message_bubble_.reset();
+  if (validation_message_bubble_)
+    validation_message_bubble_->CloseValidationMessage();
 }
 
 void Browser::MoveValidationMessage(content::WebContents* web_contents,
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 3cb74011..5c69860 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -1002,7 +1002,7 @@
   // True if the browser window has been shown at least once.
   bool window_has_shown_;
 
-  std::unique_ptr<ValidationMessageBubble> validation_message_bubble_;
+  base::WeakPtr<ValidationMessageBubble> validation_message_bubble_;
 
   SigninViewController signin_view_controller_;
 
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h
index 8dedc92..820842d 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h
+++ b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h
@@ -26,7 +26,7 @@
       ui::ProfileSigninConfirmationDelegate* delegate) override;
   void ShowManagePasswordsBubble(bool user_action) override;
   void HideManagePasswordsBubble() override;
-  std::unique_ptr<ValidationMessageBubble> ShowValidationMessage(
+  base::WeakPtr<ValidationMessageBubble> ShowValidationMessage(
       const gfx::Rect& anchor_in_root_view,
       const base::string16& main_text,
       const base::string16& sub_text) override;
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm
index a089063..6c54c04 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm
+++ b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm
@@ -68,10 +68,10 @@
   // The bubble is closed when it loses the focus.
 }
 
-std::unique_ptr<ValidationMessageBubble> TabDialogsCocoa::ShowValidationMessage(
+base::WeakPtr<ValidationMessageBubble> TabDialogsCocoa::ShowValidationMessage(
     const gfx::Rect& anchor_in_root_view,
     const base::string16& main_text,
     const base::string16& sub_text) {
-  return base::WrapUnique(new ValidationMessageBubbleCocoa(
-      web_contents_, anchor_in_root_view, main_text, sub_text));
+  return (new ValidationMessageBubbleCocoa(
+      web_contents_, anchor_in_root_view, main_text, sub_text))->AsWeakPtr();
 }
diff --git a/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.h b/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.h
index 3defb679..1357fd0e 100644
--- a/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.h
+++ b/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.h
@@ -7,6 +7,7 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/validation_message_bubble.h"
 
 @class ValidationMessageBubbleController;
@@ -15,7 +16,9 @@
 class WebContents;
 }
 
-class ValidationMessageBubbleCocoa : public ValidationMessageBubble {
+class ValidationMessageBubbleCocoa
+    : public ValidationMessageBubble,
+      public base::SupportsWeakPtr<ValidationMessageBubbleCocoa> {
  public:
   ValidationMessageBubbleCocoa(content::WebContents* web_contents,
                                const gfx::Rect& anchor_in_root_view,
@@ -27,6 +30,7 @@
   void SetPositionRelativeToAnchor(
       content::RenderWidgetHost* widget_host,
       const gfx::Rect& anchor_in_root_view) override;
+  void CloseValidationMessage() override;
 
  private:
   base::scoped_nsobject<ValidationMessageBubbleController> controller_;
diff --git a/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm b/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm
index 65932a2..f5e5892 100644
--- a/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/validation_message_bubble_cocoa.mm
@@ -167,12 +167,15 @@
          subText:sub_text] retain]);
 }
 
-ValidationMessageBubbleCocoa::~ValidationMessageBubbleCocoa() {
-  [controller_ close];
-}
+ValidationMessageBubbleCocoa::~ValidationMessageBubbleCocoa() {}
 
 void ValidationMessageBubbleCocoa::SetPositionRelativeToAnchor(
     content::RenderWidgetHost* widget_host,
     const gfx::Rect& anchor_in_root_view) {
   [controller_ setAnchorPoint:GetAnchorPoint(widget_host, anchor_in_root_view)];
 }
+
+void ValidationMessageBubbleCocoa::CloseValidationMessage() {
+  [controller_ close];
+  delete this;
+}
diff --git a/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm
index 6d3ab98..3f7bb1e4 100644
--- a/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/validation_message_bubble_controller_unittest.mm
@@ -40,5 +40,4 @@
   EXPECT_GT(NSHeight(shortMainLongSubFrame), NSHeight(shortMainMediumSubFrame));
 }
 
-}
-
+}  // namespace
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.cc b/chrome/browser/ui/passwords/password_manager_presenter.cc
index 4710a7e..f31826a1 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter.cc
@@ -28,11 +28,13 @@
 #include "components/autofill/core/common/password_form.h"
 #include "components/browser_sync/browser/profile_sync_service.h"
 #include "components/password_manager/core/browser/affiliation_utils.h"
+#include "components/password_manager/core/browser/import/password_importer.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/password_manager/sync/browser/password_sync_util.h"
 #include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -221,19 +223,9 @@
     // is empty). Don't let it crash the browser.
     return;
   }
-  if ((base::TimeTicks::Now() - last_authentication_time_) >
-      base::TimeDelta::FromSeconds(60)) {
-    bool authenticated = true;
-#if defined(OS_WIN)
-    authenticated = password_manager_util_win::AuthenticateUser(
-        password_view_->GetNativeWindow());
-#elif defined(OS_MACOSX)
-    authenticated = password_manager_util_mac::AuthenticateUser();
-#endif
-    if (authenticated)
-      last_authentication_time_ = base::TimeTicks::Now();
-    else
-      return;
+
+  if (!IsUserAuthenticated()) {
+    return;
   }
 
   sync_driver::SyncService* sync_service = nullptr;
@@ -260,6 +252,17 @@
 #endif
 }
 
+std::vector<scoped_ptr<autofill::PasswordForm>>
+PasswordManagerPresenter::GetAllPasswords() {
+  std::vector<scoped_ptr<autofill::PasswordForm>> ret_val;
+
+  for (const auto& form : password_list_) {
+    ret_val.push_back(make_scoped_ptr(new autofill::PasswordForm(*form)));
+  }
+
+  return ret_val;
+}
+
 const autofill::PasswordForm* PasswordManagerPresenter::GetPassword(
     size_t index) {
   if (index >= password_list_.size()) {
@@ -324,6 +327,26 @@
   }
 }
 
+bool PasswordManagerPresenter::IsUserAuthenticated() {
+#if defined(OS_ANDROID)
+  NOTREACHED();
+#endif
+  if (base::TimeTicks::Now() - last_authentication_time_ >
+      base::TimeDelta::FromSeconds(60)) {
+    bool authenticated = true;
+#if defined(OS_WIN)
+    authenticated = password_manager_util_win::AuthenticateUser(
+        password_view_->GetNativeWindow());
+#elif defined(OS_MACOSX)
+    authenticated = password_manager_util_mac::AuthenticateUser();
+#endif
+    if (authenticated)
+      last_authentication_time_ = base::TimeTicks::Now();
+    return authenticated;
+  }
+  return true;
+}
+
 PasswordManagerPresenter::ListPopulater::ListPopulater(
     PasswordManagerPresenter* page) : page_(page) {
 }
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.h b/chrome/browser/ui/passwords/password_manager_presenter.h
index 2729cff..267f317 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.h
+++ b/chrome/browser/ui/passwords/password_manager_presenter.h
@@ -17,6 +17,7 @@
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 #include "components/prefs/pref_member.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
 
 namespace autofill {
 struct PasswordForm;
@@ -52,6 +53,9 @@
   // Gets the password entry at |index|.
   const autofill::PasswordForm* GetPassword(size_t index);
 
+  // Gets all password entries.
+  std::vector<std::unique_ptr<autofill::PasswordForm>> GetAllPasswords();
+
   // Gets the password exception entry at |index|.
   const autofill::PasswordForm* GetPasswordException(size_t index);
 
@@ -67,11 +71,15 @@
   // |index| The index of the entry.
   void RequestShowPassword(size_t index);
 
+  // Returns true if the user is authenticated.
+  virtual bool IsUserAuthenticated();
+
  private:
   friend class PasswordManagerPresenterTest;
 
-  // Returns the password store associated with the currently active profile.
-  password_manager::PasswordStore* GetPasswordStore();
+  // Returns true if the user needs to be authenticated before a plaintext
+  // password is revealed or exported.
+  bool IsAuthenticationRequired();
 
   // Sets the password and exception list of the UI view.
   void SetPasswordList();
@@ -88,6 +96,9 @@
       DuplicatesMap* duplicates,
       bool username_and_password_in_key);
 
+  // Returns the password store associated with the currently active profile.
+  password_manager::PasswordStore* GetPasswordStore();
+
   // A short class to mediate requests to the password store.
   class ListPopulater : public password_manager::PasswordStoreConsumer {
    public:
@@ -136,6 +147,9 @@
   DuplicatesMap password_duplicates_;
   DuplicatesMap password_exception_duplicates_;
 
+  // Whether to show stored passwords or not.
+  BooleanPrefMember show_passwords_;
+
   // The last time the user was successfully authenticated.
   // Used to determine whether or not to reveal plaintext passwords.
   base::TimeTicks last_authentication_time_;
diff --git a/chrome/browser/ui/tab_dialogs.h b/chrome/browser/ui/tab_dialogs.h
index c7ad9b7..ef0f8a9 100644
--- a/chrome/browser/ui/tab_dialogs.h
+++ b/chrome/browser/ui/tab_dialogs.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "base/supports_user_data.h"
 #include "chrome/browser/ui/validation_message_bubble.h"
@@ -63,7 +64,7 @@
   virtual void ShowManagePasswordsBubble(bool user_action) = 0;
   virtual void HideManagePasswordsBubble() = 0;
 
-  virtual std::unique_ptr<ValidationMessageBubble> ShowValidationMessage(
+  virtual base::WeakPtr<ValidationMessageBubble> ShowValidationMessage(
       const gfx::Rect& anchor_in_root_view,
       const base::string16& main_text,
       const base::string16& sub_text) = 0;
diff --git a/chrome/browser/ui/validation_message_bubble.h b/chrome/browser/ui/validation_message_bubble.h
index 8307107b..d4e7378 100644
--- a/chrome/browser/ui/validation_message_bubble.h
+++ b/chrome/browser/ui/validation_message_bubble.h
@@ -21,21 +21,24 @@
  public:
   // Open a tooltip-like window to show the specified messages.  The window
   // should not change focus state.
-  static std::unique_ptr<ValidationMessageBubble> CreateAndShow(
+  static base::WeakPtr<ValidationMessageBubble> CreateAndShow(
       content::RenderWidgetHost* widget_host,
       const gfx::Rect& anchor_in_root_view,
       const base::string16& main_text,
       const base::string16& sub_text);
 
-  // Close the window and destruct the object.
-  virtual ~ValidationMessageBubble() {}
-
   // Move the window to a position such that the bubble arrow points to the
   // specified anchor.  |anchor_in_root_view| is in DIP unit, and relative to
   // RWHV for |widget_host|.
   virtual void SetPositionRelativeToAnchor(
       content::RenderWidgetHost* widget_host,
       const gfx::Rect& anchor_in_root_view) = 0;
+
+  // Called to close the bubble. This should lead to destruction of |this|.
+  virtual void CloseValidationMessage() = 0;
+
+ protected:
+  virtual ~ValidationMessageBubble() {}
 };
 
 #endif  // CHROME_BROWSER_UI_VALIDATION_MESSAGE_BUBBLE_H_
diff --git a/chrome/browser/ui/views/tab_dialogs_views.cc b/chrome/browser/ui/views/tab_dialogs_views.cc
index 617fcff9..a00eead84 100644
--- a/chrome/browser/ui/views/tab_dialogs_views.cc
+++ b/chrome/browser/ui/views/tab_dialogs_views.cc
@@ -74,10 +74,10 @@
     ManagePasswordsBubbleView::CloseCurrentBubble();
 }
 
-std::unique_ptr<ValidationMessageBubble> TabDialogsViews::ShowValidationMessage(
+base::WeakPtr<ValidationMessageBubble> TabDialogsViews::ShowValidationMessage(
     const gfx::Rect& anchor_in_root_view,
     const base::string16& main_text,
     const base::string16& sub_text) {
-  return base::WrapUnique(new ValidationMessageBubbleView(
-      web_contents_, anchor_in_root_view, main_text, sub_text));
+  return (new ValidationMessageBubbleView(
+      web_contents_, anchor_in_root_view, main_text, sub_text))->AsWeakPtr();
 }
diff --git a/chrome/browser/ui/views/tab_dialogs_views.h b/chrome/browser/ui/views/tab_dialogs_views.h
index 6448a87..cabace9 100644
--- a/chrome/browser/ui/views/tab_dialogs_views.h
+++ b/chrome/browser/ui/views/tab_dialogs_views.h
@@ -26,7 +26,7 @@
       ui::ProfileSigninConfirmationDelegate* delegate) override;
   void ShowManagePasswordsBubble(bool user_action) override;
   void HideManagePasswordsBubble() override;
-  std::unique_ptr<ValidationMessageBubble> ShowValidationMessage(
+  base::WeakPtr<ValidationMessageBubble> ShowValidationMessage(
       const gfx::Rect& anchor_in_root_view,
       const base::string16& main_text,
       const base::string16& sub_text) override;
diff --git a/chrome/browser/ui/views/validation_message_bubble_delegate.cc b/chrome/browser/ui/views/validation_message_bubble_delegate.cc
deleted file mode 100644
index ea79333..0000000
--- a/chrome/browser/ui/views/validation_message_bubble_delegate.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/validation_message_bubble_delegate.h"
-
-#include "grit/theme_resources.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/widget/widget.h"
-
-// static
-const int ValidationMessageBubbleDelegate::kWindowMinWidth = 64;
-// static
-const int ValidationMessageBubbleDelegate::kWindowMaxWidth = 256;
-static const int kPadding = 0;
-static const int kIconTextMargin = 8;
-static const int kTextVerticalMargin = 4;
-
-ValidationMessageBubbleDelegate::ValidationMessageBubbleDelegate(
-    const gfx::Rect& anchor_in_screen,
-    const base::string16& main_text,
-    const base::string16& sub_text,
-    Observer* observer)
-    : observer_(observer), width_(0), height_(0) {
-  set_can_activate(false);
-  set_arrow(views::BubbleBorder::TOP_LEFT);
-  SetAnchorRect(anchor_in_screen);
-
-  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
-  views::ImageView* icon = new views::ImageView();
-  icon->SetImage(*bundle.GetImageSkiaNamed(IDR_INPUT_ALERT));
-  gfx::Size size = icon->GetPreferredSize();
-  icon->SetBounds(kPadding, kPadding, size.width(), size.height());
-  AddChildView(icon);
-
-  views::Label* label = new views::Label(
-      main_text, bundle.GetFontList(ui::ResourceBundle::MediumFont));
-  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  int text_start_x = kPadding + size.width() + kIconTextMargin;
-  int min_available = kWindowMinWidth - text_start_x - kPadding;
-  int max_available = kWindowMaxWidth - text_start_x - kPadding;
-  int label_width = label->GetPreferredSize().width();
-  label->SetMultiLine(true);
-  AddChildView(label);
-
-  views::Label* sub_label = NULL;
-  if (!sub_text.empty()) {
-    sub_label = new views::Label(sub_text);
-    sub_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    label_width = std::max(label_width, sub_label->GetPreferredSize().width());
-    sub_label->SetMultiLine(true);
-    AddChildView(sub_label);
-  }
-
-  if (label_width < min_available)
-    label_width = min_available;
-  else if (label_width > max_available)
-    label_width = max_available;
-  label->SetBounds(text_start_x, kPadding,
-                   label_width, label->GetHeightForWidth(label_width));
-  int content_bottom = kPadding + label->height();
-
-  if (sub_label) {
-    sub_label->SetBounds(text_start_x,
-                         content_bottom + kTextVerticalMargin,
-                         label_width,
-                         sub_label->GetHeightForWidth(label_width));
-    content_bottom += kTextVerticalMargin + sub_label->height();
-  }
-
-  width_ = text_start_x + label_width + kPadding;
-  height_ = content_bottom + kPadding;
-}
-
-ValidationMessageBubbleDelegate::~ValidationMessageBubbleDelegate() {}
-
-void ValidationMessageBubbleDelegate::Close() {
-  GetWidget()->Close();
-  observer_ = NULL;
-}
-
-void ValidationMessageBubbleDelegate::SetPositionRelativeToAnchor(
-    const gfx::Rect& anchor_in_screen) {
-  SetAnchorRect(anchor_in_screen);
-}
-
-gfx::Size ValidationMessageBubbleDelegate::GetPreferredSize() const {
-  return gfx::Size(width_, height_);
-}
-
-void ValidationMessageBubbleDelegate::DeleteDelegate() {
-  delete this;
-}
-
-void ValidationMessageBubbleDelegate::WindowClosing() {
-  if (observer_ != NULL)
-    observer_->WindowClosing();
-}
diff --git a/chrome/browser/ui/views/validation_message_bubble_delegate.h b/chrome/browser/ui/views/validation_message_bubble_delegate.h
deleted file mode 100644
index 623c07b8..0000000
--- a/chrome/browser/ui/views/validation_message_bubble_delegate.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_VALIDATION_MESSAGE_BUBBLE_DELEGATE_H_
-#define CHROME_BROWSER_UI_VIEWS_VALIDATION_MESSAGE_BUBBLE_DELEGATE_H_
-
-#include "base/macros.h"
-#include "ui/views/bubble/bubble_delegate.h"
-
-// A BubbleDelegateView implementation for form validation message bubble.
-// This class is exposed for testing.
-class ValidationMessageBubbleDelegate : public views::BubbleDelegateView {
- public:
-  // An interface to observe the widget closing.
-  class Observer {
-   public:
-    virtual void WindowClosing() = 0;
-
-   protected:
-    virtual ~Observer() {}
-  };
-
-  static const int kWindowMinWidth;
-  static const int kWindowMaxWidth;
-
-  ValidationMessageBubbleDelegate(const gfx::Rect& anchor_in_screen,
-                                  const base::string16& main_text,
-                                  const base::string16& sub_text,
-                                  Observer* observer);
-  ~ValidationMessageBubbleDelegate() override;
-
-  void Close();
-  void SetPositionRelativeToAnchor(const gfx::Rect& anchor_in_screen);
-
-  // BubbleDelegateView overrides:
-  gfx::Size GetPreferredSize() const override;
-  void DeleteDelegate() override;
-  void WindowClosing() override;
-
- private:
-  Observer* observer_;
-  int width_;
-  int height_;
-
-  DISALLOW_COPY_AND_ASSIGN(ValidationMessageBubbleDelegate);
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_VALIDATION_MESSAGE_BUBBLE_DELEGATE_H_
diff --git a/chrome/browser/ui/views/validation_message_bubble_delegate_unittest.cc b/chrome/browser/ui/views/validation_message_bubble_delegate_unittest.cc
deleted file mode 100644
index 3b562dd..0000000
--- a/chrome/browser/ui/views/validation_message_bubble_delegate_unittest.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/validation_message_bubble_delegate.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-gfx::Size GetSizeForMessages(const std::string& main_text,
-                             const std::string& sub_text) {
-  ValidationMessageBubbleDelegate delegate(
-      gfx::Rect(), base::UTF8ToUTF16(main_text),
-      base::UTF8ToUTF16(sub_text), NULL);
-  return delegate.GetPreferredSize();
-}
-
-TEST(ValidationMessageBubbleDelegate, Size) {
-  gfx::Size short_main_empty_sub_size = GetSizeForMessages("foo", "");
-  EXPECT_LE(ValidationMessageBubbleDelegate::kWindowMinWidth,
-            short_main_empty_sub_size.width());
-  EXPECT_LE(0, short_main_empty_sub_size.height());
-
-  gfx::Size long_main_empty_sub_size = GetSizeForMessages(
-      "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod"
-      " tempor incididunt ut labore et dolore magna aliqua.", "");
-  EXPECT_GE(ValidationMessageBubbleDelegate::kWindowMaxWidth,
-            long_main_empty_sub_size.width());
-  EXPECT_GT(long_main_empty_sub_size.height(),
-            short_main_empty_sub_size.height());
-
-  gfx::Size short_main_medium_sub_size =
-      GetSizeForMessages("foo", "foo bar baz");
-  EXPECT_GT(short_main_medium_sub_size.width(),
-            short_main_empty_sub_size.width());
-  EXPECT_GT(short_main_medium_sub_size.height(),
-            short_main_empty_sub_size.height());
-
-  gfx::Size short_main_long_sub_size = GetSizeForMessages("foo",
-      "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod"
-      " tempor incididunt ut labore et dolore magna aliqua.");
-  EXPECT_GT(short_main_long_sub_size.width(),
-            short_main_medium_sub_size.width());
-  EXPECT_GE(ValidationMessageBubbleDelegate::kWindowMaxWidth,
-            short_main_long_sub_size.width());
-  EXPECT_GT(short_main_long_sub_size.height(),
-            short_main_medium_sub_size.height());
-}
-
-}
diff --git a/chrome/browser/ui/views/validation_message_bubble_view.cc b/chrome/browser/ui/views/validation_message_bubble_view.cc
index 9eea2ba..223edce0 100644
--- a/chrome/browser/ui/views/validation_message_bubble_view.cc
+++ b/chrome/browser/ui/views/validation_message_bubble_view.cc
@@ -7,38 +7,96 @@
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
 #include "ui/views/widget/widget.h"
 
+namespace {
+
+const int kWindowMinWidth = 64;
+const int kWindowMaxWidth = 256;
+const int kIconTextMargin = 8;
+const int kTextVerticalMargin = 4;
+
+}  // namespace
+
 ValidationMessageBubbleView::ValidationMessageBubbleView(
     content::WebContents* web_contents,
     const gfx::Rect& anchor_in_root_view,
     const base::string16& main_text,
     const base::string16& sub_text) {
   content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
+  set_parent_window(rwhv->GetNativeView());
+
+  set_can_activate(false);
+  set_arrow(views::BubbleBorder::TOP_LEFT);
   const gfx::Rect anchor_in_screen =
       anchor_in_root_view + rwhv->GetViewBounds().origin().OffsetFromOrigin();
-  delegate_ = new ValidationMessageBubbleDelegate(
-      anchor_in_screen, main_text, sub_text, this);
-  delegate_->set_parent_window(rwhv->GetNativeView());
-  views::BubbleDelegateView::CreateBubble(delegate_);
-  delegate_->GetWidget()->ShowInactive();
+  SetAnchorRect(anchor_in_screen);
+
+  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+  views::ImageView* icon = new views::ImageView();
+  icon->SetImage(*bundle.GetImageSkiaNamed(IDR_INPUT_ALERT));
+  icon->SizeToPreferredSize();
+  AddChildView(icon);
+
+  views::Label* label = new views::Label(
+      main_text, bundle.GetFontList(ui::ResourceBundle::MediumFont));
+  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  int text_start_x = icon->bounds().right() + kIconTextMargin;
+  int min_available = kWindowMinWidth - text_start_x;
+  int max_available = kWindowMaxWidth - text_start_x;
+  int label_width = label->GetPreferredSize().width();
+  label->SetMultiLine(true);
+  AddChildView(label);
+
+  views::Label* sub_label = nullptr;
+  if (!sub_text.empty()) {
+    sub_label = new views::Label(sub_text);
+    sub_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    label_width = std::max(label_width, sub_label->GetPreferredSize().width());
+    sub_label->SetMultiLine(true);
+    AddChildView(sub_label);
+  }
+
+  label_width = std::min(std::max(label_width, min_available), max_available);
+  label->SetBounds(text_start_x, 0,
+                   label_width, label->GetHeightForWidth(label_width));
+  int content_bottom = label->height();
+
+  if (sub_label) {
+    sub_label->SetBounds(text_start_x,
+                         content_bottom + kTextVerticalMargin,
+                         label_width,
+                         sub_label->GetHeightForWidth(label_width));
+    content_bottom += kTextVerticalMargin + sub_label->height();
+  }
+
+  size_ = gfx::Size(text_start_x + label_width, content_bottom);
+
+  views::BubbleDialogDelegateView::CreateBubble(this)->ShowInactive();
 }
 
 ValidationMessageBubbleView::~ValidationMessageBubbleView() {
-  if (delegate_)
-    delegate_->Close();
+}
+
+gfx::Size ValidationMessageBubbleView::GetPreferredSize() const {
+  return size_;
+}
+
+int ValidationMessageBubbleView::GetDialogButtons() const {
+  return ui::DIALOG_BUTTON_NONE;
 }
 
 void ValidationMessageBubbleView::SetPositionRelativeToAnchor(
     content::RenderWidgetHost* widget_host,
     const gfx::Rect& anchor_in_root_view) {
-  if (!delegate_)
-    return;
-  delegate_->SetPositionRelativeToAnchor(
-      anchor_in_root_view +
+  SetAnchorRect(anchor_in_root_view +
       widget_host->GetView()->GetViewBounds().origin().OffsetFromOrigin());
 }
 
-void ValidationMessageBubbleView::WindowClosing() {
-  delegate_ = NULL;
+void ValidationMessageBubbleView::CloseValidationMessage() {
+  GetWidget()->Close();
 }
diff --git a/chrome/browser/ui/views/validation_message_bubble_view.h b/chrome/browser/ui/views/validation_message_bubble_view.h
index 3d2f3a05..b496b5bb 100644
--- a/chrome/browser/ui/views/validation_message_bubble_view.h
+++ b/chrome/browser/ui/views/validation_message_bubble_view.h
@@ -6,8 +6,10 @@
 #define CHROME_BROWSER_UI_VIEWS_VALIDATION_MESSAGE_BUBBLE_VIEW_H_
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/validation_message_bubble.h"
-#include "chrome/browser/ui/views/validation_message_bubble_delegate.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/bubble/bubble_dialog_delegate.h"
 
 namespace content {
 class WebContents;
@@ -15,8 +17,9 @@
 
 // A ValidationMessageBubble implementation for Views.
 class ValidationMessageBubbleView
-    : public ValidationMessageBubble,
-      public ValidationMessageBubbleDelegate::Observer {
+    : public views::BubbleDialogDelegateView,
+      public ValidationMessageBubble,
+      public base::SupportsWeakPtr<ValidationMessageBubbleView> {
  public:
   ValidationMessageBubbleView(content::WebContents* web_contents,
                               const gfx::Rect& anchor_in_root_view,
@@ -24,16 +27,18 @@
                               const base::string16& sub_text);
   ~ValidationMessageBubbleView() override;
 
+  // BubbleDialogDelegateView overrides:
+  gfx::Size GetPreferredSize() const override;
+  int GetDialogButtons() const override;
+
   // ValidationMessageBubble overrides:
   void SetPositionRelativeToAnchor(
       content::RenderWidgetHost* widget_host,
       const gfx::Rect& anchor_in_root_view) override;
-
-  // ValidationMessageBubbleDelegate::Observer overrides:
-  void WindowClosing() override;
+  void CloseValidationMessage() override;
 
  private:
-  ValidationMessageBubbleDelegate* delegate_;
+  gfx::Size size_;
 
   DISALLOW_COPY_AND_ASSIGN(ValidationMessageBubbleView);
 };
diff --git a/chrome/browser/ui/webui/options/password_manager_handler.cc b/chrome/browser/ui/webui/options/password_manager_handler.cc
index 2f76d3e..f4698d8 100644
--- a/chrome/browser/ui/webui/options/password_manager_handler.cc
+++ b/chrome/browser/ui/webui/options/password_manager_handler.cc
@@ -5,28 +5,39 @@
 #include "chrome/browser/ui/webui/options/password_manager_handler.h"
 
 #include "base/bind.h"
+#include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
 #include "base/feature_list.h"
+#include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/browser_sync/browser/profile_sync_service.h"
+#include "components/password_manager/core/browser/export/password_exporter.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
 #include "components/password_manager/core/browser/password_manager_constants.h"
+#include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/password_manager/core/common/experiments.h"
+#include "components/password_manager/core/common/password_manager_features.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/url_formatter.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/user_metrics.h"
@@ -77,8 +88,13 @@
 
 }  // namespace
 
-PasswordManagerHandler::PasswordManagerHandler()
-    : password_manager_presenter_(this) {}
+PasswordManagerHandler::PasswordManagerHandler() {
+  password_manager_presenter_.reset(new PasswordManagerPresenter(this));
+}
+
+PasswordManagerHandler::PasswordManagerHandler(
+    scoped_ptr<PasswordManagerPresenter> presenter)
+    : password_manager_presenter_(std::move(presenter)) {}
 
 PasswordManagerHandler::~PasswordManagerHandler() {}
 
@@ -109,6 +125,10 @@
        IDS_PASSWORDS_PAGE_VIEW_NO_PASSWORDS_DESCRIPTION},
       {"passwordsNoExceptionsDescription",
        IDS_PASSWORDS_PAGE_VIEW_NO_EXCEPTIONS_DESCRIPTION},
+      {"passwordManagerImportPasswordButtonText",
+       IDS_PASSWORD_MANAGER_IMPORT_BUTTON},
+      {"passwordManagerExportPasswordButtonText",
+       IDS_PASSWORD_MANAGER_EXPORT_BUTTON},
   };
 
   RegisterStrings(localized_strings, resources, arraysize(resources));
@@ -175,10 +195,25 @@
       "requestShowPassword",
       base::Bind(&PasswordManagerHandler::HandleRequestShowPassword,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "importPassword",
+      base::Bind(&PasswordManagerHandler::HandlePasswordImport,
+                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "exportPassword",
+      base::Bind(&PasswordManagerHandler::HandlePasswordExport,
+                 base::Unretained(this)));
 }
 
 void PasswordManagerHandler::InitializeHandler() {
-  password_manager_presenter_.Initialize();
+  password_manager_presenter_->Initialize();
+}
+
+void PasswordManagerHandler::InitializePage() {
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::kPasswordImportExport)) {
+    web_ui()->CallJavascriptFunction("PasswordManager.showImportExportButton");
+  }
 }
 
 void PasswordManagerHandler::HandleRemoveSavedPassword(
@@ -186,7 +221,8 @@
   std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
   int index;
   if (base::StringToInt(string_value, &index) && index >= 0) {
-    password_manager_presenter_.RemoveSavedPassword(static_cast<size_t>(index));
+    password_manager_presenter_->RemoveSavedPassword(
+        static_cast<size_t>(index));
   }
 }
 
@@ -195,7 +231,7 @@
   std::string string_value = base::UTF16ToUTF8(ExtractStringValue(args));
   int index;
   if (base::StringToInt(string_value, &index) && index >= 0) {
-    password_manager_presenter_.RemovePasswordException(
+    password_manager_presenter_->RemovePasswordException(
         static_cast<size_t>(index));
   }
 }
@@ -206,7 +242,7 @@
   if (!ExtractIntegerValue(args, &index))
     NOTREACHED();
 
-  password_manager_presenter_.RequestShowPassword(static_cast<size_t>(index));
+  password_manager_presenter_->RequestShowPassword(static_cast<size_t>(index));
 }
 
 void PasswordManagerHandler::ShowPassword(
@@ -223,7 +259,7 @@
 
 void PasswordManagerHandler::HandleUpdatePasswordLists(
     const base::ListValue* args) {
-  password_manager_presenter_.UpdatePasswordLists();
+  password_manager_presenter_->UpdatePasswordLists();
 }
 
 void PasswordManagerHandler::SetPasswordList(
@@ -268,4 +304,116 @@
                                    entries);
 }
 
+void PasswordManagerHandler::FileSelected(const base::FilePath& path,
+                                          int index,
+                                          void* params) {
+  switch (static_cast<FileSelectorCaller>(reinterpret_cast<intptr_t>(params))) {
+    case IMPORT_FILE_SELECTED:
+      ImportPasswordFileSelected(path);
+      break;
+    case EXPORT_FILE_SELECTED:
+      ExportPasswordFileSelected(path);
+      break;
+  }
+}
+
+void PasswordManagerHandler::HandlePasswordImport(const base::ListValue* args) {
+#if !defined(OS_ANDROID)  // This is never called on Android.
+  ui::SelectFileDialog::FileTypeInfo file_type_info;
+
+  file_type_info.extensions =
+      password_manager::PasswordImporter::GetSupportedFileExtensions();
+  DCHECK(!file_type_info.extensions.empty() &&
+         !file_type_info.extensions[0].empty());
+  file_type_info.include_all_files = true;
+  ChromeSelectFilePolicy* select_file_policy =
+      new ChromeSelectFilePolicy(web_ui()->GetWebContents());
+  ANNOTATE_LEAKING_OBJECT_PTR(select_file_policy);
+  select_file_dialog_ = ui::SelectFileDialog::Create(this, select_file_policy);
+  select_file_dialog_->SelectFile(
+      ui::SelectFileDialog::SELECT_OPEN_FILE,
+      l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_IMPORT_DIALOG_TITLE),
+      base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
+      web_ui()->GetWebContents()->GetTopLevelNativeWindow(),
+      reinterpret_cast<void*>(IMPORT_FILE_SELECTED));
+#endif
+}
+
+void PasswordManagerHandler::ImportPasswordFileSelected(
+    const base::FilePath& path) {
+  scoped_refptr<ImportPasswordResultConsumer> form_consumer(
+      new ImportPasswordResultConsumer(GetProfile()));
+
+  password_manager::PasswordImporter::Import(
+      path, content::BrowserThread::GetMessageLoopProxyForThread(
+                content::BrowserThread::FILE)
+                .get(),
+      base::Bind(&ImportPasswordResultConsumer::ConsumePassword,
+                 form_consumer));
+}
+
+PasswordManagerHandler::ImportPasswordResultConsumer::
+    ImportPasswordResultConsumer(Profile* profile)
+    : profile_(profile) {}
+
+void PasswordManagerHandler::ImportPasswordResultConsumer::ConsumePassword(
+    password_manager::PasswordImporter::Result result,
+    const std::vector<autofill::PasswordForm>& forms) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "PasswordManager.ImportPasswordFromCSVResult", result,
+      password_manager::PasswordImporter::NUM_IMPORT_RESULTS);
+  if (result != password_manager::PasswordImporter::SUCCESS)
+    return;
+
+  UMA_HISTOGRAM_COUNTS("PasswordManager.ImportedPasswordsPerUserInCSV",
+                       forms.size());
+
+  scoped_refptr<password_manager::PasswordStore> store(
+      PasswordStoreFactory::GetForProfile(profile_,
+                                          ServiceAccessType::EXPLICIT_ACCESS));
+  if (store) {
+    for (const autofill::PasswordForm& form : forms) {
+      store->AddLogin(form);
+    }
+  }
+  UMA_HISTOGRAM_BOOLEAN("PasswordManager.StorePasswordImportedFromCSVResult",
+                        store);
+}
+
+void PasswordManagerHandler::HandlePasswordExport(const base::ListValue* args) {
+#if !defined(OS_ANDROID)  // This is never called on Android.
+  if (!password_manager_presenter_->IsUserAuthenticated())
+    return;
+
+  ui::SelectFileDialog::FileTypeInfo file_type_info;
+  file_type_info.extensions =
+      password_manager::PasswordExporter::GetSupportedFileExtensions();
+  DCHECK(!file_type_info.extensions.empty() &&
+         !file_type_info.extensions[0].empty());
+  file_type_info.include_all_files = true;
+  ChromeSelectFilePolicy* select_file_policy =
+      new ChromeSelectFilePolicy(web_ui()->GetWebContents());
+  ANNOTATE_LEAKING_OBJECT_PTR(select_file_policy);
+  select_file_dialog_ = ui::SelectFileDialog::Create(this, select_file_policy);
+  select_file_dialog_->SelectFile(
+      ui::SelectFileDialog::SELECT_SAVEAS_FILE,
+      l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EXPORT_DIALOG_TITLE),
+      base::FilePath(), &file_type_info, 1, file_type_info.extensions[0][0],
+      GetNativeWindow(), reinterpret_cast<void*>(EXPORT_FILE_SELECTED));
+#endif
+}
+
+void PasswordManagerHandler::ExportPasswordFileSelected(
+    const base::FilePath& path) {
+  std::vector<scoped_ptr<autofill::PasswordForm>> password_list =
+      password_manager_presenter_->GetAllPasswords();
+  UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
+                       password_list.size());
+  password_manager::PasswordExporter::Export(
+      path, std::move(password_list),
+      content::BrowserThread::GetMessageLoopProxyForThread(
+          content::BrowserThread::FILE)
+          .get());
+}
+
 }  // namespace options
diff --git a/chrome/browser/ui/webui/options/password_manager_handler.h b/chrome/browser/ui/webui/options/password_manager_handler.h
index 520dbb8..aa5525c 100644
--- a/chrome/browser/ui/webui/options/password_manager_handler.h
+++ b/chrome/browser/ui/webui/options/password_manager_handler.h
@@ -10,27 +10,46 @@
 #include <string>
 #include <vector>
 
+#include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/passwords/password_manager_presenter.h"
 #include "chrome/browser/ui/passwords/password_ui_view.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
+#include "components/password_manager/core/browser/import/password_importer.h"
 #include "components/prefs/pref_member.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+
+class PasswordManagerHandlerTest;
 
 namespace options {
 
 // The WebUI based PasswordUIView. Displays passwords in the web ui.
 class PasswordManagerHandler : public OptionsPageUIHandler,
-                               public PasswordUIView {
+                               public PasswordUIView,
+                               public ui::SelectFileDialog::Listener {
  public:
+  // Enumeration of different callers of SelectFile.
+  enum FileSelectorCaller {
+    IMPORT_FILE_SELECTED,
+    EXPORT_FILE_SELECTED,
+  };
+
   PasswordManagerHandler();
   ~PasswordManagerHandler() override;
 
   // OptionsPageUIHandler implementation.
   void GetLocalizedValues(base::DictionaryValue* localized_strings) override;
   void InitializeHandler() override;
+  void InitializePage() override;
   void RegisterMessages() override;
 
+  // ui::SelectFileDialog::Listener implementation.
+  // |params| is of type FileSelectorCaller which indicates direction of IO.
+  void FileSelected(const base::FilePath& path,
+                    int index,
+                    void* params) override;
+
   // PasswordUIView implementation.
   Profile* GetProfile() override;
   void ShowPassword(
@@ -47,6 +66,12 @@
 #if !defined(OS_ANDROID)
   gfx::NativeWindow GetNativeWindow() const override;
 #endif
+
+ protected:
+  // This constructor is used for testing only.
+  explicit PasswordManagerHandler(
+      scoped_ptr<PasswordManagerPresenter> presenter);
+
  private:
   // Clears and then populates the list of passwords and password exceptions.
   // Called when the JS PasswordManager object is initialized.
@@ -64,8 +89,48 @@
   // |index| The index of the entry.
   void HandleRequestShowPassword(const base::ListValue* args);
 
-  // The PasswordManagerPresenter object owned by the this view.
-  PasswordManagerPresenter password_manager_presenter_;
+  // Import from CSV/JSON file. The steps are:
+  //   1. user click import button -> HandlePasswordImport() ->
+  //   start file selector
+  //   2. user selects file -> ImportPasswordFileSeleted() -> read to memory
+  //   3. read completes -> ImportPasswordFileRead() -> store to PasswordStore
+  void HandlePasswordImport(const base::ListValue* args);
+  void ImportPasswordFileSelected(const base::FilePath& path);
+  void ImportPasswordFileRead(password_manager::PasswordImporter::Result result,
+                              const std::vector<autofill::PasswordForm>& forms);
+
+  // Export to CSV/JSON file. The steps are:
+  //   1. user click export button -> HandlePasswordExport() ->
+  //   check OS password if necessary -> start file selector
+  //   2. user selects file -> ExportPasswordFileSeleted() ->
+  //   write to memory buffer -> start write operation
+  void HandlePasswordExport(const base::ListValue* args);
+  void ExportPasswordFileSelected(const base::FilePath& path);
+
+  // A short class to persist imported password forms to password store.
+  class ImportPasswordResultConsumer
+      : public base::RefCountedThreadSafe<ImportPasswordResultConsumer> {
+   public:
+    explicit ImportPasswordResultConsumer(Profile* profile);
+
+    void ConsumePassword(password_manager::PasswordImporter::Result result,
+                         const std::vector<autofill::PasswordForm>& forms);
+
+   private:
+    friend class base::RefCountedThreadSafe<ImportPasswordResultConsumer>;
+
+    ~ImportPasswordResultConsumer() {}
+
+    Profile* profile_;
+  };
+
+  // User pref for storing accept languages.
+  std::string languages_;
+
+  scoped_ptr<PasswordManagerPresenter> password_manager_presenter_;
+
+  // File picker to import/export file path.
+  scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
 
   DISALLOW_COPY_AND_ASSIGN(PasswordManagerHandler);
 };
diff --git a/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc b/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc
new file mode 100644
index 0000000..8ba4583
--- /dev/null
+++ b/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc
@@ -0,0 +1,237 @@
+// Copyright 2016 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/metrics/histogram.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/browser/ui/passwords/password_manager_presenter.h"
+#include "chrome/browser/ui/webui/options/password_manager_handler.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/password_manager/core/browser/mock_password_store.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_web_ui.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/select_file_dialog_factory.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+using password_manager::MockPasswordStore;
+
+namespace {
+class TestSelectFileDialogFactory final : public ui::SelectFileDialogFactory {
+ public:
+  TestSelectFileDialogFactory() {}
+  ~TestSelectFileDialogFactory() override {}
+  ui::SelectFileDialog* Create(ui::SelectFileDialog::Listener* listener,
+                               ui::SelectFilePolicy* policy) override {
+    return new TestSelectFileDialog(listener, new TestSelectFilePolicy);
+  }
+
+ private:
+  class TestSelectFilePolicy : public ui::SelectFilePolicy {
+   public:
+    bool CanOpenSelectFileDialog() override { return true; }
+    void SelectFileDenied() override {}
+  };
+
+  class TestSelectFileDialog : public ui::SelectFileDialog {
+   public:
+    TestSelectFileDialog(Listener* listener, ui::SelectFilePolicy* policy)
+        : ui::SelectFileDialog(listener, policy) {}
+
+   protected:
+    void SelectFileImpl(Type type,
+                        const base::string16& title,
+                        const base::FilePath& default_path,
+                        const FileTypeInfo* file_types,
+                        int file_type_index,
+                        const base::FilePath::StringType& default_extension,
+                        gfx::NativeWindow owning_window,
+                        void* params) override {
+      listener_->FileSelected(default_path, file_type_index, params);
+    }
+    bool IsRunning(gfx::NativeWindow owning_window) const override {
+      return false;
+    }
+    void ListenerDestroyed() override {}
+    bool HasMultipleFileTypeChoicesImpl() override { return false; }
+    ~TestSelectFileDialog() override {}
+  };
+};
+
+class CallbackTestWebUI : public content::TestWebUI {
+ public:
+  CallbackTestWebUI() {}
+  ~CallbackTestWebUI() override {}
+  void RegisterMessageCallback(const std::string& message,
+                               const MessageCallback& callback) override;
+  void ProcessWebUIMessage(const GURL& source_url,
+                           const std::string& message,
+                           const base::ListValue& args) override;
+
+  MOCK_CONST_METHOD0(GetWebContents, content::WebContents*());
+
+ private:
+  std::map<std::string, MessageCallback> message_callbacks_;
+};
+
+void CallbackTestWebUI::RegisterMessageCallback(
+    const std::string& message,
+    const MessageCallback& callback) {
+  message_callbacks_.insert(std::make_pair(message, callback));
+}
+
+void CallbackTestWebUI::ProcessWebUIMessage(const GURL& source_url,
+                                            const std::string& message,
+                                            const base::ListValue& args) {
+  std::map<std::string, MessageCallback>::const_iterator callback =
+      message_callbacks_.find(message);
+  if (callback != message_callbacks_.end()) {
+    callback->second.Run(&args);
+  }
+}
+
+class TestPasswordManagerHandler : public options::PasswordManagerHandler {
+ public:
+  TestPasswordManagerHandler(scoped_ptr<PasswordManagerPresenter> presenter,
+                             CallbackTestWebUI* web_ui)
+      : PasswordManagerHandler(std::move(presenter)) {
+    set_web_ui(web_ui);
+  }
+  ~TestPasswordManagerHandler() override {}
+#if !defined(OS_ANDROID)
+  gfx::NativeWindow GetNativeWindow() const override;
+#endif
+
+  MOCK_METHOD3(FileSelected, void(const base::FilePath& path, int, void*));
+};
+#if !defined(OS_ANDROID)
+gfx::NativeWindow TestPasswordManagerHandler::GetNativeWindow() const {
+  return NULL;
+}
+#endif
+
+class MockPasswordManagerPresenter : public PasswordManagerPresenter {
+ public:
+  explicit MockPasswordManagerPresenter(PasswordUIView* handler)
+      : PasswordManagerPresenter(handler) {}
+  ~MockPasswordManagerPresenter() override {}
+
+  MOCK_METHOD0(IsUserAuthenticated, bool());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerPresenter);
+};
+
+class DummyPasswordManagerHandler : public PasswordUIView {
+ public:
+  DummyPasswordManagerHandler() : password_manager_presenter_(this) {
+    password_manager_presenter_.Initialize();
+  }
+  ~DummyPasswordManagerHandler() override {}
+  Profile* GetProfile() override;
+
+  void ShowPassword(size_t,
+                    const std::string&,
+                    const std::string&,
+                    const base::string16&) override {}
+  void SetPasswordList(
+      const std::vector<scoped_ptr<autofill::PasswordForm>>&) override {}
+  void SetPasswordExceptionList(
+      const std::vector<scoped_ptr<autofill::PasswordForm>>&) override {}
+
+#if !defined(OS_ANDROID)
+  gfx::NativeWindow GetNativeWindow() const override;
+#endif
+ private:
+  TestingProfile profile_;
+  PasswordManagerPresenter password_manager_presenter_;
+
+  DISALLOW_COPY_AND_ASSIGN(DummyPasswordManagerHandler);
+};
+
+#if !defined(OS_ANDROID)
+gfx::NativeWindow DummyPasswordManagerHandler::GetNativeWindow() const {
+  return NULL;
+}
+#endif
+
+Profile* DummyPasswordManagerHandler::GetProfile() {
+  return &profile_;
+}
+
+}  // namespace
+
+class PasswordManagerHandlerTest : public testing::Test {
+ protected:
+  PasswordManagerHandlerTest() {
+    dummy_handler_.reset(new DummyPasswordManagerHandler());
+    presenter_raw_ = new MockPasswordManagerPresenter(dummy_handler_.get());
+    web_contents_ =
+        content::WebContentsTester::CreateTestWebContents(&profile_, NULL);
+    web_ui_.set_web_contents(web_contents_);
+    handler_.reset(new TestPasswordManagerHandler(
+        make_scoped_ptr(presenter_raw_), &web_ui_));
+    handler_->RegisterMessages();
+    ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactory);
+    handler_->InitializeHandler();
+  }
+
+  ~PasswordManagerHandlerTest() override {}
+
+  void ExportPassword() {
+    base::ListValue tmp;
+    web_ui_.ProcessWebUIMessage(GURL(), "exportPassword", tmp);
+  }
+
+  void ImportPassword() {
+    base::ListValue tmp;
+    web_ui_.ProcessWebUIMessage(GURL(), "importPassword", tmp);
+  }
+
+  PasswordManagerPresenter* presenter_raw_;
+  CallbackTestWebUI web_ui_;
+  content::WebContents* web_contents_;
+  scoped_ptr<DummyPasswordManagerHandler> dummy_handler_;
+  scoped_ptr<TestPasswordManagerHandler> handler_;
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordManagerHandlerTest);
+};
+
+MATCHER(IsEmptyPath, "") {
+  return arg.empty();
+}
+
+TEST_F(PasswordManagerHandlerTest, PasswordImport) {
+  EXPECT_CALL(web_ui_, GetWebContents())
+      .WillRepeatedly(testing::Return(web_contents_));
+  EXPECT_CALL(
+      *handler_,
+      FileSelected(IsEmptyPath(), 1,
+                   reinterpret_cast<void*>(
+                       TestPasswordManagerHandler::IMPORT_FILE_SELECTED)));
+  ImportPassword();
+}
+
+TEST_F(PasswordManagerHandlerTest, PasswordExport) {
+  const base::FilePath file_path;
+  EXPECT_CALL(*(static_cast<MockPasswordManagerPresenter*>(presenter_raw_)),
+              IsUserAuthenticated())
+      .Times(testing::AtLeast(1))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(
+      *handler_,
+      FileSelected(IsEmptyPath(), 1,
+                   reinterpret_cast<void*>(
+                       TestPasswordManagerHandler::EXPORT_FILE_SELECTED)));
+  ExportPassword();
+}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 459dd0d9..2142bab 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -111,8 +111,11 @@
       'browser/browsing_data/history_counter.h',
       'browser/browsing_data/local_data_container.cc',
       'browser/browsing_data/local_data_container.h',
+      'browser/browsing_data/origin_filter_builder.cc',
+      'browser/browsing_data/origin_filter_builder.h',
       'browser/browsing_data/passwords_counter.cc',
       'browser/browsing_data/passwords_counter.h',
+      'browser/browsing_data/registrable_domain_filter_builder.cc',
       'browser/character_encoding.cc',
       'browser/character_encoding.h',
       'browser/chrome_browser_application_mac.h',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 0713b83..875617171 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -2519,8 +2519,6 @@
       'browser/ui/views/translate/translate_icon_view.h',
       'browser/ui/views/update_recommended_message_box.cc',
       'browser/ui/views/update_recommended_message_box.h',
-      'browser/ui/views/validation_message_bubble_delegate.cc',
-      'browser/ui/views/validation_message_bubble_delegate.h',
       'browser/ui/views/validation_message_bubble_view.cc',
       'browser/ui/views/validation_message_bubble_view.h',
       'browser/ui/views/web_contents_modal_dialog_manager_views.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index eed998e3..b6633b11 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -13,8 +13,8 @@
       'renderer/chrome_content_renderer_client.h',
       'renderer/chrome_render_frame_observer.cc',
       'renderer/chrome_render_frame_observer.h',
-      'renderer/chrome_render_process_observer.cc',
-      'renderer/chrome_render_process_observer.h',
+      'renderer/chrome_render_thread_observer.cc',
+      'renderer/chrome_render_thread_observer.h',
       'renderer/chrome_render_view_observer.cc',
       'renderer/chrome_render_view_observer.h',
       'renderer/content_settings_observer.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 302525b..486fd976 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -49,7 +49,6 @@
       'browser/browsing_data/browsing_data_counter_utils_unittest.cc',
       'browser/browsing_data/browsing_data_database_helper_unittest.cc',
       'browser/browsing_data/browsing_data_file_system_helper_unittest.cc',
-      'browser/browsing_data/browsing_data_filter_builder_unittest.cc',
       'browser/browsing_data/browsing_data_helper_unittest.cc',
       'browser/browsing_data/browsing_data_indexed_db_helper_unittest.cc',
       'browser/browsing_data/browsing_data_local_storage_helper_unittest.cc',
@@ -59,6 +58,8 @@
       'browser/browsing_data/browsing_data_remover_unittest.cc',
       'browser/browsing_data/browsing_data_service_worker_helper_unittest.cc',
       'browser/browsing_data/cookies_tree_model_unittest.cc',
+      'browser/browsing_data/origin_filter_builder_unittest.cc',
+      'browser/browsing_data/registrable_domain_filter_builder_unittest.cc',
       'browser/chrome_browser_application_mac_unittest.mm',
       'browser/chrome_content_browser_client_unittest.cc',
       'browser/chrome_elf_init_unittest_win.cc',
@@ -1385,7 +1386,6 @@
       'browser/ui/views/toolbar/toolbar_action_view_unittest.cc',
       'browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc',
       'browser/ui/views/translate/translate_bubble_view_unittest.cc',
-      'browser/ui/views/validation_message_bubble_delegate_unittest.cc',
     ],
     'chrome_unit_tests_win_sources': [
       'app/chrome_dll.rc',
@@ -1565,6 +1565,7 @@
       'browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc',
       'browser/ui/webui/options/autofill_options_handler_unittest.cc',
       'browser/ui/webui/options/language_options_handler_unittest.cc',
+      'browser/ui/webui/options/password_manager_handler_unittest.cc',
       'browser/ui/webui/options/pepper_flash_content_settings_utils_unittest.cc',
       'browser/ui/webui/options/sync_setup_handler_unittest.cc',
       'browser/ui/webui/settings_utils_unittest.cc',
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 54b9be85..3be44db4e 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -35,7 +35,7 @@
 #include "chrome/renderer/banners/app_banner_client.h"
 #include "chrome/renderer/benchmarking_extension.h"
 #include "chrome/renderer/chrome_render_frame_observer.h"
-#include "chrome/renderer/chrome_render_process_observer.h"
+#include "chrome/renderer/chrome_render_thread_observer.h"
 #include "chrome/renderer/chrome_render_view_observer.h"
 #include "chrome/renderer/content_settings_observer.h"
 #include "chrome/renderer/external_extension.h"
@@ -77,7 +77,7 @@
 #include "components/startup_metric_utils/common/startup_metric_messages.h"
 #include "components/version_info/version_info.h"
 #include "components/visitedlink/renderer/visitedlink_slave.h"
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_render_thread_observer.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
@@ -331,8 +331,8 @@
   thread->Send(new StartupMetricHostMsg_RecordRendererMainEntryTime(
       main_entry_time_));
 
-  chrome_observer_.reset(new ChromeRenderProcessObserver());
-  web_cache_observer_.reset(new web_cache::WebCacheRenderProcessObserver());
+  chrome_observer_.reset(new ChromeRenderThreadObserver());
+  web_cache_observer_.reset(new web_cache::WebCacheRenderThreadObserver());
 
 #if defined(ENABLE_EXTENSIONS)
   ChromeExtensionsRendererClient::GetInstance()->RenderThreadStarted();
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index e95cef6..aa3c859 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -20,7 +20,7 @@
 #include "ipc/ipc_channel_proxy.h"
 #include "v8/include/v8.h"
 
-class ChromeRenderProcessObserver;
+class ChromeRenderThreadObserver;
 #if defined(ENABLE_PRINT_PREVIEW)
 class ChromePDFPrintClient;
 #endif
@@ -59,7 +59,7 @@
 }
 
 namespace web_cache {
-class WebCacheRenderProcessObserver;
+class WebCacheRenderThreadObserver;
 }
 
 namespace blink {
@@ -196,8 +196,8 @@
                             blink::WebPluginParams* params);
 #endif
 
-  std::unique_ptr<ChromeRenderProcessObserver> chrome_observer_;
-  std::unique_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
+  std::unique_ptr<ChromeRenderThreadObserver> chrome_observer_;
+  std::unique_ptr<web_cache::WebCacheRenderThreadObserver> web_cache_observer_;
 
   std::unique_ptr<network_hints::PrescientNetworkingDispatcher>
       prescient_networking_dispatcher_;
diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc
similarity index 93%
rename from chrome/renderer/chrome_render_process_observer.cc
rename to chrome/renderer/chrome_render_thread_observer.cc
index 96e52b0..aedcebff 100644
--- a/chrome/renderer/chrome_render_process_observer.cc
+++ b/chrome/renderer/chrome_render_thread_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/renderer/chrome_render_process_observer.h"
+#include "chrome/renderer/chrome_render_thread_observer.h"
 
 #include <stddef.h>
 
@@ -132,7 +132,7 @@
 class ResourceUsageReporterImpl : public mojom::ResourceUsageReporter {
  public:
   ResourceUsageReporterImpl(
-      base::WeakPtr<ChromeRenderProcessObserver> observer,
+      base::WeakPtr<ChromeRenderThreadObserver> observer,
       mojo::InterfaceRequest<mojom::ResourceUsageReporter> req)
       : workers_to_go_(0),
         binding_(this, std::move(req)),
@@ -222,7 +222,7 @@
   mojo::Callback<void(mojom::ResourceUsageDataPtr)> callback_;
   int workers_to_go_;
   mojo::StrongBinding<mojom::ResourceUsageReporter> binding_;
-  base::WeakPtr<ChromeRenderProcessObserver> observer_;
+  base::WeakPtr<ChromeRenderThreadObserver> observer_;
 
   base::WeakPtrFactory<ResourceUsageReporterImpl> weak_factory_;
 
@@ -230,16 +230,16 @@
 };
 
 void CreateResourceUsageReporter(
-    base::WeakPtr<ChromeRenderProcessObserver> observer,
+    base::WeakPtr<ChromeRenderThreadObserver> observer,
     mojo::InterfaceRequest<mojom::ResourceUsageReporter> request) {
   new ResourceUsageReporterImpl(observer, std::move(request));
 }
 
 }  // namespace
 
-bool ChromeRenderProcessObserver::is_incognito_process_ = false;
+bool ChromeRenderThreadObserver::is_incognito_process_ = false;
 
-ChromeRenderProcessObserver::ChromeRenderProcessObserver()
+ChromeRenderThreadObserver::ChromeRenderThreadObserver()
     : weak_factory_(this) {
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
@@ -276,9 +276,9 @@
       native_scheme);
 }
 
-ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {}
+ChromeRenderThreadObserver::~ChromeRenderThreadObserver() {}
 
-void ChromeRenderProcessObserver::InitFieldTrialObserving(
+void ChromeRenderThreadObserver::InitFieldTrialObserving(
     const base::CommandLine& command_line) {
   // Set up initial set of crash dump data for field trials in this renderer.
   variations::SetVariationListCrashKeys();
@@ -306,10 +306,10 @@
   }
 }
 
-bool ChromeRenderProcessObserver::OnControlMessageReceived(
+bool ChromeRenderThreadObserver::OnControlMessageReceived(
     const IPC::Message& message) {
   bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
+  IPC_BEGIN_MESSAGE_MAP(ChromeRenderThreadObserver, message)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
                         OnSetIsIncognitoProcess)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
@@ -320,17 +320,17 @@
   return handled;
 }
 
-void ChromeRenderProcessObserver::OnSetIsIncognitoProcess(
+void ChromeRenderThreadObserver::OnSetIsIncognitoProcess(
     bool is_incognito_process) {
   is_incognito_process_ = is_incognito_process;
 }
 
-void ChromeRenderProcessObserver::OnSetContentSettingRules(
+void ChromeRenderThreadObserver::OnSetContentSettingRules(
     const RendererContentSettingRules& rules) {
   content_setting_rules_ = rules;
 }
 
-void ChromeRenderProcessObserver::OnSetFieldTrialGroup(
+void ChromeRenderThreadObserver::OnSetFieldTrialGroup(
     const std::string& field_trial_name,
     const std::string& group_name,
     base::ProcessId sender_pid) {
@@ -367,11 +367,11 @@
 }
 
 const RendererContentSettingRules*
-ChromeRenderProcessObserver::content_setting_rules() const {
+ChromeRenderThreadObserver::content_setting_rules() const {
   return &content_setting_rules_;
 }
 
-void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized(
+void ChromeRenderThreadObserver::OnFieldTrialGroupFinalized(
     const std::string& trial_name,
     const std::string& group_name) {
   content::RenderThread::Get()->Send(
diff --git a/chrome/renderer/chrome_render_process_observer.h b/chrome/renderer/chrome_render_thread_observer.h
similarity index 79%
rename from chrome/renderer/chrome_render_process_observer.h
rename to chrome/renderer/chrome_render_thread_observer.h
index ca8720e..a59cec6 100644
--- a/chrome/renderer/chrome_render_process_observer.h
+++ b/chrome/renderer/chrome_render_thread_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_RENDERER_CHROME_RENDER_PROCESS_OBSERVER_H_
-#define CHROME_RENDERER_CHROME_RENDER_PROCESS_OBSERVER_H_
+#ifndef CHROME_RENDERER_CHROME_RENDER_THREAD_OBSERVER_H_
+#define CHROME_RENDERER_CHROME_RENDER_THREAD_OBSERVER_H_
 
 #include <memory>
 #include <string>
@@ -15,7 +15,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/process/process.h"
 #include "components/content_settings/core/common/content_settings.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 class GURL;
 struct ContentSettings;
@@ -32,16 +32,16 @@
 // a RenderView) for Chrome specific messages that the content layer doesn't
 // happen.  If a few messages are related, they should probably have their own
 // observer.
-class ChromeRenderProcessObserver : public content::RenderProcessObserver,
+class ChromeRenderThreadObserver : public content::RenderThreadObserver,
                                     public base::FieldTrialList::Observer {
  public:
-  ChromeRenderProcessObserver();
-  ~ChromeRenderProcessObserver() override;
+  ChromeRenderThreadObserver();
+  ~ChromeRenderThreadObserver() override;
 
   static bool is_incognito_process() { return is_incognito_process_; }
 
   // Returns a pointer to the content setting rules owned by
-  // |ChromeRenderProcessObserver|.
+  // |ChromeRenderThreadObserver|.
   const RendererContentSettingRules* content_setting_rules() const;
 
  private:
@@ -49,7 +49,7 @@
   // of any field trials that might have already been activated.
   void InitFieldTrialObserving(const base::CommandLine& command_line);
 
-  // content::RenderProcessObserver:
+  // content::RenderThreadObserver:
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   // base::FieldTrialList::Observer:
@@ -69,9 +69,9 @@
   std::unique_ptr<content::ResourceDispatcherDelegate> resource_delegate_;
   RendererContentSettingRules content_setting_rules_;
 
-  base::WeakPtrFactory<ChromeRenderProcessObserver> weak_factory_;
+  base::WeakPtrFactory<ChromeRenderThreadObserver> weak_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(ChromeRenderProcessObserver);
+  DISALLOW_COPY_AND_ASSIGN(ChromeRenderThreadObserver);
 };
 
-#endif  // CHROME_RENDERER_CHROME_RENDER_PROCESS_OBSERVER_H_
+#endif  // CHROME_RENDERER_CHROME_RENDER_THREAD_OBSERVER_H_
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index fdee41f..c31c540a 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -22,7 +22,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
 #include "chrome/renderer/web_apps.h"
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_render_thread_observer.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/render_frame.h"
@@ -41,9 +41,9 @@
 
 ChromeRenderViewObserver::ChromeRenderViewObserver(
     content::RenderView* render_view,
-    web_cache::WebCacheRenderProcessObserver* web_cache_render_process_observer)
+    web_cache::WebCacheRenderThreadObserver* web_cache_render_thread_observer)
     : content::RenderViewObserver(render_view),
-      web_cache_render_process_observer_(web_cache_render_process_observer),
+      web_cache_render_thread_observer_(web_cache_render_thread_observer),
       webview_visually_deemphasized_(false) {}
 
 ChromeRenderViewObserver::~ChromeRenderViewObserver() {
@@ -138,8 +138,8 @@
 void ChromeRenderViewObserver::Navigate(const GURL& url) {
   // Execute cache clear operations that were postponed until a navigation
   // event (including tab reload).
-  if (web_cache_render_process_observer_)
-    web_cache_render_process_observer_->ExecutePendingClearCache();
+  if (web_cache_render_thread_observer_)
+    web_cache_render_thread_observer_->ExecutePendingClearCache();
 }
 
 #if defined(ENABLE_EXTENSIONS)
diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h
index 370ac31..5d460b66 100644
--- a/chrome/renderer/chrome_render_view_observer.h
+++ b/chrome/renderer/chrome_render_view_observer.h
@@ -25,7 +25,7 @@
 }
 
 namespace web_cache {
-class WebCacheRenderProcessObserver;
+class WebCacheRenderThreadObserver;
 }
 
 // This class holds the Chrome specific parts of RenderView, and has the same
@@ -35,8 +35,8 @@
   // translate_helper can be NULL.
   ChromeRenderViewObserver(
       content::RenderView* render_view,
-      web_cache::WebCacheRenderProcessObserver*
-          web_cache_render_process_observer);
+      web_cache::WebCacheRenderThreadObserver*
+          web_cache_render_thread_observer);
   ~ChromeRenderViewObserver() override;
 
  private:
@@ -67,7 +67,7 @@
   std::vector<base::string16> webui_javascript_;
 
   // Owned by ChromeContentRendererClient and outlive us.
-  web_cache::WebCacheRenderProcessObserver* web_cache_render_process_observer_;
+  web_cache::WebCacheRenderThreadObserver* web_cache_render_thread_observer_;
 
   // true if webview is overlayed with grey color.
   bool webview_visually_deemphasized_;
diff --git a/chrome/renderer/content_settings_observer.h b/chrome/renderer/content_settings_observer.h
index c54a33d..97af499 100644
--- a/chrome/renderer/content_settings_observer.h
+++ b/chrome/renderer/content_settings_observer.h
@@ -136,7 +136,7 @@
 
   // A pointer to content setting rules stored by the renderer. Normally, the
   // |RendererContentSettingRules| object is owned by
-  // |ChromeRenderProcessObserver|. In the tests it is owned by the caller of
+  // |ChromeRenderThreadObserver|. In the tests it is owned by the caller of
   // |SetContentSettingRules|.
   const RendererContentSettingRules* content_setting_rules_;
 
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
index 4b54e1d..49d98dcc 100644
--- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
+++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
@@ -15,7 +15,7 @@
 #include "chrome/common/extensions/extension_metrics.h"
 #include "chrome/common/extensions/extension_process_policy.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/renderer/chrome_render_process_observer.h"
+#include "chrome/renderer/chrome_render_thread_observer.h"
 #include "chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h"
 #include "chrome/renderer/extensions/renderer_permissions_policy_delegate.h"
 #include "chrome/renderer/extensions/resource_request_policy.h"
@@ -126,7 +126,7 @@
 }
 
 bool ChromeExtensionsRendererClient::IsIncognitoProcess() const {
-  return ChromeRenderProcessObserver::is_incognito_process();
+  return ChromeRenderThreadObserver::is_incognito_process();
 }
 
 int ChromeExtensionsRendererClient::GetLowestIsolatedWorldId() const {
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h
index 2d08ed7b..0e26387 100644
--- a/chrome/renderer/net/net_error_helper.h
+++ b/chrome/renderer/net/net_error_helper.h
@@ -16,7 +16,7 @@
 #include "components/error_page/renderer/net_error_helper_core.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "content/public/renderer/render_frame_observer_tracker.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 class GURL;
 
@@ -42,7 +42,7 @@
 class NetErrorHelper
     : public content::RenderFrameObserver,
       public content::RenderFrameObserverTracker<NetErrorHelper>,
-      public content::RenderProcessObserver,
+      public content::RenderThreadObserver,
       public error_page::NetErrorHelperCore::Delegate,
       public NetErrorPageController::Delegate {
  public:
@@ -65,7 +65,7 @@
   // IPC::Listener implementation.
   bool OnMessageReceived(const IPC::Message& message) override;
 
-  // RenderProcessObserver implementation.
+  // RenderThreadObserver implementation.
   void NetworkStateChanged(bool online) override;
 
   // Initializes |error_html| with the HTML of an error page in response to
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h
index 975eba2c..2d28df1 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.h
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.h
@@ -11,13 +11,13 @@
 #include "chrome/renderer/plugins/power_saver_info.h"
 #include "components/plugins/renderer/loadable_plugin_placeholder.h"
 #include "content/public/renderer/context_menu_client.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 enum class ChromeViewHostMsg_GetPluginInfo_Status;
 
 class ChromePluginPlaceholder final
     : public plugins::LoadablePluginPlaceholder,
-      public content::RenderProcessObserver,
+      public content::RenderThreadObserver,
       public content::ContextMenuClient,
       public gin::Wrappable<ChromePluginPlaceholder> {
  public:
@@ -68,7 +68,7 @@
   v8::Local<v8::Value> GetV8Handle(v8::Isolate* isolate) override;
   void ShowContextMenu(const blink::WebMouseEvent&) override;
 
-  // content::RenderProcessObserver methods:
+  // content::RenderThreadObserver methods:
   void PluginListChanged() override;
 
   // content::ContextMenuClient methods:
diff --git a/chrome/renderer/prerender/prerender_dispatcher.h b/chrome/renderer/prerender/prerender_dispatcher.h
index 412aeca0..4f2f16e1 100644
--- a/chrome/renderer/prerender/prerender_dispatcher.h
+++ b/chrome/renderer/prerender/prerender_dispatcher.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "third_party/WebKit/public/platform/WebPrerender.h"
 #include "third_party/WebKit/public/platform/WebPrerenderingSupport.h"
 
@@ -23,7 +23,7 @@
 // prerenders were launched from this renderer, and ensures prerender navigation
 // is triggered on navigation to those. It implements the prerendering interface
 // supplied to WebKit.
-class PrerenderDispatcher : public content::RenderProcessObserver,
+class PrerenderDispatcher : public content::RenderThreadObserver,
                             public blink::WebPrerenderingSupport {
  public:
   PrerenderDispatcher();
@@ -42,7 +42,7 @@
   void OnPrerenderRemoveAliases(const std::vector<GURL>& aliases);
   void OnPrerenderStop(int prerender_id);
 
-  // From RenderProcessObserver:
+  // From RenderThreadObserver:
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   // From WebPrerenderingSupport:
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
index 73b7f7b..d9c4006 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
@@ -53,7 +53,7 @@
 }
 
 PhishingClassifierFilter::PhishingClassifierFilter()
-    : RenderProcessObserver() {}
+    : RenderThreadObserver() {}
 
 PhishingClassifierFilter::~PhishingClassifierFilter() {}
 
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate.h b/chrome/renderer/safe_browsing/phishing_classifier_delegate.h
index 56da659..6de13a2b 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_delegate.h
+++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "content/public/renderer/render_frame_observer.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 
@@ -21,7 +21,7 @@
 class PhishingClassifier;
 class Scorer;
 
-class PhishingClassifierFilter : public content::RenderProcessObserver {
+class PhishingClassifierFilter : public content::RenderThreadObserver {
  public:
   static PhishingClassifierFilter* Create();
   ~PhishingClassifierFilter() override;
diff --git a/chrome/renderer/searchbox/search_bouncer.cc b/chrome/renderer/searchbox/search_bouncer.cc
index 35899c04..8b9e3003 100644
--- a/chrome/renderer/searchbox/search_bouncer.cc
+++ b/chrome/renderer/searchbox/search_bouncer.cc
@@ -7,7 +7,7 @@
 #include "base/lazy_instance.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/search_urls.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "ipc/ipc_message_macros.h"
 
 namespace {
diff --git a/chrome/renderer/searchbox/search_bouncer.h b/chrome/renderer/searchbox/search_bouncer.h
index e822f72..3a57f31 100644
--- a/chrome/renderer/searchbox/search_bouncer.h
+++ b/chrome/renderer/searchbox/search_bouncer.h
@@ -9,7 +9,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "url/gurl.h"
 
 namespace IPC {
@@ -18,7 +18,7 @@
 
 // SearchBouncer tracks a set of URLs which should be transferred back to the
 // browser process for potential reassignment to an Instant renderer process.
-class SearchBouncer : public content::RenderProcessObserver {
+class SearchBouncer : public content::RenderThreadObserver {
  public:
   SearchBouncer();
   ~SearchBouncer() override;
@@ -38,7 +38,7 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(SearchBouncerTest, SetSearchURLs);
 
-  // From RenderProcessObserver:
+  // From RenderThreadObserver:
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   // URLs to bounce back to the browser.
diff --git a/chrome/renderer/spellchecker/spellcheck.h b/chrome/renderer/spellchecker/spellcheck.h
index 7c75b503..2b4386e 100644
--- a/chrome/renderer/spellchecker/spellcheck.h
+++ b/chrome/renderer/spellchecker/spellcheck.h
@@ -17,7 +17,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/renderer/spellchecker/custom_dictionary_engine.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 struct SpellCheckBDictLanguage;
 class SpellcheckLanguage;
@@ -37,7 +37,7 @@
 // See http://crbug.com/73699.
 // Shared spellchecking logic/data for a RenderProcess. All RenderViews use
 // this object to perform spellchecking tasks.
-class SpellCheck : public content::RenderProcessObserver,
+class SpellCheck : public content::RenderThreadObserver,
                    public base::SupportsWeakPtr<SpellCheck> {
  public:
   // TODO(groby): I wonder if this can be private, non-mac only.
@@ -121,7 +121,7 @@
        const std::vector<std::vector<base::string16>>& suggestions_list,
        std::vector<base::string16>* optional_suggestions);
 
-  // RenderProcessObserver implementation:
+  // RenderThreadObserver implementation:
    bool OnControlMessageReceived(const IPC::Message& message) override;
 
   // Message handlers.
diff --git a/chrome/renderer/tts_dispatcher.h b/chrome/renderer/tts_dispatcher.h
index e4a48802..24617398 100644
--- a/chrome/renderer/tts_dispatcher.h
+++ b/chrome/renderer/tts_dispatcher.h
@@ -10,7 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "third_party/WebKit/public/platform/WebSpeechSynthesizer.h"
 #include "third_party/WebKit/public/platform/WebSpeechSynthesizerClient.h"
 
@@ -29,14 +29,14 @@
 // the utterance id (which is globally unique) matches.
 class TtsDispatcher
     : public blink::WebSpeechSynthesizer,
-      public content::RenderProcessObserver {
+      public content::RenderThreadObserver {
  public:
   explicit TtsDispatcher(blink::WebSpeechSynthesizerClient* client);
 
  private:
   ~TtsDispatcher() override;
 
-  // RenderProcessObserver override.
+  // RenderThreadObserver override.
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   // blink::WebSpeechSynthesizer implementation.
diff --git a/chrome/test/data/extensions/api_test/display_source/wifi_display_session.js b/chrome/test/data/extensions/api_test/display_source/wifi_display_session.js
index 80c96509..a596362 100644
--- a/chrome/test/data/extensions/api_test/display_source/wifi_display_session.js
+++ b/chrome/test/data/extensions/api_test/display_source/wifi_display_session.js
@@ -7,8 +7,9 @@
 var testStartSessionErrorReport = function() {
   function onSessionError(errorSinkId, errorMessage){
     chrome.test.assertEq(1, errorSinkId);
-    chrome.test.assertEq('timeout_error', errorMessage.type);
-    chrome.test.assertEq('Sink became unresponsive', errorMessage.description);
+    chrome.test.assertEq('media_pipeline_error', errorMessage.type);
+    chrome.test.assertEq('Failed to initialize media pipeline for the session',
+        errorMessage.description);
     errorReported = true;
   };
   chrome.displaySource.onSessionErrorOccured.addListener(onSessionError);
@@ -22,9 +23,23 @@
 
   chrome.tabs.getCurrent(function(tab) {
     var sink_id = 1;
+
+    // If the test case does not provide height, width and frame properties,
+    // the captured stream is 640x480 30 fps by default.
+    // But WiFi Display requires 60 fps for this resolution.
+    // Thus, min and max frame rates should be explicitly defined.
+
+    var video_constraints = {
+          mandatory: {
+              minFrameRate: 60,
+              maxFrameRate: 60
+          }
+       };
+
     var constraints = {
         audio: false,
         video: true,
+        videoConstraints: video_constraints,
     };
 
     function onStream(stream) {
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp
index 70f48e1..af3e0287 100644
--- a/chromecast/chromecast.gyp
+++ b/chromecast/chromecast.gyp
@@ -410,8 +410,8 @@
         'renderer/cast_content_renderer_client.h',
         'renderer/cast_media_load_deferrer.cc',
         'renderer/cast_media_load_deferrer.h',
-        'renderer/cast_render_process_observer.cc',
-        'renderer/cast_render_process_observer.h',
+        'renderer/cast_render_thread_observer.cc',
+        'renderer/cast_render_thread_observer.h',
         'renderer/key_systems_cast.cc',
         'renderer/key_systems_cast.h',
         'renderer/media/capabilities_message_filter.cc',
diff --git a/chromecast/renderer/BUILD.gn b/chromecast/renderer/BUILD.gn
index 92cf3ef..1d20da3 100644
--- a/chromecast/renderer/BUILD.gn
+++ b/chromecast/renderer/BUILD.gn
@@ -10,8 +10,8 @@
     "cast_content_renderer_client.h",
     "cast_media_load_deferrer.cc",
     "cast_media_load_deferrer.h",
-    "cast_render_process_observer.cc",
-    "cast_render_process_observer.h",
+    "cast_render_thread_observer.cc",
+    "cast_render_thread_observer.h",
     "key_systems_cast.cc",
     "key_systems_cast.h",
   ]
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc
index 60f3bad..d02ffc33 100644
--- a/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -14,7 +14,7 @@
 #include "chromecast/crash/cast_crash_keys.h"
 #include "chromecast/media/base/media_caps.h"
 #include "chromecast/renderer/cast_media_load_deferrer.h"
-#include "chromecast/renderer/cast_render_process_observer.h"
+#include "chromecast/renderer/cast_render_thread_observer.h"
 #include "chromecast/renderer/key_systems_cast.h"
 #include "chromecast/renderer/media/chromecast_media_renderer_factory.h"
 #include "components/network_hints/renderer/prescient_networking_dispatcher.h"
@@ -59,7 +59,7 @@
     }
   }
 
-  cast_observer_.reset(new CastRenderProcessObserver());
+  cast_observer_.reset(new CastRenderThreadObserver());
 
   prescient_networking_dispatcher_.reset(
       new network_hints::PrescientNetworkingDispatcher());
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h
index c888f1f0..cb04ad6a 100644
--- a/chromecast/renderer/cast_content_renderer_client.h
+++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -21,7 +21,7 @@
 
 namespace chromecast {
 namespace shell {
-class CastRenderProcessObserver;
+class CastRenderThreadObserver;
 
 class CastContentRendererClient : public content::ContentRendererClient {
  public:
@@ -53,7 +53,7 @@
  private:
   std::unique_ptr<network_hints::PrescientNetworkingDispatcher>
       prescient_networking_dispatcher_;
-  std::unique_ptr<CastRenderProcessObserver> cast_observer_;
+  std::unique_ptr<CastRenderThreadObserver> cast_observer_;
   const bool allow_hidden_media_playback_;
 
   DISALLOW_COPY_AND_ASSIGN(CastContentRendererClient);
diff --git a/chromecast/renderer/cast_render_process_observer.cc b/chromecast/renderer/cast_render_thread_observer.cc
similarity index 80%
rename from chromecast/renderer/cast_render_process_observer.cc
rename to chromecast/renderer/cast_render_thread_observer.cc
index 0eb6abb..5c3d2bb 100644
--- a/chromecast/renderer/cast_render_process_observer.cc
+++ b/chromecast/renderer/cast_render_thread_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromecast/renderer/cast_render_process_observer.h"
+#include "chromecast/renderer/cast_render_thread_observer.h"
 
 #include "build/build_config.h"
 #include "chromecast/renderer/media/capabilities_message_filter.h"
@@ -12,18 +12,18 @@
 namespace chromecast {
 namespace shell {
 
-CastRenderProcessObserver::CastRenderProcessObserver() {
+CastRenderThreadObserver::CastRenderThreadObserver() {
   content::RenderThread* thread = content::RenderThread::Get();
   thread->AddObserver(this);
   CreateCustomFilters();
 }
 
-CastRenderProcessObserver::~CastRenderProcessObserver() {
-  // CastRenderProcessObserver outlives content::RenderThread.
+CastRenderThreadObserver::~CastRenderThreadObserver() {
+  // CastRenderThreadObserver outlives content::RenderThread.
   // No need to explicitly call RemoveObserver in teardown.
 }
 
-void CastRenderProcessObserver::CreateCustomFilters() {
+void CastRenderThreadObserver::CreateCustomFilters() {
   content::RenderThread* thread = content::RenderThread::Get();
 #if !defined(OS_ANDROID)
   cma_message_filter_proxy_ =
@@ -34,7 +34,7 @@
   thread->AddFilter(capabilities_message_filter_.get());
 }
 
-void CastRenderProcessObserver::OnRenderProcessShutdown() {
+void CastRenderThreadObserver::OnRenderProcessShutdown() {
   content::RenderThread* thread = content::RenderThread::Get();
 #if !defined(OS_ANDROID)
   if (cma_message_filter_proxy_.get()) {
diff --git a/chromecast/renderer/cast_render_process_observer.h b/chromecast/renderer/cast_render_thread_observer.h
similarity index 60%
rename from chromecast/renderer/cast_render_process_observer.h
rename to chromecast/renderer/cast_render_thread_observer.h
index 713e5427..297c3f2 100644
--- a/chromecast/renderer/cast_render_process_observer.h
+++ b/chromecast/renderer/cast_render_thread_observer.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMECAST_RENDERER_CAST_RENDER_PROCESS_OBSERVER_H_
-#define CHROMECAST_RENDERER_CAST_RENDER_PROCESS_OBSERVER_H_
+#ifndef CHROMECAST_RENDERER_CAST_RENDER_THREAD_OBSERVER_H_
+#define CHROMECAST_RENDERER_CAST_RENDER_THREAD_OBSERVER_H_
 
 #include <vector>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 namespace chromecast {
 class CapabilitiesMessageFilter;
@@ -20,13 +20,13 @@
 
 namespace shell {
 
-class CastRenderProcessObserver : public content::RenderProcessObserver {
+class CastRenderThreadObserver : public content::RenderThreadObserver {
  public:
-  CastRenderProcessObserver();
-  ~CastRenderProcessObserver() override;
+  CastRenderThreadObserver();
+  ~CastRenderThreadObserver() override;
 
  private:
-  // content::RenderProcessObserver implementation:
+  // content::RenderThreadObserver implementation:
   void OnRenderProcessShutdown() override;
 
   void CreateCustomFilters();
@@ -36,10 +36,10 @@
 #endif  // !defined(OS_ANDROID)
   scoped_refptr<CapabilitiesMessageFilter> capabilities_message_filter_;
 
-  DISALLOW_COPY_AND_ASSIGN(CastRenderProcessObserver);
+  DISALLOW_COPY_AND_ASSIGN(CastRenderThreadObserver);
 };
 
 }  // namespace shell
 }  // namespace chromecast
 
-#endif  // CHROMECAST_RENDERER_CAST_RENDER_PROCESS_OBSERVER_H_
+#endif  // CHROMECAST_RENDERER_CAST_RENDER_THREAD_OBSERVER_H_
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 313d8b0..244ff1c 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -467,6 +467,8 @@
       'password_manager/core/browser/affiliation_utils_unittest.cc',
       'password_manager/core/browser/browser_save_password_progress_logger_unittest.cc',
       'password_manager/core/browser/export/csv_writer_unittest.cc',
+      'password_manager/core/browser/export/password_exporter_unittest.cc',
+      'password_manager/core/browser/import/password_importer_unittest.cc',
       'password_manager/core/browser/facet_manager_unittest.cc',
       'password_manager/core/browser/import/csv_reader_unittest.cc',
       'password_manager/core/browser/log_manager_unittest.cc',
@@ -637,6 +639,7 @@
       'safe_browsing_db/safe_browsing_api_handler_unittest.cc',
     ],
     'safe_browsing_db_unittest_sources': [
+      'safe_browsing_db/database_manager_unittest.cc',
       'safe_browsing_db/prefix_set_unittest.cc',
       'safe_browsing_db/testing_util.h',
       'safe_browsing_db/util_unittest.cc',
@@ -1269,6 +1272,7 @@
             'components.gyp:sessions_content',
             'components.gyp:storage_monitor',
             'components.gyp:storage_monitor_test_support',
+            'components.gyp:test_database_manager',
             'components.gyp:ui_zoom',
             'components.gyp:url_matcher',
             'components.gyp:visitedlink_browser',
diff --git a/components/drive.gypi b/components/drive.gypi
index c97397c..003cbc04 100644
--- a/components/drive.gypi
+++ b/components/drive.gypi
@@ -71,79 +71,6 @@
     },
 
     {
-      # GN version: //components/drive:drive_chromeos
-      'target_name': 'drive_chromeos',
-      'type': 'static_library',
-      'include_dirs': [
-        '..',
-      ],
-      'dependencies': [
-        'drive',
-	'drive_proto',
-        '../base/base.gyp:base',
-        '../google_apis/google_apis.gyp:google_apis',
-        '../net/net.gyp:net',
-      ],
-      # TODO(yawano): move these files under components/drive/chromeos.
-      'sources': [
-        'drive/change_list_loader.cc',
-        'drive/change_list_loader.h',
-        'drive/change_list_loader_observer.h',
-        'drive/change_list_processor.cc',
-        'drive/change_list_processor.h',
-        'drive/directory_loader.cc',
-        'drive/directory_loader.h',
-        'drive/file_cache.cc',
-        'drive/file_cache.h',
-        'drive/file_system.cc',
-        'drive/file_system.h',
-        'drive/file_system_interface.cc',
-        'drive/file_system_interface.h',
-        'drive/file_system_observer.h',
-        'drive/file_system/copy_operation.cc',
-        'drive/file_system/copy_operation.h',
-        'drive/file_system/create_directory_operation.cc',
-        'drive/file_system/create_directory_operation.h',
-        'drive/file_system/create_file_operation.cc',
-        'drive/file_system/create_file_operation.h',
-        'drive/file_system/download_operation.cc',
-        'drive/file_system/download_operation.h',
-        'drive/file_system/get_file_for_saving_operation.cc',
-        'drive/file_system/get_file_for_saving_operation.h',
-        'drive/file_system/move_operation.cc',
-        'drive/file_system/move_operation.h',
-        'drive/file_system/open_file_operation.cc',
-        'drive/file_system/open_file_operation.h',
-        'drive/file_system/operation_delegate.cc',
-        'drive/file_system/operation_delegate.h',
-        'drive/file_system/remove_operation.cc',
-        'drive/file_system/remove_operation.h',
-        'drive/file_system/search_operation.cc',
-        'drive/file_system/search_operation.h',
-        'drive/file_system/set_property_operation.cc',
-        'drive/file_system/set_property_operation.h',
-        'drive/file_system/touch_operation.cc',
-        'drive/file_system/touch_operation.h',
-        'drive/file_system/truncate_operation.cc',
-        'drive/file_system/truncate_operation.h',
-        'drive/remove_stale_cache_files.cc',
-        'drive/remove_stale_cache_files.h',
-        'drive/resource_metadata.cc',
-        'drive/resource_metadata.h',
-        'drive/search_metadata.cc',
-        'drive/search_metadata.h',
-        'drive/sync_client.cc',
-        'drive/sync_client.h',
-        'drive/sync/entry_revert_performer.cc',
-        'drive/sync/entry_revert_performer.h',
-        'drive/sync/entry_update_performer.cc',
-        'drive/sync/entry_update_performer.h',
-        'drive/sync/remove_performer.cc',
-        'drive/sync/remove_performer.h',
-      ],
-    },
-
-    {
       # GN version: //components/drive:proto
       # Protobuf compiler / generator for the Drive protocol buffer.
       'target_name': 'drive_proto',
@@ -181,33 +108,112 @@
       ],
     },
 
-    {
-      # GN version: //components/drive:test_support_chromeos
-      'target_name': 'drive_test_support_chromeos',
-      'type': 'static_library',
-      'include_dirs': [
-        '..',
-      ],
-      'dependencies': [
-        'drive',
-        'drive_chromeos',
-        'drive_proto',
-        '../base/base.gyp:base',
-        '../content/content_shell_and_tests.gyp:test_support_content',
-      ],
-      'sources': [
-        "drive/drive_test_util.cc",
-        "drive/drive_test_util.h",
-        "drive/dummy_file_system.cc",
-        "drive/dummy_file_system.h",
-        "drive/fake_file_system.cc",
-        "drive/fake_file_system.h",
-        "drive/fake_free_disk_space_getter.cc",
-        "drive/fake_free_disk_space_getter.h",
-      ]
-    }
-
     # TODO(lukasza): drive_unittests target.
     # Currently tests are built as part of chrome/chrome_tests_unit.gypi.
   ],
+
+  'conditions': [
+    ['chromeos==1', {
+      'targets': [
+        {
+          # GN version: //components/drive:drive_chromeos
+          'target_name': 'drive_chromeos',
+          'type': 'static_library',
+          'include_dirs': [
+            '..',
+          ],
+          'dependencies': [
+            'drive',
+	    'drive_proto',
+            '../base/base.gyp:base',
+            '../google_apis/google_apis.gyp:google_apis',
+            '../net/net.gyp:net',
+          ],
+          # TODO(yawano): move these files under components/drive/chromeos.
+          'sources': [
+            'drive/change_list_loader.cc',
+            'drive/change_list_loader.h',
+            'drive/change_list_loader_observer.h',
+            'drive/change_list_processor.cc',
+            'drive/change_list_processor.h',
+            'drive/directory_loader.cc',
+            'drive/directory_loader.h',
+            'drive/file_cache.cc',
+            'drive/file_cache.h',
+            'drive/file_system.cc',
+            'drive/file_system.h',
+            'drive/file_system_interface.cc',
+            'drive/file_system_interface.h',
+            'drive/file_system_observer.h',
+            'drive/file_system/copy_operation.cc',
+            'drive/file_system/copy_operation.h',
+            'drive/file_system/create_directory_operation.cc',
+            'drive/file_system/create_directory_operation.h',
+            'drive/file_system/create_file_operation.cc',
+            'drive/file_system/create_file_operation.h',
+            'drive/file_system/download_operation.cc',
+            'drive/file_system/download_operation.h',
+            'drive/file_system/get_file_for_saving_operation.cc',
+            'drive/file_system/get_file_for_saving_operation.h',
+            'drive/file_system/move_operation.cc',
+            'drive/file_system/move_operation.h',
+            'drive/file_system/open_file_operation.cc',
+            'drive/file_system/open_file_operation.h',
+            'drive/file_system/operation_delegate.cc',
+            'drive/file_system/operation_delegate.h',
+            'drive/file_system/remove_operation.cc',
+            'drive/file_system/remove_operation.h',
+            'drive/file_system/search_operation.cc',
+            'drive/file_system/search_operation.h',
+            'drive/file_system/set_property_operation.cc',
+            'drive/file_system/set_property_operation.h',
+            'drive/file_system/touch_operation.cc',
+            'drive/file_system/touch_operation.h',
+            'drive/file_system/truncate_operation.cc',
+            'drive/file_system/truncate_operation.h',
+            'drive/remove_stale_cache_files.cc',
+            'drive/remove_stale_cache_files.h',
+            'drive/resource_metadata.cc',
+            'drive/resource_metadata.h',
+            'drive/search_metadata.cc',
+            'drive/search_metadata.h',
+            'drive/sync_client.cc',
+            'drive/sync_client.h',
+            'drive/sync/entry_revert_performer.cc',
+            'drive/sync/entry_revert_performer.h',
+            'drive/sync/entry_update_performer.cc',
+            'drive/sync/entry_update_performer.h',
+            'drive/sync/remove_performer.cc',
+            'drive/sync/remove_performer.h',
+          ],
+        },
+
+        {
+          # GN version: //components/drive:test_support_chromeos
+          'target_name': 'drive_test_support_chromeos',
+          'type': 'static_library',
+          'include_dirs': [
+            '..',
+          ],
+          'dependencies': [
+            'drive',
+            'drive_chromeos',
+            'drive_proto',
+            '../base/base.gyp:base',
+            '../content/content_shell_and_tests.gyp:test_support_content',
+          ],
+          'sources': [
+            "drive/drive_test_util.cc",
+            "drive/drive_test_util.h",
+            "drive/dummy_file_system.cc",
+            "drive/dummy_file_system.h",
+            "drive/fake_file_system.cc",
+            "drive/fake_file_system.h",
+            "drive/fake_free_disk_space_getter.cc",
+            "drive/fake_free_disk_space_getter.h",
+          ]
+        }
+      ]
+    }]
+  ]
 }
diff --git a/components/guest_view/renderer/guest_view_container_dispatcher.h b/components/guest_view/renderer/guest_view_container_dispatcher.h
index 6bb98cf..a004ec1 100644
--- a/components/guest_view/renderer/guest_view_container_dispatcher.h
+++ b/components/guest_view/renderer/guest_view_container_dispatcher.h
@@ -8,13 +8,13 @@
 #include "base/macros.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "ipc/ipc_message.h"
 
 namespace guest_view {
 
 // Dispatcher used to route messages to GuestViewContainer.
-class GuestViewContainerDispatcher : public content::RenderProcessObserver {
+class GuestViewContainerDispatcher : public content::RenderThreadObserver {
  public:
   GuestViewContainerDispatcher();
   ~GuestViewContainerDispatcher() override;
@@ -24,7 +24,7 @@
   virtual bool HandlesMessage(const IPC::Message& message);
 
  private:
-  // content::RenderProcessObserver implementation.
+  // content::RenderThreadObserver implementation.
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   DISALLOW_COPY_AND_ASSIGN(GuestViewContainerDispatcher);
diff --git a/components/password_manager.gypi b/components/password_manager.gypi
index a7e411c..a1110b5 100644
--- a/components/password_manager.gypi
+++ b/components/password_manager.gypi
@@ -57,11 +57,15 @@
         'password_manager/core/browser/credentials_filter.h',
         'password_manager/core/browser/export/csv_writer.cc',
         'password_manager/core/browser/export/csv_writer.h',
+        'password_manager/core/browser/export/password_exporter.cc',
+        'password_manager/core/browser/export/password_exporter.h',
         'password_manager/core/browser/facet_manager.cc',
         'password_manager/core/browser/facet_manager.h',
         'password_manager/core/browser/facet_manager_host.h',
         'password_manager/core/browser/import/csv_reader.cc',
         'password_manager/core/browser/import/csv_reader.h',
+        'password_manager/core/browser/import/password_importer.cc',
+        'password_manager/core/browser/import/password_importer.h',
         'password_manager/core/browser/keychain_migration_status_mac.h',
         'password_manager/core/browser/log_manager.cc',
         'password_manager/core/browser/log_manager.h',
@@ -120,6 +124,7 @@
         'password_manager/core/browser/statistics_table.cc',
         'password_manager/core/browser/statistics_table.h',
         'password_manager/core/browser/test_affiliation_fetcher_factory.h',
+        'password_manager/core/browser/types.h',
         'password_manager/core/browser/webdata/logins_table.cc',
         'password_manager/core/browser/webdata/logins_table.h',
         'password_manager/core/browser/webdata/logins_table_win.cc',
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 8819e403..7752be8 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -37,11 +37,15 @@
     "credentials_filter.h",
     "export/csv_writer.cc",
     "export/csv_writer.h",
+    "export/password_exporter.cc",
+    "export/password_exporter.h",
     "facet_manager.cc",
     "facet_manager.h",
     "facet_manager_host.h",
     "import/csv_reader.cc",
     "import/csv_reader.h",
+    "import/password_importer.cc",
+    "import/password_importer.h",
     "keychain_migration_status_mac.h",
     "log_manager.cc",
     "log_manager.h",
diff --git a/components/password_manager/core/browser/export/password_exporter.cc b/components/password_manager/core/browser/export/password_exporter.cc
new file mode 100644
index 0000000..45b1112
--- /dev/null
+++ b/components/password_manager/core/browser/export/password_exporter.cc
@@ -0,0 +1,121 @@
+// Copyright 2016 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 "components/password_manager/core/browser/export/password_exporter.h"
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/location.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner.h"
+#include "base/values.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/export/csv_writer.h"
+
+namespace password_manager {
+
+namespace {
+
+using autofill::PasswordForm;
+
+// PasswordWriterBase ---------------------------------------------------------
+
+// Interface for writing a list of passwords into various formats.
+class PasswordWriterBase {
+ public:
+  virtual ~PasswordWriterBase() = 0;
+
+  // Serializes the list of |passwords|.
+  virtual std::string SerializePasswords(
+      std::vector<scoped_ptr<PasswordForm>>& passwords) = 0;
+};
+
+PasswordWriterBase::~PasswordWriterBase() {}
+
+// PasswordCSVWriter ----------------------------------------------------------
+
+class PasswordCSVWriter : public PasswordWriterBase {
+ public:
+  static const base::FilePath::CharType kFileExtension[];
+
+  PasswordCSVWriter() {}
+
+  // PasswordWriterBase:
+  std::string SerializePasswords(
+      std::vector<scoped_ptr<PasswordForm>>& passwords) override {
+    std::vector<std::string> header;
+    header.push_back(kTitleFieldName);
+    header.push_back(kUrlFieldName);
+    header.push_back(kUsernameFieldName);
+    header.push_back(kPasswordFieldName);
+
+    std::vector<std::map<std::string, std::string>> records;
+    records.reserve(passwords.size());
+    for (const auto& it : passwords) {
+      records.push_back(PasswordFormToRecord(it.get()));
+    }
+    std::string result;
+    WriteCSV(header, records, &result);
+    return result;
+  }
+
+ private:
+  static const char kUrlFieldName[];
+  static const char kUsernameFieldName[];
+  static const char kPasswordFieldName[];
+  static const char kTitleFieldName[];
+
+  std::map<std::string, std::string> PasswordFormToRecord(
+      const PasswordForm* form) {
+    std::map<std::string, std::string> record;
+    record[kUrlFieldName] = (form->origin).spec();
+    record[kUsernameFieldName] = base::UTF16ToUTF8(form->username_value);
+    record[kPasswordFieldName] = base::UTF16ToUTF8(form->password_value);
+    record[kTitleFieldName] = form->origin.host();
+    return record;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordCSVWriter);
+};
+
+const base::FilePath::CharType PasswordCSVWriter::kFileExtension[] =
+    FILE_PATH_LITERAL("csv");
+const char PasswordCSVWriter::kUrlFieldName[] = "url";
+const char PasswordCSVWriter::kUsernameFieldName[] = "username";
+const char PasswordCSVWriter::kPasswordFieldName[] = "password";
+const char PasswordCSVWriter::kTitleFieldName[] = "name";
+
+// Helper ---------------------------------------------------------------------
+
+void WriteToFile(const base::FilePath& path, const std::string& data) {
+  base::WriteFile(path, data.c_str(), data.size());
+}
+
+}  // namespace
+
+// static
+void PasswordExporter::Export(
+    const base::FilePath& path,
+    std::vector<scoped_ptr<PasswordForm>> passwords,
+    scoped_refptr<base::TaskRunner> blocking_task_runner) {
+  // Currently, CSV is the only supported format.
+  PasswordCSVWriter password_writer;
+
+  std::string serialized_passwords =
+      password_writer.SerializePasswords(passwords);
+
+  blocking_task_runner->PostTask(
+      FROM_HERE, base::Bind(&WriteToFile, path, serialized_passwords));
+}
+
+// static
+std::vector<std::vector<base::FilePath::StringType>>
+PasswordExporter::GetSupportedFileExtensions() {
+  std::vector<std::vector<base::FilePath::StringType>> extensions;
+  extensions.resize(1);
+  extensions[0].push_back(PasswordCSVWriter::kFileExtension);
+  return extensions;
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/export/password_exporter.h b/components/password_manager/core/browser/export/password_exporter.h
new file mode 100644
index 0000000..5dcf3c0
--- /dev/null
+++ b/components/password_manager/core/browser/export/password_exporter.h
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_EXPORT_PASSWORD_EXPORTER_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_EXPORT_PASSWORD_EXPORTER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace autofill {
+struct PasswordForm;
+}
+
+namespace base {
+class FilePath;
+class TaskRunner;
+}
+
+namespace password_manager {
+
+class PasswordExporter {
+ public:
+  // Exports |passwords| into a file at |path|, overwriting any existing file,
+  // and fires |completion| on the calling thread when ready. Blocking IO tasks
+  // will be posted to |blocking_task_runner|. The format of the export will be
+  // selected based on the file extension in |path|.
+  static void Export(const base::FilePath& path,
+                     std::vector<scoped_ptr<autofill::PasswordForm>> passwords,
+                     scoped_refptr<base::TaskRunner> blocking_task_runner);
+
+  // Returns the file extensions corresponding to supported formats.
+  // Inner vector indicates equivalent extensions. For example:
+  //   { { "html", "htm" }, { "csv" } }
+  static std::vector<std::vector<base::FilePath::StringType>>
+  GetSupportedFileExtensions();
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PasswordExporter);
+};
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_EXPORT_PASSWORD_EXPORTER_H_
diff --git a/components/password_manager/core/browser/export/password_exporter_unittest.cc b/components/password_manager/core/browser/export/password_exporter_unittest.cc
new file mode 100644
index 0000000..c43a68e6
--- /dev/null
+++ b/components/password_manager/core/browser/export/password_exporter_unittest.cc
@@ -0,0 +1,86 @@
+// Copyright 2016 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 "components/password_manager/core/browser/export/password_exporter.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/password_form.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+
+class PasswordExporterTest : public testing::Test {
+ public:
+  PasswordExporterTest() {}
+
+ protected:
+  std::vector<scoped_ptr<autofill::PasswordForm>> ConstructTestPasswordForms() {
+    scoped_ptr<autofill::PasswordForm> password_form_(
+        new autofill::PasswordForm());
+    password_form_->origin = GURL("http://accounts.google.com/a/LoginAuth");
+    password_form_->username_value = base::ASCIIToUTF16("test@gmail.com");
+    password_form_->password_value = base::ASCIIToUTF16("test1");
+
+    std::vector<scoped_ptr<autofill::PasswordForm>> password_forms;
+    password_forms.push_back(std::move(password_form_));
+    return password_forms;
+  }
+
+  void StartExportAndWaitUntilCompleteThenReadOutput(
+      const base::FilePath::StringType& provided_extension,
+      const base::FilePath::StringType& expected_extension,
+      std::vector<scoped_ptr<autofill::PasswordForm>> passwords,
+      std::string* output) {
+    base::FilePath temporary_dir;
+    ASSERT_TRUE(base::CreateNewTempDirectory(base::FilePath::StringType(),
+                                             &temporary_dir));
+    base::FilePath output_file =
+        temporary_dir.AppendASCII("passwords").AddExtension(provided_extension);
+
+    PasswordExporter::Export(output_file, std::move(passwords),
+                             message_loop_.task_runner());
+
+    base::RunLoop run_loop;
+    run_loop.RunUntilIdle();
+
+    if (provided_extension != expected_extension) {
+      output_file = output_file.ReplaceExtension(expected_extension);
+    }
+
+    EXPECT_TRUE(base::ReadFileToString(output_file, output));
+    base::DeleteFile(temporary_dir, true);
+  }
+
+ private:
+  base::MessageLoop message_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordExporterTest);
+};
+
+TEST_F(PasswordExporterTest, CSVExport) {
+#if defined(OS_WIN)
+  const char kLineEnding[] = "\r\n";
+#else
+  const char kLineEnding[] = "\n";
+#endif
+  std::string kExpectedCSVOutput = base::StringPrintf(
+      "name,url,username,password%s"
+      "accounts.google.com,http://accounts.google.com/a/"
+      "LoginAuth,test@gmail.com,test1%s",
+      kLineEnding, kLineEnding);
+
+  std::string output;
+  ASSERT_NO_FATAL_FAILURE(StartExportAndWaitUntilCompleteThenReadOutput(
+      FILE_PATH_LITERAL(".csv"), FILE_PATH_LITERAL(".csv"),
+      ConstructTestPasswordForms(), &output));
+  EXPECT_EQ(kExpectedCSVOutput, output);
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/import/csv_reader.h b/components/password_manager/core/browser/import/csv_reader.h
index b1dcde5..ad1c487e 100644
--- a/components/password_manager/core/browser/import/csv_reader.h
+++ b/components/password_manager/core/browser/import/csv_reader.h
@@ -22,7 +22,7 @@
 //     be converted to LF characters inside quotes.
 //   * Inconsistent number of fields within records is handled gracefully. Extra
 //     fields are ignored. Missing fields will have no corresponding key-value
-//     pair in the record's ColumnNameToValueMap.
+//     pair in the record.
 //   * Repeated columns of the same name are not supported (the last value will
 //     be preserved).
 //
diff --git a/components/password_manager/core/browser/import/password_importer.cc b/components/password_manager/core/browser/import/password_importer.cc
new file mode 100644
index 0000000..e210e379
--- /dev/null
+++ b/components/password_manager/core/browser/import/password_importer.cc
@@ -0,0 +1,188 @@
+// Copyright 2016 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 "components/password_manager/core/browser/import/password_importer.h"
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner.h"
+#include "base/task_runner_util.h"
+#include "base/values.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/import/csv_reader.h"
+
+namespace password_manager {
+
+namespace {
+
+using autofill::PasswordForm;
+
+// PasswordReaderBase ---------------------------------------------------------
+
+// Interface for writing a list of passwords into various formats.
+class PasswordReaderBase {
+ public:
+  virtual ~PasswordReaderBase() = 0;
+
+  // Deserializes a list of passwords from |input| into |passwords|.
+  virtual PasswordImporter::Result DeserializePasswords(
+      const std::string& input,
+      std::vector<PasswordForm>* passwords) = 0;
+};
+
+PasswordReaderBase::~PasswordReaderBase() {}
+
+// PasswordCSVReader ----------------------------------------------------------
+
+class PasswordCSVReader : public PasswordReaderBase {
+ public:
+  static const base::FilePath::CharType kFileExtension[];
+
+  PasswordCSVReader() {}
+
+  // PasswordWriterBase:
+  PasswordImporter::Result DeserializePasswords(
+      const std::string& input,
+      std::vector<PasswordForm>* passwords) override {
+    std::vector<std::string> header;
+    std::vector<std::map<std::string, std::string>> records;
+    if (!ReadCSV(input, &header, &records))
+      return PasswordImporter::SYNTAX_ERROR;
+
+    if (!GetActualFieldName(header, GetURLFieldNames(), url_field_name_) ||
+        !GetActualFieldName(header, GetUsernameFieldNames(),
+                            username_field_name_) ||
+        !GetActualFieldName(header, GetPasswordFieldNames(),
+                            password_field_name_))
+      return PasswordImporter::SEMANTIC_ERROR;
+
+    passwords->clear();
+    passwords->reserve(records.size());
+
+    for (const auto& record : records) {
+      PasswordForm form;
+      if (RecordToPasswordForm(record, &form))
+        passwords->push_back(form);
+    }
+    return PasswordImporter::SUCCESS;
+  }
+
+ private:
+  std::string url_field_name_;
+  std::string username_field_name_;
+  std::string password_field_name_;
+
+  const std::vector<std::string> GetURLFieldNames() {
+    std::vector<std::string> url_names;
+    url_names.push_back("url");
+    url_names.push_back("website");
+    url_names.push_back("origin");
+    url_names.push_back("hostname");
+    return url_names;
+  }
+
+  const std::vector<std::string> GetUsernameFieldNames() {
+    std::vector<std::string> username_names;
+    username_names.push_back("username");
+    username_names.push_back("user");
+    username_names.push_back("login");
+    username_names.push_back("account");
+    return username_names;
+  }
+
+  const std::vector<std::string> GetPasswordFieldNames() {
+    std::vector<std::string> password_names;
+    password_names.push_back("password");
+    return password_names;
+  }
+
+  bool RecordToPasswordForm(const std::map<std::string, std::string>& record,
+                            PasswordForm* form) {
+    if (!record.count(url_field_name_) || !record.count(username_field_name_) ||
+        !record.count(password_field_name_)) {
+      return false;
+    }
+    form->origin = GURL(record.at(url_field_name_));
+    form->signon_realm = form->origin.GetOrigin().spec();
+    form->username_value = base::UTF8ToUTF16(record.at(username_field_name_));
+    form->password_value = base::UTF8ToUTF16(record.at(password_field_name_));
+    return true;
+  }
+
+  bool GetActualFieldName(const std::vector<std::string>& header,
+                          const std::vector<std::string>& options,
+                          std::string& field_name) {
+    auto it = std::find_if(header.begin(), header.end(),
+                           [&options](const std::string& str) {
+                             return std::count(options.begin(), options.end(),
+                                               base::ToLowerASCII(str));
+                           });
+
+    if (it == header.end()) {
+      return false;
+    }
+
+    field_name = *it;
+    return true;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordCSVReader);
+};
+
+const base::FilePath::CharType PasswordCSVReader::kFileExtension[] =
+    FILE_PATH_LITERAL("csv");
+
+// Helpers --------------------------------------------------------------------
+
+// Reads and returns the contents of the file at |path| as a string, or returns
+// a scoped point containing a NULL if there was an error.
+scoped_ptr<std::string> ReadFileToString(const base::FilePath& path) {
+  scoped_ptr<std::string> contents(new std::string);
+  if (!base::ReadFileToString(path, contents.get()))
+    return scoped_ptr<std::string>();
+  return contents;
+}
+
+// Parses passwords from |input| using |password_reader| and synchronously calls
+// |completion| with the results.
+static void ParsePasswords(
+    scoped_ptr<PasswordReaderBase> password_reader,
+    const PasswordImporter::CompletionCallback& completion,
+    scoped_ptr<std::string> input) {
+  std::vector<PasswordForm> passwords;
+  PasswordImporter::Result result = PasswordImporter::IO_ERROR;
+  if (input)
+    result = password_reader->DeserializePasswords(*input, &passwords);
+  completion.Run(result, passwords);
+}
+
+}  // namespace
+
+// static
+void PasswordImporter::Import(
+    const base::FilePath& path,
+    scoped_refptr<base::TaskRunner> blocking_task_runner,
+    const CompletionCallback& completion) {
+  // Currently, CSV is the only supported format.
+  scoped_ptr<PasswordReaderBase> password_reader(new PasswordCSVReader);
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner.get(), FROM_HERE,
+      base::Bind(&ReadFileToString, path),
+      base::Bind(&ParsePasswords, base::Passed(&password_reader), completion));
+}
+
+// static
+std::vector<std::vector<base::FilePath::StringType>>
+PasswordImporter::GetSupportedFileExtensions() {
+  std::vector<std::vector<base::FilePath::StringType>> extensions;
+  extensions.resize(1);
+  extensions[0].push_back(PasswordCSVReader::kFileExtension);
+  return extensions;
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/import/password_importer.h b/components/password_manager/core/browser/import/password_importer.h
new file mode 100644
index 0000000..d2e7f24
--- /dev/null
+++ b/components/password_manager/core/browser/import/password_importer.h
@@ -0,0 +1,59 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_PASSWORD_IMPORTER_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_PASSWORD_IMPORTER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+
+namespace autofill {
+struct PasswordForm;
+}
+
+namespace base {
+class FilePath;
+class TaskRunner;
+}
+
+namespace password_manager {
+
+class PasswordImporter {
+ public:
+  enum Result {
+    SUCCESS,
+    IO_ERROR,
+    SYNTAX_ERROR,
+    SEMANTIC_ERROR,
+    NUM_IMPORT_RESULTS
+  };
+
+  typedef base::Callback<void(Result,
+                              const std::vector<autofill::PasswordForm>&)>
+      CompletionCallback;
+
+  // Imports passwords from the file at |path|, and fires |completion| callback
+  // on the calling thread with the passwords when ready. Blocking IO operations
+  // will be posted to |blocking_task_runner|. The file format should correspond
+  // to the extension of the file.
+  static void Import(const base::FilePath& path,
+                     scoped_refptr<base::TaskRunner> blocking_task_runner,
+                     const CompletionCallback& completion);
+
+  // Returns the file extensions corresponding to supported formats.
+  static std::vector<std::vector<base::FilePath::StringType>>
+  GetSupportedFileExtensions();
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PasswordImporter);
+};
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_PASSWORD_IMPORTER_H_
diff --git a/components/password_manager/core/browser/import/password_importer_unittest.cc b/components/password_manager/core/browser/import/password_importer_unittest.cc
new file mode 100644
index 0000000..058dd43
--- /dev/null
+++ b/components/password_manager/core/browser/import/password_importer_unittest.cc
@@ -0,0 +1,103 @@
+// Copyright 2016 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 "components/password_manager/core/browser/import/password_importer.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "components/autofill/core/common/password_form.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+
+namespace {
+const char kTestOriginURL[] = "http://accounts.google.com/a/LoginAuth";
+const char kTestSignonRealm[] = "http://accounts.google.com/";
+const char kTestUsername[] = "test@gmail.com";
+const char kTestPassword[] = "test1";
+const char kTestFileName[] = "test_only.csv";
+}  // namespace
+
+class PasswordImporterTest : public testing::Test {
+ public:
+  PasswordImporterTest()
+      : callback_called_(false), result_(PasswordImporter::SUCCESS) {
+    CHECK(temp_directory_.CreateUniqueTempDir());
+  }
+
+ protected:
+  void StartImportAndWaitForCompletion(const base::FilePath& input_file) {
+    PasswordImporter::Import(input_file, message_loop_.task_runner(),
+                             base::Bind(&PasswordImporterTest::OnImportFinished,
+                                        base::Unretained(this)));
+
+    base::RunLoop run_loop;
+    run_loop.RunUntilIdle();
+
+    ASSERT_TRUE(callback_called_);
+  }
+
+  void OnImportFinished(PasswordImporter::Result result,
+                        const std::vector<autofill::PasswordForm>& passwords) {
+    callback_called_ = true;
+    result_ = result;
+    imported_passwords_ = passwords;
+  }
+
+  const PasswordImporter::Result& result() { return result_; }
+  const std::vector<autofill::PasswordForm>& imported_passwords() {
+    return imported_passwords_;
+  }
+
+  // Directory for creating files by this test.
+  base::ScopedTempDir temp_directory_;
+
+ private:
+  base::MessageLoop message_loop_;
+
+  bool callback_called_;
+  PasswordImporter::Result result_;
+  std::vector<autofill::PasswordForm> imported_passwords_;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordImporterTest);
+};
+
+TEST_F(PasswordImporterTest, CSVImport) {
+  const char kTestCSVInput[] =
+      "Url,Username,Password\n"
+      "http://accounts.google.com/a/LoginAuth,test@gmail.com,test1\n";
+
+  base::FilePath input_path = temp_directory_.path().AppendASCII(kTestFileName);
+  ASSERT_TRUE(
+      base::WriteFile(input_path, kTestCSVInput, strlen(kTestCSVInput)));
+  ASSERT_NO_FATAL_FAILURE(StartImportAndWaitForCompletion(input_path));
+
+  EXPECT_EQ(PasswordImporter::SUCCESS, result());
+  ASSERT_EQ(1u, imported_passwords().size());
+  EXPECT_EQ(GURL(kTestOriginURL), imported_passwords()[0].origin);
+  EXPECT_EQ(kTestSignonRealm, imported_passwords()[0].signon_realm);
+  EXPECT_EQ(base::ASCIIToUTF16(kTestUsername),
+            imported_passwords()[0].username_value);
+  EXPECT_EQ(base::ASCIIToUTF16(kTestPassword),
+            imported_passwords()[0].password_value);
+}
+
+TEST_F(PasswordImporterTest, ImportIOErrorDueToUnreadableFile) {
+  base::FilePath non_existent_input_file(FILE_PATH_LITERAL("nonexistent.csv"));
+  ASSERT_NO_FATAL_FAILURE(
+      StartImportAndWaitForCompletion(non_existent_input_file));
+
+  EXPECT_EQ(PasswordImporter::IO_ERROR, result());
+  ASSERT_EQ(0u, imported_passwords().size());
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index ca9f658..b0a58b2 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -46,6 +46,9 @@
 const base::Feature kProtectSyncCredentialOnReauth = {
     "protect-sync-credential-on-reauth", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kPasswordImportExport = {"password-import-export",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index 2e42281..f477f667 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -25,6 +25,7 @@
 extern const base::Feature kEnablePasswordForceSaving;
 extern const base::Feature kProtectSyncCredential;
 extern const base::Feature kProtectSyncCredentialOnReauth;
+extern const base::Feature kPasswordImportExport;
 
 }  // namespace features
 
diff --git a/components/safe_browsing_db/BUILD.gn b/components/safe_browsing_db/BUILD.gn
index dc5c80a..4f91591 100644
--- a/components/safe_browsing_db/BUILD.gn
+++ b/components/safe_browsing_db/BUILD.gn
@@ -219,6 +219,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "database_manager_unittest.cc",
     "prefix_set_unittest.cc",
     "util_unittest.cc",
     "v4_get_hash_protocol_manager_unittest.cc",
@@ -226,14 +227,17 @@
     "v4_update_protocol_manager_unittest.cc",
   ]
   deps = [
+    ":database_manager",
     ":prefix_set",
     ":proto",
+    ":test_database_manager",
     ":util",
     ":v4_get_hash_protocol_manager",
     ":v4_local_database_manager",
     ":v4_protocol_manager_util",
     ":v4_update_protocol_manager",
     "//base",
+    "//content/test:test_support",
     "//net",
     "//net:test_support",
     "//testing/gtest",
diff --git a/components/safe_browsing_db/DEPS b/components/safe_browsing_db/DEPS
index 8bf7b58..2130e6f 100644
--- a/components/safe_browsing_db/DEPS
+++ b/components/safe_browsing_db/DEPS
@@ -2,6 +2,7 @@
   "+components/variations",
   "+content/public/browser",
   "+content/public/common",
+  "+content/public/test",
   "+crypto",
   "+net",
 ]
diff --git a/components/safe_browsing_db/database_manager.cc b/components/safe_browsing_db/database_manager.cc
index b8998b4..c8d7aa3 100644
--- a/components/safe_browsing_db/database_manager.cc
+++ b/components/safe_browsing_db/database_manager.cc
@@ -25,11 +25,9 @@
     net::URLRequestContextGetter* request_context_getter,
     const V4ProtocolConfig& config) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (request_context_getter) {
-    // Instantiate a V4GetHashProtocolManager.
-    v4_get_hash_protocol_manager_ = V4GetHashProtocolManager::Create(
-        request_context_getter, config);
-  }
+
+  v4_get_hash_protocol_manager_ = V4GetHashProtocolManager::Create(
+      request_context_getter, config);
 }
 
 // |shutdown| not used. Destroys the v4 protocol managers. This may be called
@@ -42,11 +40,61 @@
     delete v4_get_hash_protocol_manager_;
     v4_get_hash_protocol_manager_ = NULL;
   }
+  // TODO(kcarattini): Call back clients with pending requests.
 }
 
-void SafeBrowsingDatabaseManager::CheckApiBlacklistUrl(const GURL& url,
+bool SafeBrowsingDatabaseManager::CheckApiBlacklistUrl(const GURL& url,
                                                        Client* client) {
-  // TODO(kcarattini): Implement this.
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(v4_get_hash_protocol_manager_);
+
+  // Make sure we can check this url.
+  if (!(url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme))) {
+    return true;
+  }
+
+  // Compute a list of hashes for this url.
+  std::vector<SBFullHash> full_hashes;
+  UrlToFullHashes(url, false, &full_hashes);
+  if (full_hashes.empty())
+    return true;
+
+  // Copy to prefixes.
+  std::vector<SBPrefix> prefixes;
+  for (const SBFullHash& full_hash : full_hashes) {
+    prefixes.push_back(full_hash.prefix);
+  }
+  // Multiple full hashes could share a prefix, remove duplicates.
+  std::sort(prefixes.begin(), prefixes.end());
+  prefixes.erase(std::unique(prefixes.begin(), prefixes.end()), prefixes.end());
+  DCHECK(!prefixes.empty());
+
+  // TODO(kcarattini): Track checks in a map.
+  std::shared_ptr<SafeBrowsingApiCheck> check(
+      new SafeBrowsingApiCheck(url, full_hashes, client));
+
+  // TODO(kcarattini): Implement cache compliance.
+  v4_get_hash_protocol_manager_->GetFullHashesWithApis(prefixes,
+      base::Bind(&SafeBrowsingDatabaseManager::HandleGetHashesWithApisResults,
+                 base::Unretained(this), check));
+
+  return false;
+}
+
+void SafeBrowsingDatabaseManager::HandleGetHashesWithApisResults(
+    std::shared_ptr<SafeBrowsingApiCheck> check,
+    const std::vector<SBFullHashResult>& full_hash_results,
+    const base::TimeDelta& negative_cache_duration) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  // TODO(kcarattini): Implement response handler.
+}
+
+SafeBrowsingDatabaseManager::SafeBrowsingApiCheck::SafeBrowsingApiCheck(
+    const GURL& url, const std::vector<SBFullHash>& full_hashes, Client* client)
+        : url_(url), full_hashes_(full_hashes), client_(client) {
+}
+
+SafeBrowsingDatabaseManager::SafeBrowsingApiCheck::~SafeBrowsingApiCheck() {
 }
 
 }  // namespace safe_browsing
diff --git a/components/safe_browsing_db/database_manager.h b/components/safe_browsing_db/database_manager.h
index 12d893d..083bd0e 100644
--- a/components/safe_browsing_db/database_manager.h
+++ b/components/safe_browsing_db/database_manager.h
@@ -14,6 +14,8 @@
 #include <string>
 #include <vector>
 
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "components/safe_browsing_db/hit_report.h"
 #include "components/safe_browsing_db/util.h"
@@ -63,7 +65,6 @@
                                           const std::string& threat_hash) {}
   };
 
-
   // Returns true if URL-checking is supported on this build+device.
   // If false, calls to CheckBrowseUrl may dcheck-fail.
   virtual bool IsSupported() const = 0;
@@ -148,15 +149,20 @@
   virtual bool IsCsdWhitelistKillSwitchOn() = 0;
 
   // Called on the IO thread to cancel a pending check if the result is no
-  // longer needed.  Also called after the result has been handled.
+  // longer needed.  Also called after the result has been handled. Api checks
+  // are handled separately. To cancel an API check use CancelApiCheck.
   virtual void CancelCheck(Client* client) = 0;
 
+  // TODO(kcarattini): Add a CancelApiCheck method.
+
   // Called on the IO thread to check if the given url has blacklisted APIs.
   // "client" is called asynchronously with the result when it is ready.
   // This method has the same implementation for both the local and remote
   // database managers since it pings Safe Browsing servers directly without
-  // accessing the database at all.
-  virtual void CheckApiBlacklistUrl(const GURL& url, Client* client);
+  // accessing the database at all.  Returns true if we can synchronously
+  // determine that the url is safe. Otherwise it returns false, and "client" is
+  // called asynchronously with the result when it is ready.
+  virtual bool CheckApiBlacklistUrl(const GURL& url, Client* client);
 
   // Called to initialize objects that are used on the io_thread, such as the
   // v4 protocol manager.  This may be called multiple times during the life of
@@ -175,7 +181,35 @@
 
   friend class base::RefCountedThreadSafe<SafeBrowsingDatabaseManager>;
 
-  // Created and destroyed via StartonIOThread/StopOnIOThread.
+  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingDatabaseManagerTest,
+                           CheckApiBlacklistUrlPrefixes);
+
+  // Bundled client info for an API abuse hash prefix check.
+  class SafeBrowsingApiCheck {
+   public:
+    SafeBrowsingApiCheck(const GURL& url,
+                         const std::vector<SBFullHash>& full_hashes,
+                         Client* client);
+    ~SafeBrowsingApiCheck();
+
+   private:
+    GURL url_;
+    std::vector<SBFullHash> full_hashes_;
+    // Not owned.
+    SafeBrowsingDatabaseManager::Client* client_;
+
+    DISALLOW_COPY_AND_ASSIGN(SafeBrowsingApiCheck);
+  };
+
+  // Called on the IO thread wheh the SafeBrowsingProtocolManager has received
+  // the full hash and api results for prefixes of the |url| argument in
+  // CheckApiBlacklistUrl.
+  virtual void HandleGetHashesWithApisResults(
+      std::shared_ptr<SafeBrowsingApiCheck> check,
+      const std::vector<SBFullHashResult>& full_hash_results,
+      const base::TimeDelta& negative_cache_duration);
+
+  // Created and destroyed via StartOnIOThread/StopOnIOThread.
   V4GetHashProtocolManager* v4_get_hash_protocol_manager_;
 };  // class SafeBrowsingDatabaseManager
 
diff --git a/components/safe_browsing_db/database_manager_unittest.cc b/components/safe_browsing_db/database_manager_unittest.cc
new file mode 100644
index 0000000..04490d9
--- /dev/null
+++ b/components/safe_browsing_db/database_manager_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright 2016 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 <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "components/safe_browsing_db/database_manager.h"
+#include "components/safe_browsing_db/test_database_manager.h"
+#include "components/safe_browsing_db/v4_get_hash_protocol_manager.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using content::BrowserThread;
+
+namespace safe_browsing {
+
+namespace {
+
+// A TestV4GetHashProtocolManager that returns fixed responses from the
+// Safe Browsing server for testing purpose.
+class TestV4GetHashProtocolManager : public V4GetHashProtocolManager {
+ public:
+  TestV4GetHashProtocolManager(
+      net::URLRequestContextGetter* request_context_getter,
+      const V4ProtocolConfig& config)
+      : V4GetHashProtocolManager(request_context_getter, config) {}
+
+  ~TestV4GetHashProtocolManager() override {}
+
+  void GetFullHashesWithApis(const std::vector<SBPrefix>& prefixes,
+                             FullHashCallback callback) override {
+    prefixes_ = prefixes;
+    callback.Run(full_hashes_, base::TimeDelta::FromMinutes(0));
+  }
+
+  // Prepare the GetFullHash results for the next request.
+  void AddGetFullHashResponse(const SBFullHashResult& full_hash_result) {
+    full_hashes_.push_back(full_hash_result);
+  }
+
+  // Returns the prefixes that were sent in the last request.
+  const std::vector<SBPrefix>& GetRequestPrefixes() { return prefixes_; }
+
+ private:
+  std::vector<SBPrefix> prefixes_;
+  std::vector<SBFullHashResult> full_hashes_;
+};
+
+// Factory that creates test protocol manager instances.
+class TestV4GetHashProtocolManagerFactory :
+    public V4GetHashProtocolManagerFactory {
+ public:
+  TestV4GetHashProtocolManagerFactory() : pm_(NULL) {}
+  ~TestV4GetHashProtocolManagerFactory() override {}
+
+  V4GetHashProtocolManager* CreateProtocolManager(
+      net::URLRequestContextGetter* request_context_getter,
+      const V4ProtocolConfig& config) override {
+    pm_ = new TestV4GetHashProtocolManager(request_context_getter, config);
+    return pm_;
+  }
+
+ private:
+  // Owned by the SafeBrowsingDatabaseManager.
+  TestV4GetHashProtocolManager* pm_;
+};
+
+class TestClient : public SafeBrowsingDatabaseManager::Client {
+ public:
+  TestClient() {}
+  ~TestClient() override {}
+
+  void OnCheckApiBlacklistUrlResult(const GURL& url,
+                                    const ThreatMetadata& metadata) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestClient);
+};
+
+}  // namespace
+
+class SafeBrowsingDatabaseManagerTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    TestV4GetHashProtocolManagerFactory get_hash_pm_factory;
+    V4GetHashProtocolManager::RegisterFactory(&get_hash_pm_factory);
+
+    db_manager_ = new TestSafeBrowsingDatabaseManager();
+    db_manager_->StartOnIOThread(NULL, V4ProtocolConfig());
+  }
+
+  void TearDown() override {
+    base::RunLoop().RunUntilIdle();
+    db_manager_->StopOnIOThread(false);
+  }
+
+  scoped_refptr<SafeBrowsingDatabaseManager> db_manager_;
+
+ private:
+  content::TestBrowserThreadBundle test_browser_thread_bundle_;
+};
+
+TEST_F(SafeBrowsingDatabaseManagerTest, CheckApiBlacklistUrlWrongScheme) {
+  TestClient client;
+  const GURL url("file://example.txt");
+  EXPECT_TRUE(db_manager_->CheckApiBlacklistUrl(url, &client));
+}
+
+TEST_F(SafeBrowsingDatabaseManagerTest, CheckApiBlacklistUrlPrefixes) {
+  TestClient client;
+  const GURL url("https://www.example.com/more");
+  // Generated from the sorted output of UrlToFullHashes in util.h.
+  std::vector<SBPrefix> expected_prefixes =
+      {1237562338, 2871045197, 3553205461, 3766933875};
+
+  EXPECT_FALSE(db_manager_->CheckApiBlacklistUrl(url, &client));
+  std::vector<SBPrefix> prefixes = static_cast<TestV4GetHashProtocolManager*>(
+      db_manager_->v4_get_hash_protocol_manager_)->GetRequestPrefixes();
+  EXPECT_EQ(expected_prefixes.size(), prefixes.size());
+  for (unsigned int i = 0; i < prefixes.size(); ++i) {
+    EXPECT_EQ(expected_prefixes[i], prefixes[i]);
+  }
+}
+
+}  // namespace safe_browsing
diff --git a/components/safe_browsing_db/test_database_manager.cc b/components/safe_browsing_db/test_database_manager.cc
index 478e064..1c3a91e 100644
--- a/components/safe_browsing_db/test_database_manager.cc
+++ b/components/safe_browsing_db/test_database_manager.cc
@@ -120,17 +120,4 @@
   NOTIMPLEMENTED();
 }
 
-void TestSafeBrowsingDatabaseManager::CheckApiBlacklistUrl(const GURL& url,
-                                                           Client* client) {
-  NOTIMPLEMENTED();
-}
-
-void TestSafeBrowsingDatabaseManager::StartOnIOThread(
-    net::URLRequestContextGetter* request_context_getter,
-    const V4ProtocolConfig& config) {
-}
-
-void TestSafeBrowsingDatabaseManager::StopOnIOThread(bool shutdown) {
-}
-
 }  // namespace safe_browsing
diff --git a/components/safe_browsing_db/test_database_manager.h b/components/safe_browsing_db/test_database_manager.h
index eb7fcfd..ae98b9a1 100644
--- a/components/safe_browsing_db/test_database_manager.h
+++ b/components/safe_browsing_db/test_database_manager.h
@@ -21,7 +21,8 @@
 
 // This is a non-pure-virtual implementation of the SafeBrowsingDatabaseManager
 // interface.  It's used in tests by overriding only the functions that get
-// called, and it'll complain if you call one that isn't overriden.
+// called, and it'll complain if you call one that isn't overriden. The
+// non-abstract methods in the base class are not overridden.
 class TestSafeBrowsingDatabaseManager
     : public SafeBrowsingDatabaseManager {
  public:
@@ -47,11 +48,6 @@
   bool IsMalwareKillSwitchOn() override;
   bool IsCsdWhitelistKillSwitchOn() override;
   void CancelCheck(Client* client) override;
-  void CheckApiBlacklistUrl(const GURL& url, Client* client) override;
-  void StartOnIOThread(
-      net::URLRequestContextGetter* request_context_getter,
-      const V4ProtocolConfig& config) override;
-  void StopOnIOThread(bool shutdown) override;
 
  protected:
   ~TestSafeBrowsingDatabaseManager() override {};
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 16111311..8a9b604a 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -51,14 +51,6 @@
 // Used in kReportLanguageDetectionErrorURL to specify the page URL.
 const char kUrlQueryName[] = "u";
 
-// Notifies |g_callback_list_| of translate errors.
-void NotifyTranslateError(const TranslateErrorDetails& details) {
-  if (!g_callback_list_)
-    return;
-
-  g_callback_list_->Notify(details);
-}
-
 }  // namespace
 
 TranslateManager::~TranslateManager() {}
@@ -296,6 +288,20 @@
       page_seq_no_, translate_script, source_lang, target_lang);
 }
 
+// Notifies |g_callback_list_| of translate errors.
+void TranslateManager::NotifyTranslateError(TranslateErrors::Type error_type) {
+  if (!g_callback_list_ || error_type == TranslateErrors::NONE ||
+      translate_driver_->IsOffTheRecord()) {
+    return;
+  }
+
+  TranslateErrorDetails error_details;
+  error_details.time = base::Time::Now();
+  error_details.url = translate_driver_->GetLastCommittedURL();
+  error_details.error = error_type;
+  g_callback_list_->Notify(error_details);
+}
+
 void TranslateManager::PageTranslated(const std::string& source_lang,
                                       const std::string& target_lang,
                                       TranslateErrors::Type error_type) {
@@ -313,15 +319,7 @@
                                      target_lang,
                                      error_type,
                                      false);
-
-  if (error_type != TranslateErrors::NONE &&
-      !translate_driver_->IsOffTheRecord()) {
-    TranslateErrorDetails error_details;
-    error_details.time = base::Time::Now();
-    error_details.url = translate_driver_->GetLastCommittedURL();
-    error_details.error = error_type;
-    NotifyTranslateError(error_details);
-  }
+  NotifyTranslateError(error_type);
 }
 
 void TranslateManager::OnTranslateScriptFetchComplete(
@@ -345,13 +343,7 @@
         target_lang,
         TranslateErrors::NETWORK,
         false);
-    if (!translate_driver_->IsOffTheRecord()) {
-      TranslateErrorDetails error_details;
-      error_details.time = base::Time::Now();
-      error_details.url = translate_driver_->GetLastCommittedURL();
-      error_details.error = TranslateErrors::NETWORK;
-      NotifyTranslateError(error_details);
-    }
+    NotifyTranslateError(TranslateErrors::NETWORK);
   }
 }
 
diff --git a/components/translate/core/browser/translate_manager.h b/components/translate/core/browser/translate_manager.h
index 3cf2af1..a8fcc19 100644
--- a/components/translate/core/browser/translate_manager.h
+++ b/components/translate/core/browser/translate_manager.h
@@ -108,6 +108,9 @@
                        const std::string& source_lang,
                        const std::string& target_lang);
 
+  // Notifies all registered callbacks of translate errors.
+  void NotifyTranslateError(TranslateErrors::Type error_type);
+
   // Called when the Translate script has been fetched.
   // Initiates the translation.
   void OnTranslateScriptFetchComplete(const std::string& source_lang,
diff --git a/components/visitedlink/renderer/visitedlink_slave.h b/components/visitedlink/renderer/visitedlink_slave.h
index 6db2f32..31cae89a 100644
--- a/components/visitedlink/renderer/visitedlink_slave.h
+++ b/components/visitedlink/renderer/visitedlink_slave.h
@@ -9,19 +9,19 @@
 #include "base/macros.h"
 #include "base/memory/shared_memory.h"
 #include "components/visitedlink/common/visitedlink_common.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 namespace visitedlink {
 
 // Reads the link coloring database provided by the master. There can be any
 // number of slaves reading the same database.
 class VisitedLinkSlave : public VisitedLinkCommon,
-                         public content::RenderProcessObserver {
+                         public content::RenderThreadObserver {
  public:
   VisitedLinkSlave();
   ~VisitedLinkSlave() override;
 
-  // RenderProcessObserver implementation.
+  // RenderThreadObserver implementation.
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   // Message handlers.
diff --git a/components/web_cache.gypi b/components/web_cache.gypi
index a48ce61..af4e75c 100644
--- a/components/web_cache.gypi
+++ b/components/web_cache.gypi
@@ -40,8 +40,8 @@
         'web_cache_mojo_bindings',
       ],
       'sources': [
-        'web_cache/renderer/web_cache_render_process_observer.cc',
-        'web_cache/renderer/web_cache_render_process_observer.h',
+        'web_cache/renderer/web_cache_render_thread_observer.cc',
+        'web_cache/renderer/web_cache_render_thread_observer.h',
       ],
     },
   ],
diff --git a/components/web_cache/renderer/BUILD.gn b/components/web_cache/renderer/BUILD.gn
index c803783f..c7d34c5 100644
--- a/components/web_cache/renderer/BUILD.gn
+++ b/components/web_cache/renderer/BUILD.gn
@@ -4,8 +4,8 @@
 
 source_set("renderer") {
   sources = [
-    "web_cache_render_process_observer.cc",
-    "web_cache_render_process_observer.h",
+    "web_cache_render_thread_observer.cc",
+    "web_cache_render_thread_observer.h",
   ]
 
   deps = [
diff --git a/components/web_cache/renderer/web_cache_render_process_observer.cc b/components/web_cache/renderer/web_cache_render_thread_observer.cc
similarity index 77%
rename from components/web_cache/renderer/web_cache_render_process_observer.cc
rename to components/web_cache/renderer/web_cache_render_thread_observer.cc
index a1f1425..b7c0552 100644
--- a/components/web_cache/renderer/web_cache_render_process_observer.cc
+++ b/components/web_cache/renderer/web_cache_render_thread_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_render_thread_observer.h"
 
 #include <limits>
 
@@ -14,23 +14,23 @@
 
 namespace web_cache {
 
-WebCacheRenderProcessObserver::WebCacheRenderProcessObserver()
+WebCacheRenderThreadObserver::WebCacheRenderThreadObserver()
     : clear_cache_state_(kInit) {
   content::ServiceRegistry* service_registry =
       content::RenderThread::Get()->GetServiceRegistry();
   service_registry->AddService(base::Bind(
-      &WebCacheRenderProcessObserver::BindRequest, base::Unretained(this)));
+      &WebCacheRenderThreadObserver::BindRequest, base::Unretained(this)));
 }
 
-WebCacheRenderProcessObserver::~WebCacheRenderProcessObserver() {
+WebCacheRenderThreadObserver::~WebCacheRenderThreadObserver() {
 }
 
-void WebCacheRenderProcessObserver::BindRequest(
+void WebCacheRenderThreadObserver::BindRequest(
     mojo::InterfaceRequest<mojom::WebCache> web_cache_request) {
   bindings_.AddBinding(this, std::move(web_cache_request));
 }
 
-void WebCacheRenderProcessObserver::ExecutePendingClearCache() {
+void WebCacheRenderThreadObserver::ExecutePendingClearCache() {
   switch (clear_cache_state_) {
     case kInit:
       clear_cache_state_ = kNavigate_Pending;
@@ -44,7 +44,7 @@
   }
 }
 
-void WebCacheRenderProcessObserver::SetCacheCapacities(
+void WebCacheRenderThreadObserver::SetCacheCapacities(
     uint64_t min_dead_capacity,
     uint64_t max_dead_capacity,
     uint64_t capacity64) {
@@ -56,7 +56,7 @@
                                  capacity);
 }
 
-void WebCacheRenderProcessObserver::ClearCache(bool on_navigation) {
+void WebCacheRenderThreadObserver::ClearCache(bool on_navigation) {
   if (!on_navigation) {
     blink::WebCache::clear();
     return;
diff --git a/components/web_cache/renderer/web_cache_render_process_observer.h b/components/web_cache/renderer/web_cache_render_thread_observer.h
similarity index 77%
rename from components/web_cache/renderer/web_cache_render_process_observer.h
rename to components/web_cache/renderer/web_cache_render_thread_observer.h
index a43f539..c0ab078c 100644
--- a/components/web_cache/renderer/web_cache_render_process_observer.h
+++ b/components/web_cache/renderer/web_cache_render_thread_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
-#define COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+#ifndef COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_THREAD_OBSERVER_H_
+#define COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_THREAD_OBSERVER_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -16,10 +16,10 @@
 namespace web_cache {
 
 // This class implements the Mojo interface mojom::WebCache.
-class WebCacheRenderProcessObserver : public mojom::WebCache {
+class WebCacheRenderThreadObserver : public mojom::WebCache {
  public:
-  WebCacheRenderProcessObserver();
-  ~WebCacheRenderProcessObserver() override;
+  WebCacheRenderThreadObserver();
+  ~WebCacheRenderThreadObserver() override;
 
   void BindRequest(mojo::InterfaceRequest<mojom::WebCache> web_cache_request);
 
@@ -49,10 +49,10 @@
 
   mojo::BindingSet<mojom::WebCache> bindings_;
 
-  DISALLOW_COPY_AND_ASSIGN(WebCacheRenderProcessObserver);
+  DISALLOW_COPY_AND_ASSIGN(WebCacheRenderThreadObserver);
 };
 
 }  // namespace web_cache
 
-#endif  // COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_PROCESS_OBSERVER_H_
+#endif  // COMPONENTS_WEB_CACHE_RENDERER_WEB_CACHE_RENDER_THREAD_OBSERVER_H_
 
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index 8c973f76..c006142 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -58,7 +58,6 @@
 #include "net/base/data_url.h"
 #include "net/base/ip_address.h"
 #include "net/base/net_errors.h"
-#include "net/base/port_util.h"
 #include "third_party/WebKit/public/platform/WebData.h"
 #include "third_party/WebKit/public/platform/WebFloatPoint.h"
 #include "third_party/WebKit/public/platform/WebMemoryDumpProvider.h"
@@ -458,15 +457,6 @@
   return address.IsReserved();
 }
 
-bool BlinkPlatformImpl::portAllowed(const blink::WebURL& url) const {
-  GURL gurl = GURL(url);
-  // Return true for URLs without a port specified.  This is needed to let
-  // through non-network schemes that don't go over the network.
-  if (!gurl.has_port())
-    return true;
-  return net::IsPortAllowedForScheme(gurl.EffectiveIntPort(), gurl.scheme());
-}
-
 bool BlinkPlatformImpl::parseMultipartHeadersFromBody(
     const char* bytes,
     size_t size,
diff --git a/content/child/blink_platform_impl.h b/content/child/blink_platform_impl.h
index 1b04587..cc02897 100644
--- a/content/child/blink_platform_impl.h
+++ b/content/child/blink_platform_impl.h
@@ -93,12 +93,10 @@
                               blink::WebString& charset) override;
   blink::WebURLError cancelledError(const blink::WebURL& url) const override;
   bool isReservedIPAddress(const blink::WebString& host) const override;
-  bool portAllowed(const blink::WebURL& url) const override;
   bool parseMultipartHeadersFromBody(const char* bytes,
                                      size_t size,
                                      blink::WebURLResponse* response,
                                      size_t* end) const override;
-
   blink::WebThread* createThread(const char* name) override;
   blink::WebThread* currentThread() override;
   void recordAction(const blink::UserMetricsAction&) override;
diff --git a/content/child/blink_platform_impl_unittest.cc b/content/child/blink_platform_impl_unittest.cc
index 0512f79..dcacee3 100644
--- a/content/child/blink_platform_impl_unittest.cc
+++ b/content/child/blink_platform_impl_unittest.cc
@@ -68,18 +68,6 @@
   }
 }
 
-TEST(BlinkPlatformTest, portAllowed) {
-  BlinkPlatformImpl platform_impl;
-  EXPECT_TRUE(platform_impl.portAllowed(GURL("http://example.com")));
-  EXPECT_TRUE(platform_impl.portAllowed(GURL("file://example.com")));
-  EXPECT_TRUE(platform_impl.portAllowed(GURL("file://example.com:87")));
-  EXPECT_TRUE(platform_impl.portAllowed(GURL("ftp://example.com:21")));
-  EXPECT_FALSE(platform_impl.portAllowed(GURL("ftp://example.com:87")));
-  EXPECT_FALSE(platform_impl.portAllowed(GURL("ws://example.com:21")));
-  EXPECT_TRUE(platform_impl.portAllowed(GURL("http://example.com:80")));
-  EXPECT_TRUE(platform_impl.portAllowed(GURL("http://example.com:8889")));
-}
-
 TEST(BlinkPlatformTest, castWebSecurityOrigin) {
   struct TestCase {
     const char* origin;
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 9c71624..fadb26e 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -77,8 +77,8 @@
       'public/renderer/render_frame_observer.cc',
       'public/renderer/render_frame_observer.h',
       'public/renderer/render_frame_observer_tracker.h',
-      'public/renderer/render_process_observer.cc',
-      'public/renderer/render_process_observer.h',
+      'public/renderer/render_thread_observer.cc',
+      'public/renderer/render_thread_observer.h',
       'public/renderer/render_thread.cc',
       'public/renderer/render_thread.h',
       'public/renderer/render_view.h',
diff --git a/content/content_shell.gypi b/content/content_shell.gypi
index e1ffca04..f093081 100644
--- a/content/content_shell.gypi
+++ b/content/content_shell.gypi
@@ -220,8 +220,8 @@
         'shell/renderer/layout_test/layout_test_content_renderer_client.h',
         'shell/renderer/layout_test/layout_test_render_frame_observer.cc',
         'shell/renderer/layout_test/layout_test_render_frame_observer.h',
-        'shell/renderer/layout_test/layout_test_render_process_observer.cc',
-        'shell/renderer/layout_test/layout_test_render_process_observer.h',
+        'shell/renderer/layout_test/layout_test_render_thread_observer.cc',
+        'shell/renderer/layout_test/layout_test_render_thread_observer.h',
         'shell/renderer/layout_test/leak_detector.cc',
         'shell/renderer/layout_test/leak_detector.h',
         'shell/renderer/layout_test/test_media_stream_renderer_factory.cc',
diff --git a/content/public/renderer/platform_event_observer.h b/content/public/renderer/platform_event_observer.h
index a7d296c..b62d169 100644
--- a/content/public/renderer/platform_event_observer.h
+++ b/content/public/renderer/platform_event_observer.h
@@ -7,8 +7,8 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
-#include "content/public/renderer/render_process_observer.h"
 #include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 namespace blink {
 class WebPlatformEventListener;
@@ -41,7 +41,7 @@
 // registered as an observer via the constructor taking a RenderThread.
 template <typename ListenerType>
 class PlatformEventObserver : public PlatformEventObserverBase,
-                              public RenderProcessObserver {
+                              public RenderThreadObserver {
  public:
   // Creates a PlatformEventObserver that doesn't listen to responses from the
   // browser process. Can be used for testing purposes or for observers that
diff --git a/content/public/renderer/render_thread.h b/content/public/renderer/render_thread.h
index 4a1ec579..2c219f25 100644
--- a/content/public/renderer/render_thread.h
+++ b/content/public/renderer/render_thread.h
@@ -38,7 +38,7 @@
 
 namespace content {
 
-class RenderProcessObserver;
+class RenderThreadObserver;
 class ResourceDispatcherDelegate;
 class ServiceRegistry;
 
@@ -68,8 +68,8 @@
   virtual void RemoveFilter(IPC::MessageFilter* filter) = 0;
 
   // Add/remove observers for the process.
-  virtual void AddObserver(RenderProcessObserver* observer) = 0;
-  virtual void RemoveObserver(RenderProcessObserver* observer) = 0;
+  virtual void AddObserver(RenderThreadObserver* observer) = 0;
+  virtual void RemoveObserver(RenderThreadObserver* observer) = 0;
 
   // Set the ResourceDispatcher delegate object for this process.
   virtual void SetResourceDispatcherDelegate(
diff --git a/content/public/renderer/render_process_observer.cc b/content/public/renderer/render_thread_observer.cc
similarity index 70%
rename from content/public/renderer/render_process_observer.cc
rename to content/public/renderer/render_thread_observer.cc
index 8e97cb7..cbed17dc 100644
--- a/content/public/renderer/render_process_observer.cc
+++ b/content/public/renderer/render_thread_observer.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 
 namespace content {
 
-bool RenderProcessObserver::OnControlMessageReceived(
+bool RenderThreadObserver::OnControlMessageReceived(
     const IPC::Message& message) {
   return false;
 }
diff --git a/content/public/renderer/render_process_observer.h b/content/public/renderer/render_thread_observer.h
similarity index 72%
rename from content/public/renderer/render_process_observer.h
rename to content/public/renderer/render_thread_observer.h
index 30f855d..fd2ca57 100644
--- a/content/public/renderer/render_process_observer.h
+++ b/content/public/renderer/render_thread_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_PUBLIC_RENDERER_RENDER_PROCESS_OBSERVER_H_
-#define CONTENT_PUBLIC_RENDERER_RENDER_PROCESS_OBSERVER_H_
+#ifndef CONTENT_PUBLIC_RENDERER_RENDER_THREAD_OBSERVER_H_
+#define CONTENT_PUBLIC_RENDERER_RENDER_THREAD_OBSERVER_H_
 
 #include "base/macros.h"
 #include "content/common/content_export.h"
@@ -16,10 +16,10 @@
 
 // Base class for objects that want to filter control IPC messages and get
 // notified of events.
-class CONTENT_EXPORT RenderProcessObserver {
+class CONTENT_EXPORT RenderThreadObserver {
  public:
-  RenderProcessObserver() {}
-  virtual ~RenderProcessObserver() {}
+  RenderThreadObserver() {}
+  virtual ~RenderThreadObserver() {}
 
   // Allows filtering of control messages.
   virtual bool OnControlMessageReceived(const IPC::Message& message);
@@ -36,9 +36,9 @@
   virtual void NetworkStateChanged(bool online) {}
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(RenderProcessObserver);
+  DISALLOW_COPY_AND_ASSIGN(RenderThreadObserver);
 };
 
 }  // namespace content
 
-#endif  // CONTENT_PUBLIC_RENDERER_RENDER_PROCESS_OBSERVER_H_
+#endif  // CONTENT_PUBLIC_RENDERER_RENDER_THREAD_OBSERVER_H_
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index b12143d..d499691 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -11,7 +11,7 @@
 #include "content/common/frame_messages.h"
 #include "content/common/mojo/service_registry_impl.h"
 #include "content/common/view_messages.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "content/renderer/render_view_impl.h"
 #include "ipc/ipc_message_utils.h"
 #include "ipc/ipc_sync_message.h"
@@ -111,11 +111,11 @@
   NOTREACHED() << "filter to be removed not found";
 }
 
-void MockRenderThread::AddObserver(RenderProcessObserver* observer) {
+void MockRenderThread::AddObserver(RenderThreadObserver* observer) {
   observers_.AddObserver(observer);
 }
 
-void MockRenderThread::RemoveObserver(RenderProcessObserver* observer) {
+void MockRenderThread::RemoveObserver(RenderThreadObserver* observer) {
   observers_.RemoveObserver(observer);
 }
 
@@ -220,8 +220,8 @@
 }
 
 bool MockRenderThread::OnControlMessageReceived(const IPC::Message& msg) {
-  base::ObserverListBase<RenderProcessObserver>::Iterator it(&observers_);
-  RenderProcessObserver* observer;
+  base::ObserverListBase<RenderThreadObserver>::Iterator it(&observers_);
+  RenderThreadObserver* observer;
   while ((observer = it.GetNext()) != NULL) {
     if (observer->OnControlMessageReceived(msg))
       return true;
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index eeb3744..eab9587 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -59,8 +59,8 @@
   int GenerateRoutingID() override;
   void AddFilter(IPC::MessageFilter* filter) override;
   void RemoveFilter(IPC::MessageFilter* filter) override;
-  void AddObserver(RenderProcessObserver* observer) override;
-  void RemoveObserver(RenderProcessObserver* observer) override;
+  void AddObserver(RenderThreadObserver* observer) override;
+  void RemoveObserver(RenderThreadObserver* observer) override;
   void SetResourceDispatcherDelegate(
       ResourceDispatcherDelegate* delegate) override;
   void RecordAction(const base::UserMetricsAction& action) override;
@@ -107,7 +107,7 @@
   // Dispatches control messages to observers.
   bool OnControlMessageReceived(const IPC::Message& msg);
 
-  base::ObserverList<RenderProcessObserver>& observers() { return observers_; }
+  base::ObserverList<RenderThreadObserver>& observers() { return observers_; }
 
  protected:
   // This function operates as a regular IPC listener. Subclasses
@@ -155,7 +155,7 @@
   std::vector<scoped_refptr<IPC::MessageFilter> > filters_;
 
   // Observers to notify.
-  base::ObserverList<RenderProcessObserver> observers_;
+  base::ObserverList<RenderThreadObserver> observers_;
 
   cc::TestSharedBitmapManager shared_bitmap_manager_;
   std::unique_ptr<ServiceRegistry> service_registry_;
diff --git a/content/renderer/browser_plugin/browser_plugin_manager.h b/content/renderer/browser_plugin/browser_plugin_manager.h
index b8471af..1d4ff7c 100644
--- a/content/renderer/browser_plugin/browser_plugin_manager.h
+++ b/content/renderer/browser_plugin/browser_plugin_manager.h
@@ -8,7 +8,7 @@
 #include "base/id_map.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "ipc/ipc_sender.h"
 
 namespace blink {
@@ -24,7 +24,7 @@
 // BrowserPluginManager manages the routing of messages to the appropriate
 // BrowserPlugin object based on its instance ID. There is one BrowserPlugin
 // for the RenderThread.
-class CONTENT_EXPORT BrowserPluginManager : public RenderProcessObserver {
+class CONTENT_EXPORT BrowserPluginManager : public RenderThreadObserver {
  public:
   static BrowserPluginManager* Get();
 
@@ -60,7 +60,7 @@
   void DidCommitCompositorFrame(int render_frame_routing_id);
   bool Send(IPC::Message* msg);
 
-  // RenderProcessObserver override.
+  // RenderThreadObserver override.
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
  private:
diff --git a/content/renderer/cache_storage/cache_storage_dispatcher.h b/content/renderer/cache_storage/cache_storage_dispatcher.h
index 88a3933..366cb7a 100644
--- a/content/renderer/cache_storage/cache_storage_dispatcher.h
+++ b/content/renderer/cache_storage/cache_storage_dispatcher.h
@@ -15,7 +15,7 @@
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "content/public/child/worker_thread.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "ipc/ipc_message.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCache.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheError.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheStorage.h"
diff --git a/content/renderer/image_downloader/image_downloader_impl.h b/content/renderer/image_downloader/image_downloader_impl.h
index 907eae7a..07ba015 100644
--- a/content/renderer/image_downloader/image_downloader_impl.h
+++ b/content/renderer/image_downloader/image_downloader_impl.h
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_vector.h"
 #include "content/common/image_downloader/image_downloader.mojom.h"
 #include "content/public/renderer/render_frame_observer.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "url/gurl.h"
 
@@ -30,13 +30,13 @@
 
 class ImageDownloaderImpl : public content::mojom::ImageDownloader,
                             public RenderFrameObserver,
-                            public RenderProcessObserver {
+                            public RenderThreadObserver {
  public:
   static void CreateMojoService(
       RenderFrame* render_frame,
       mojo::InterfaceRequest<content::mojom::ImageDownloader> request);
 
-  // RenderProcessObserver implementation.
+  // RenderThreadObserver implementation.
   void OnRenderProcessShutdown() override;
 
  private:
diff --git a/content/renderer/media/media_stream_center.h b/content/renderer/media/media_stream_center.h
index 2b1253bc..5b72e6c 100644
--- a/content/renderer/media/media_stream_center.h
+++ b/content/renderer/media/media_stream_center.h
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "content/common/content_export.h"
 #include "content/common/media/media_stream_options.h"
-#include "content/public/renderer/render_process_observer.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamCenter.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
diff --git a/content/renderer/media/peer_connection_tracker.h b/content/renderer/media/peer_connection_tracker.h
index 80b823c..679ca45 100644
--- a/content/renderer/media/peer_connection_tracker.h
+++ b/content/renderer/media/peer_connection_tracker.h
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
@@ -40,7 +40,7 @@
 // sends it to the browser process, and handles messages
 // from the browser process.
 class CONTENT_EXPORT PeerConnectionTracker
-    : public RenderProcessObserver,
+    : public RenderThreadObserver,
       public base::SupportsWeakPtr<PeerConnectionTracker> {
  public:
   PeerConnectionTracker();
@@ -58,7 +58,7 @@
     ACTION_CREATE_ANSWER
   };
 
-  // RenderProcessObserver implementation.
+  // RenderThreadObserver implementation.
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   //
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index e581743..276f3d1 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -9,10 +9,10 @@
 
 #include "base/files/file.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
 #include "content/common/content_export.h"
-#include "content/public/renderer/render_process_observer.h"
 #include "content/renderer/media/webrtc/stun_field_trial.h"
 #include "content/renderer/p2p/socket_dispatcher.h"
 #include "ipc/ipc_platform_file.h"
diff --git a/content/renderer/media/webrtc_identity_service.h b/content/renderer/media/webrtc_identity_service.h
index 927700d..9abc398 100644
--- a/content/renderer/media/webrtc_identity_service.h
+++ b/content/renderer/media/webrtc_identity_service.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "content/common/content_export.h"
 #include "content/common/media/webrtc_identity_messages.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -20,7 +20,7 @@
 // This class handles WebRTC DTLS identity requests by sending IPC messages to
 // the browser process. Only one request is sent to the browser at a time; other
 // requests are queued and have to wait for the outstanding request to complete.
-class CONTENT_EXPORT WebRTCIdentityService : public RenderProcessObserver {
+class CONTENT_EXPORT WebRTCIdentityService : public RenderThreadObserver {
  public:
   typedef base::Callback<
       void(const std::string& certificate, const std::string& private_key)>
@@ -61,7 +61,7 @@
  protected:
   // For unittest to override.
   virtual bool Send(IPC::Message* message);
-  // RenderProcessObserver implementation. Protected for testing.
+  // RenderThreadObserver implementation. Protected for testing.
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
  private:
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index eac04476..a668699c 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -86,7 +86,7 @@
 #include "content/public/common/renderer_preferences.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/renderer/content_renderer_client.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "content/public/renderer/render_view_visitor.h"
 #include "content/renderer/bluetooth/bluetooth_message_filter.h"
 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
@@ -849,7 +849,7 @@
 
 void RenderThreadImpl::Shutdown() {
   FOR_EACH_OBSERVER(
-      RenderProcessObserver, observers_, OnRenderProcessShutdown());
+      RenderThreadObserver, observers_, OnRenderProcessShutdown());
 
   if (memory_observer_) {
     message_loop()->RemoveTaskObserver(memory_observer_.get());
@@ -1109,11 +1109,11 @@
   channel()->RemoveFilter(filter);
 }
 
-void RenderThreadImpl::AddObserver(RenderProcessObserver* observer) {
+void RenderThreadImpl::AddObserver(RenderThreadObserver* observer) {
   observers_.AddObserver(observer);
 }
 
-void RenderThreadImpl::RemoveObserver(RenderProcessObserver* observer) {
+void RenderThreadImpl::RemoveObserver(RenderThreadObserver* observer) {
   observers_.RemoveObserver(observer);
 }
 
@@ -1402,7 +1402,7 @@
     idle_timer_.Stop();
   }
 
-  FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification());
+  FOR_EACH_OBSERVER(RenderThreadObserver, observers_, IdleNotification());
 }
 
 int64_t RenderThreadImpl::GetIdleNotificationDelayInMs() const {
@@ -1729,8 +1729,8 @@
 }
 
 bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
-  base::ObserverListBase<RenderProcessObserver>::Iterator it(&observers_);
-  RenderProcessObserver* observer;
+  base::ObserverListBase<RenderThreadObserver>::Iterator it(&observers_);
+  RenderThreadObserver* observer;
   while ((observer = it.GetNext()) != NULL) {
     if (observer->OnControlMessageReceived(msg))
       return true;
@@ -1907,7 +1907,7 @@
   blink::resetPluginCache(reload_pages);
   blink_platform_impl_->set_plugin_refresh_allowed(true);
 
-  FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged());
+  FOR_EACH_OBSERVER(RenderThreadObserver, observers_, PluginListChanged());
 }
 #endif
 
@@ -1917,7 +1917,7 @@
   bool online = type != net::NetworkChangeNotifier::CONNECTION_NONE;
   WebNetworkStateNotifier::setOnLine(online);
   FOR_EACH_OBSERVER(
-      RenderProcessObserver, observers_, NetworkStateChanged(online));
+      RenderThreadObserver, observers_, NetworkStateChanged(online));
   WebNetworkStateNotifier::setWebConnection(
       NetConnectionTypeToWebConnectionType(type), max_bandwidth_mbps);
 }
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 2ff20c0..ae69e3b4 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -116,7 +116,7 @@
 class PeerConnectionDependencyFactory;
 class PeerConnectionTracker;
 class RasterWorkerPool;
-class RenderProcessObserver;
+class RenderThreadObserver;
 class RendererBlinkPlatformImpl;
 class RendererDemuxerAndroid;
 class RendererGpuVideoAcceleratorFactories;
@@ -180,8 +180,8 @@
   int GenerateRoutingID() override;
   void AddFilter(IPC::MessageFilter* filter) override;
   void RemoveFilter(IPC::MessageFilter* filter) override;
-  void AddObserver(RenderProcessObserver* observer) override;
-  void RemoveObserver(RenderProcessObserver* observer) override;
+  void AddObserver(RenderThreadObserver* observer) override;
+  void RemoveObserver(RenderThreadObserver* observer) override;
   void SetResourceDispatcherDelegate(
       ResourceDispatcherDelegate* delegate) override;
   std::unique_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
@@ -645,7 +645,7 @@
 
   scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_;
 
-  base::ObserverList<RenderProcessObserver> observers_;
+  base::ObserverList<RenderThreadObserver> observers_;
 
   scoped_refptr<ContextProviderCommandBuffer> shared_worker_context_provider_;
 
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 5437060f..31ffc7f 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -169,8 +169,8 @@
     "renderer/layout_test/layout_test_content_renderer_client.h",
     "renderer/layout_test/layout_test_render_frame_observer.cc",
     "renderer/layout_test/layout_test_render_frame_observer.h",
-    "renderer/layout_test/layout_test_render_process_observer.cc",
-    "renderer/layout_test/layout_test_render_process_observer.h",
+    "renderer/layout_test/layout_test_render_thread_observer.cc",
+    "renderer/layout_test/layout_test_render_thread_observer.h",
     "renderer/layout_test/leak_detector.cc",
     "renderer/layout_test/leak_detector.h",
     "renderer/layout_test/test_media_stream_renderer_factory.cc",
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc
index b66595d..8ebd862 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.cc
+++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -51,7 +51,7 @@
 #include "content/shell/common/shell_messages.h"
 #include "content/shell/common/shell_switches.h"
 #include "content/shell/renderer/layout_test/blink_test_helpers.h"
-#include "content/shell/renderer/layout_test/layout_test_render_process_observer.h"
+#include "content/shell/renderer/layout_test/layout_test_render_thread_observer.h"
 #include "content/shell/renderer/layout_test/leak_detector.h"
 #include "media/audio/audio_parameters.h"
 #include "media/base/audio_capturer_source.h"
@@ -316,7 +316,7 @@
     return WebURL(GURL(utf8_url));
 
   base::FilePath replace_path =
-      LayoutTestRenderProcessObserver::GetInstance()->webkit_source_dir()
+      LayoutTestRenderThreadObserver::GetInstance()->webkit_source_dir()
           .Append(FILE_PATH_LITERAL("LayoutTests/"));
 #if defined(OS_WIN)
   std::string utf8_path = base::WideToUTF8(replace_path.value());
@@ -551,7 +551,7 @@
     return;
   }
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   interfaces->SetTestIsRunning(false);
   if (interfaces->TestRunner()->ShouldDumpBackForwardList()) {
     SyncNavigationStateVisitor visitor;
@@ -722,7 +722,7 @@
 
 void BlinkTestRunner::DidClearWindowObject(WebLocalFrame* frame) {
   WebTestingSupport::injectInternalsObject(frame);
-  LayoutTestRenderProcessObserver::GetInstance()->test_interfaces()->BindTo(
+  LayoutTestRenderThreadObserver::GetInstance()->test_interfaces()->BindTo(
       frame);
 }
 
@@ -745,10 +745,10 @@
 void BlinkTestRunner::Navigate(const GURL& url) {
   focus_on_next_commit_ = true;
   if (!is_main_window_ &&
-      LayoutTestRenderProcessObserver::GetInstance()->main_test_runner() ==
+      LayoutTestRenderThreadObserver::GetInstance()->main_test_runner() ==
           this) {
     test_runner::WebTestInterfaces* interfaces =
-        LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+        LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
     interfaces->SetTestIsRunning(true);
     interfaces->ConfigureForTestWithURL(GURL(), false);
     ForceResizeRenderView(render_view(), WebSize(800, 600));
@@ -796,7 +796,7 @@
 
 void BlinkTestRunner::CaptureDump() {
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   TRACE_EVENT0("shell", "BlinkTestRunner::CaptureDump");
 
   if (interfaces->TestRunner()->ShouldDumpAsAudio()) {
@@ -827,7 +827,7 @@
 
 void BlinkTestRunner::OnLayoutDumpCompleted(std::string completed_layout_dump) {
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   if (interfaces->TestRunner()->ShouldDumpBackForwardList()) {
     for (WebView* web_view : interfaces->GetWindowList())
       completed_layout_dump.append(DumpHistoryForWindow(web_view));
@@ -840,7 +840,7 @@
 
 void BlinkTestRunner::CaptureDumpContinued() {
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   if (test_config_.enable_pixel_dumping &&
       interfaces->TestRunner()->ShouldGeneratePixelResults() &&
       !interfaces->TestRunner()->ShouldDumpAsAudio()) {
@@ -910,7 +910,7 @@
   is_main_window_ = true;
 
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   interfaces->SetTestIsRunning(true);
   interfaces->ConfigureForTestWithURL(params.test_url,
                                       params.enable_pixel_dumping);
@@ -923,7 +923,7 @@
   ForceResizeRenderView(
       render_view(),
       WebSize(params.initial_size.width(), params.initial_size.height()));
-  LayoutTestRenderProcessObserver::GetInstance()
+  LayoutTestRenderThreadObserver::GetInstance()
       ->test_interfaces()
       ->TestRunner()
       ->SetFocus(render_view()->GetWebView(), true);
@@ -940,7 +940,7 @@
 }
 
 void BlinkTestRunner::OnReset() {
-  LayoutTestRenderProcessObserver::GetInstance()->test_interfaces()->ResetAll();
+  LayoutTestRenderThreadObserver::GetInstance()->test_interfaces()->ResetAll();
   Reset(true /* for_new_test */);
   // Navigating to about:blank will make sure that no new loads are initiated
   // by the renderer.
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
index 526d2d9..67cc21d2 100644
--- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
+++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
@@ -12,7 +12,7 @@
 #include "components/test_runner/web_test_interfaces.h"
 #include "components/test_runner/web_test_proxy.h"
 #include "components/test_runner/web_test_runner.h"
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_render_thread_observer.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_view.h"
@@ -21,7 +21,7 @@
 #include "content/shell/renderer/layout_test/blink_test_helpers.h"
 #include "content/shell/renderer/layout_test/blink_test_runner.h"
 #include "content/shell/renderer/layout_test/layout_test_render_frame_observer.h"
-#include "content/shell/renderer/layout_test/layout_test_render_process_observer.h"
+#include "content/shell/renderer/layout_test/layout_test_render_thread_observer.h"
 #include "content/shell/renderer/layout_test/test_media_stream_renderer_factory.h"
 #include "content/shell/renderer/shell_render_view_observer.h"
 #include "content/test/mock_webclipboard_impl.h"
@@ -55,20 +55,20 @@
   test_runner->set_proxy(proxy);
   proxy->set_delegate(test_runner);
 
-  if (!LayoutTestRenderProcessObserver::GetInstance()->test_delegate()) {
-    LayoutTestRenderProcessObserver::GetInstance()->SetTestDelegate(
+  if (!LayoutTestRenderThreadObserver::GetInstance()->test_delegate()) {
+    LayoutTestRenderThreadObserver::GetInstance()->SetTestDelegate(
         test_runner);
   }
-  proxy->set_view_test_client(LayoutTestRenderProcessObserver::GetInstance()
+  proxy->set_view_test_client(LayoutTestRenderThreadObserver::GetInstance()
                                   ->test_interfaces()
                                   ->CreateWebViewTestClient(proxy));
   proxy->SetInterfaces(
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces());
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces());
 }
 
 void WebFrameTestProxyCreated(RenderFrame* render_frame,
                               test_runner::WebFrameTestProxyBase* proxy) {
-  proxy->set_test_client(LayoutTestRenderProcessObserver::GetInstance()
+  proxy->set_test_client(LayoutTestRenderThreadObserver::GetInstance()
                              ->test_interfaces()
                              ->CreateWebFrameTestClient());
 }
@@ -85,7 +85,7 @@
 
 void LayoutTestContentRendererClient::RenderThreadStarted() {
   ShellContentRendererClient::RenderThreadStarted();
-  shell_observer_.reset(new LayoutTestRenderProcessObserver());
+  shell_observer_.reset(new LayoutTestRenderThreadObserver());
 }
 
 void LayoutTestContentRendererClient::RenderFrameCreated(
@@ -104,15 +104,15 @@
   BlinkTestRunner* test_runner = BlinkTestRunner::Get(render_view);
   test_runner->Reset(false /* for_new_test */);
 
-  LayoutTestRenderProcessObserver::GetInstance()
+  LayoutTestRenderThreadObserver::GetInstance()
       ->test_interfaces()
       ->TestRunner()
       ->InitializeWebViewWithMocks(render_view->GetWebView());
 
   test_runner::WebTestDelegate* delegate =
-      LayoutTestRenderProcessObserver::GetInstance()->test_delegate();
+      LayoutTestRenderThreadObserver::GetInstance()->test_delegate();
   if (delegate == static_cast<test_runner::WebTestDelegate*>(test_runner))
-    LayoutTestRenderProcessObserver::GetInstance()->SetMainWindow(render_view);
+    LayoutTestRenderThreadObserver::GetInstance()->SetMainWindow(render_view);
 }
 
 WebMediaStreamCenter*
@@ -120,7 +120,7 @@
     WebMediaStreamCenterClient* client) {
 #if defined(ENABLE_WEBRTC)
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   return interfaces->CreateMediaStreamCenter(client);
 #else
   return NULL;
@@ -132,7 +132,7 @@
     WebRTCPeerConnectionHandlerClient* client) {
 #if defined(ENABLE_WEBRTC)
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   return interfaces->CreateWebRTCPeerConnectionHandler(client);
 #else
   return NULL;
@@ -143,7 +143,7 @@
 LayoutTestContentRendererClient::OverrideCreateMIDIAccessor(
     WebMIDIAccessorClient* client) {
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   return interfaces->CreateMIDIAccessor(client);
 }
 
@@ -151,7 +151,7 @@
 LayoutTestContentRendererClient::OverrideCreateAudioDevice(
     double sample_rate) {
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   return interfaces->CreateAudioDevice(sample_rate);
 }
 
@@ -162,7 +162,7 @@
 }
 
 WebThemeEngine* LayoutTestContentRendererClient::OverrideThemeEngine() {
-  return LayoutTestRenderProcessObserver::GetInstance()
+  return LayoutTestRenderThreadObserver::GetInstance()
       ->test_interfaces()
       ->ThemeEngine();
 }
@@ -171,7 +171,7 @@
 LayoutTestContentRendererClient::CreateAppBannerClient(
     RenderFrame* render_frame) {
   test_runner::WebTestInterfaces* interfaces =
-      LayoutTestRenderProcessObserver::GetInstance()->test_interfaces();
+      LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
   return interfaces->CreateAppBannerClient();
 }
 
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.h b/content/shell/renderer/layout_test/layout_test_content_renderer_client.h
index b7bc9bb2..2c1bdce1 100644
--- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.h
+++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.h
@@ -11,7 +11,7 @@
 
 namespace content {
 
-class LayoutTestRenderProcessObserver;
+class LayoutTestRenderThreadObserver;
 class MockWebClipboardImpl;
 
 class LayoutTestContentRendererClient : public ShellContentRendererClient {
@@ -38,7 +38,7 @@
       override;
 
  private:
-  std::unique_ptr<LayoutTestRenderProcessObserver> shell_observer_;
+  std::unique_ptr<LayoutTestRenderThreadObserver> shell_observer_;
   std::unique_ptr<MockWebClipboardImpl> clipboard_;
 };
 
diff --git a/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc b/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc
index 8fa6569d..14bc812 100644
--- a/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc
+++ b/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc
@@ -11,7 +11,7 @@
 #include "content/public/renderer/render_frame.h"
 #include "content/shell/common/shell_messages.h"
 #include "content/shell/renderer/layout_test/blink_test_runner.h"
-#include "content/shell/renderer/layout_test/layout_test_render_process_observer.h"
+#include "content/shell/renderer/layout_test/layout_test_render_thread_observer.h"
 #include "ipc/ipc_message_macros.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 
@@ -21,7 +21,7 @@
     RenderFrame* render_frame)
     : RenderFrameObserver(render_frame) {
   render_frame->GetWebFrame()->setContentSettingsClient(
-      LayoutTestRenderProcessObserver::GetInstance()
+      LayoutTestRenderThreadObserver::GetInstance()
           ->test_interfaces()
           ->TestRunner()
           ->GetWebContentSettings());
@@ -46,7 +46,7 @@
 
 void LayoutTestRenderFrameObserver::OnLayoutDumpRequest() {
   std::string dump =
-      LayoutTestRenderProcessObserver::GetInstance()
+      LayoutTestRenderThreadObserver::GetInstance()
           ->test_interfaces()
           ->TestRunner()
           ->DumpLayout(render_frame()->GetWebFrame());
@@ -55,7 +55,7 @@
 
 void LayoutTestRenderFrameObserver::OnReplicateLayoutTestRuntimeFlagsChanges(
     const base::DictionaryValue& changed_layout_test_runtime_flags) {
-  LayoutTestRenderProcessObserver::GetInstance()
+  LayoutTestRenderThreadObserver::GetInstance()
       ->test_interfaces()
       ->TestRunner()
       ->ReplicateLayoutTestRuntimeFlagsChanges(
@@ -66,7 +66,7 @@
     const ShellTestConfiguration& test_config,
     const base::DictionaryValue&
         accumulated_layout_test_runtime_flags_changes) {
-  LayoutTestRenderProcessObserver::GetInstance()
+  LayoutTestRenderThreadObserver::GetInstance()
       ->main_test_runner()
       ->OnReplicateTestConfiguration(test_config);
 
@@ -76,7 +76,7 @@
 
 void LayoutTestRenderFrameObserver::OnSetTestConfiguration(
     const ShellTestConfiguration& test_config) {
-  LayoutTestRenderProcessObserver::GetInstance()
+  LayoutTestRenderThreadObserver::GetInstance()
       ->main_test_runner()
       ->OnSetTestConfiguration(test_config);
 }
diff --git a/content/shell/renderer/layout_test/layout_test_render_process_observer.cc b/content/shell/renderer/layout_test/layout_test_render_thread_observer.cc
similarity index 80%
rename from content/shell/renderer/layout_test/layout_test_render_process_observer.cc
rename to content/shell/renderer/layout_test/layout_test_render_thread_observer.cc
index 0ca01490..5974f33 100644
--- a/content/shell/renderer/layout_test/layout_test_render_process_observer.cc
+++ b/content/shell/renderer/layout_test/layout_test_render_thread_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/shell/renderer/layout_test/layout_test_render_process_observer.h"
+#include "content/shell/renderer/layout_test/layout_test_render_thread_observer.h"
 
 #include "base/command_line.h"
 #include "components/test_runner/event_sender.h"
@@ -27,16 +27,16 @@
 namespace content {
 
 namespace {
-LayoutTestRenderProcessObserver* g_instance = NULL;
+LayoutTestRenderThreadObserver* g_instance = NULL;
 }
 
 // static
-LayoutTestRenderProcessObserver*
-LayoutTestRenderProcessObserver::GetInstance() {
+LayoutTestRenderThreadObserver*
+LayoutTestRenderThreadObserver::GetInstance() {
   return g_instance;
 }
 
-LayoutTestRenderProcessObserver::LayoutTestRenderProcessObserver()
+LayoutTestRenderThreadObserver::LayoutTestRenderThreadObserver()
     : main_test_runner_(NULL),
       test_delegate_(NULL) {
   CHECK(!g_instance);
@@ -66,31 +66,31 @@
   }
 }
 
-LayoutTestRenderProcessObserver::~LayoutTestRenderProcessObserver() {
+LayoutTestRenderThreadObserver::~LayoutTestRenderThreadObserver() {
   CHECK(g_instance == this);
   g_instance = NULL;
 }
 
-void LayoutTestRenderProcessObserver::SetTestDelegate(
+void LayoutTestRenderThreadObserver::SetTestDelegate(
     test_runner::WebTestDelegate* delegate) {
   test_interfaces_->SetDelegate(delegate);
   test_delegate_ = delegate;
 }
 
-void LayoutTestRenderProcessObserver::SetMainWindow(RenderView* view) {
+void LayoutTestRenderThreadObserver::SetMainWindow(RenderView* view) {
   BlinkTestRunner* test_runner = BlinkTestRunner::Get(view);
   test_interfaces_->SetWebView(view->GetWebView(), test_runner->proxy());
   main_test_runner_ = test_runner;
 }
 
-void LayoutTestRenderProcessObserver::OnRenderProcessShutdown() {
+void LayoutTestRenderThreadObserver::OnRenderProcessShutdown() {
   test_interfaces_.reset();
 }
 
-bool LayoutTestRenderProcessObserver::OnControlMessageReceived(
+bool LayoutTestRenderThreadObserver::OnControlMessageReceived(
     const IPC::Message& message) {
   bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(LayoutTestRenderProcessObserver, message)
+  IPC_BEGIN_MESSAGE_MAP(LayoutTestRenderThreadObserver, message)
     IPC_MESSAGE_HANDLER(ShellViewMsg_SetWebKitSourceDir, OnSetWebKitSourceDir)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
@@ -98,7 +98,7 @@
   return handled;
 }
 
-void LayoutTestRenderProcessObserver::OnSetWebKitSourceDir(
+void LayoutTestRenderThreadObserver::OnSetWebKitSourceDir(
     const base::FilePath& webkit_source_dir) {
   webkit_source_dir_ = webkit_source_dir;
 }
diff --git a/content/shell/renderer/layout_test/layout_test_render_process_observer.h b/content/shell/renderer/layout_test/layout_test_render_thread_observer.h
similarity index 72%
rename from content/shell/renderer/layout_test/layout_test_render_process_observer.h
rename to content/shell/renderer/layout_test/layout_test_render_thread_observer.h
index fee241b..945a420 100644
--- a/content/shell/renderer/layout_test/layout_test_render_process_observer.h
+++ b/content/shell/renderer/layout_test/layout_test_render_thread_observer.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_SHELL_RENDERER_LAYOUT_TEST_LAYOUT_TEST_RENDER_PROCESS_OBSERVER_H_
-#define CONTENT_SHELL_RENDERER_LAYOUT_TEST_LAYOUT_TEST_RENDER_PROCESS_OBSERVER_H_
+#ifndef CONTENT_SHELL_RENDERER_LAYOUT_TEST_LAYOUT_TEST_RENDER_THREAD_OBSERVER_H_
+#define CONTENT_SHELL_RENDERER_LAYOUT_TEST_LAYOUT_TEST_RENDER_THREAD_OBSERVER_H_
 
 #include <memory>
 
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "ipc/ipc_platform_file.h"
 
 namespace blink {
@@ -27,17 +27,17 @@
 class RenderView;
 class BlinkTestRunner;
 
-class LayoutTestRenderProcessObserver : public RenderProcessObserver {
+class LayoutTestRenderThreadObserver : public RenderThreadObserver {
  public:
-  static LayoutTestRenderProcessObserver* GetInstance();
+  static LayoutTestRenderThreadObserver* GetInstance();
 
-  LayoutTestRenderProcessObserver();
-  ~LayoutTestRenderProcessObserver() override;
+  LayoutTestRenderThreadObserver();
+  ~LayoutTestRenderThreadObserver() override;
 
   void SetTestDelegate(test_runner::WebTestDelegate* delegate);
   void SetMainWindow(RenderView* view);
 
-  // RenderProcessObserver implementation.
+  // RenderThreadObserver implementation.
   void OnRenderProcessShutdown() override;
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
@@ -60,9 +60,9 @@
 
   base::FilePath webkit_source_dir_;
 
-  DISALLOW_COPY_AND_ASSIGN(LayoutTestRenderProcessObserver);
+  DISALLOW_COPY_AND_ASSIGN(LayoutTestRenderThreadObserver);
 };
 
 }  // namespace content
 
-#endif  // CONTENT_SHELL_RENDERER_LAYOUT_TEST_LAYOUT_TEST_RENDER_PROCESS_OBSERVER_H_
+#endif  // CONTENT_SHELL_RENDERER_LAYOUT_TEST_LAYOUT_TEST_RENDER_THREAD_OBSERVER_H_
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index c1d501ca..10c8b3d 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -5,7 +5,7 @@
 #include "content/shell/renderer/shell_content_renderer_client.h"
 
 #include "base/command_line.h"
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_render_thread_observer.h"
 #include "content/shell/renderer/shell_render_view_observer.h"
 #include "third_party/WebKit/public/web/WebView.h"
 #include "v8/include/v8.h"
@@ -22,7 +22,7 @@
 }
 
 void ShellContentRendererClient::RenderThreadStarted() {
-  web_cache_observer_.reset(new web_cache::WebCacheRenderProcessObserver());
+  web_cache_observer_.reset(new web_cache::WebCacheRenderThreadObserver());
 }
 
 void ShellContentRendererClient::RenderViewCreated(RenderView* render_view) {
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h
index 2e5e691a..d715f218 100644
--- a/content/shell/renderer/shell_content_renderer_client.h
+++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -11,7 +11,7 @@
 #include "content/public/renderer/content_renderer_client.h"
 
 namespace web_cache {
-class WebCacheRenderProcessObserver;
+class WebCacheRenderThreadObserver;
 }
 
 namespace content {
@@ -31,7 +31,7 @@
   bool IsPluginAllowedToUseDevChannelAPIs() override;
 
  private:
-  std::unique_ptr<web_cache::WebCacheRenderProcessObserver> web_cache_observer_;
+  std::unique_ptr<web_cache::WebCacheRenderThreadObserver> web_cache_observer_;
 };
 
 }  // namespace content
diff --git a/extensions/browser/api/display_source/display_source_apitestbase.cc b/extensions/browser/api/display_source/display_source_apitestbase.cc
index 7fa354d8..945a833 100644
--- a/extensions/browser/api/display_source/display_source_apitestbase.cc
+++ b/extensions/browser/api/display_source/display_source_apitestbase.cc
@@ -28,8 +28,8 @@
 
   const DisplaySourceSinkInfoList& last_found_sinks() const override;
 
-  const DisplaySourceConnectionDelegate::Connection* connection()
-      const override {
+  DisplaySourceConnectionDelegate::Connection* connection()
+      override {
     return (active_sink_ && active_sink_->state == SINK_STATE_CONNECTED)
                ? this
                : nullptr;
@@ -59,10 +59,10 @@
 
   std::string GetSinkAddress() const override;
 
-  void SendMessage(const std::string& message) const override;
+  void SendMessage(const std::string& message) override;
 
   void SetMessageReceivedCallback(
-      const StringCallback& callback) const override;
+      const StringCallback& callback) override;
 
  private:
   void AddSink(DisplaySourceSinkInfo sink,
@@ -73,13 +73,38 @@
 
   void NotifySinksUpdated();
 
-  mutable DisplaySourceSinkInfoList sinks_;
+  void EnqueueSinkMessage(std::string message);
+
+  void CheckSourceMessageContent(std::string pattern,
+                                 const std::string& message);
+
+  DisplaySourceSinkInfoList sinks_;
   DisplaySourceSinkInfo* active_sink_;
   std::map<int, std::pair<AuthenticationMethod, std::string>> auth_infos_;
+  StringCallback message_received_cb_;
+
+  struct Message {
+    enum Direction {
+      SourceToSink,
+      SinkToSource
+    };
+    std::string data;
+    Direction direction;
+
+    bool is_from_sink() const { return direction == SinkToSource; }
+    Message(const std::string& message_data, Direction direction)
+      : data(message_data), direction(direction) {}
+  };
+
+  std::list<Message> messages_list_;
+  std::string session_id_;
 };
 
 namespace {
 
+const size_t kSessionIdLength = 8;
+const char kSessionKey[] = "Session: ";
+
 DisplaySourceSinkInfo CreateSinkInfo(int id, const std::string& name) {
   DisplaySourceSinkInfo ptr;
   ptr.id = id;
@@ -89,9 +114,6 @@
   return ptr;
 }
 
-const char kWiFiDisplayStartSessionMessage[] =
-  "OPTIONS * RTSP/1.0\r\nCSeq: 1\r\nRequire: org.wfa.wfd1.0\r\n\r\n";
-
 scoped_ptr<KeyedService> CreateMockDelegate(content::BrowserContext* profile) {
   return make_scoped_ptr<KeyedService>(
     new MockDisplaySourceConnectionDelegate());
@@ -103,9 +125,110 @@
   DisplaySourceConnectionDelegateFactory::GetInstance()->SetTestingFactory(
     profile, &CreateMockDelegate);
 }
+namespace {
 
+// WiFi Display session RTSP messages patterns.
+
+const char kM1Message[] = "OPTIONS * RTSP/1.0\r\n"
+                          "CSeq: 1\r\n"
+                          "Require: org.wfa.wfd1.0\r\n\r\n";
+
+const char kM1MessageReply[] = "RTSP/1.0 200 OK\r\n"
+                               "CSeq:1\r\n"
+                               "Public: org.wfa.wfd1.0, "
+                               "GET_PARAMETER, SET_PARAMETER\r\n\r\n";
+
+const char kM2Message[] = "OPTIONS * RTSP/1.0\r\n"
+                          "CSeq: 2\r\n"
+                          "Require: org.wfa.wfd1.0\r\n\r\n";
+
+const char kM2MessageReply[] = "RTSP/1.0 200 OK\r\n"
+                               "CSeq: 2\r\n"
+                               "Public: org.wfa.wfd1.0, "
+                               "GET_PARAMETER, SET_PARAMETER, PLAY, PAUSE, "
+                               "SETUP, TEARDOWN\r\n\r\n";
+
+const char kM3Message[] = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"
+                          "CSeq: 2\r\n"
+                          "Content-Type: text/parameters\r\n"
+                          "Content-Length: 41\r\n\r\n"
+                          "wfd_video_formats\r\n"
+                          "wfd_client_rtp_ports\r\n";
+
+const char kM3MessageReply[] = "RTSP/1.0 200 OK\r\n"
+                               "CSeq: 2\r\n"
+                               "Content-Type: text/parameters\r\n"
+                               "Content-Length: 145\r\n\r\n"
+                               "wfd_video_formats: "
+                               "40 00 02 10 0001FFFF 1FFFFFFF 00000FFF 00 0000 "
+                               "0000 00 none none\r\n"
+                               "wfd_client_rtp_ports: RTP/AVP/UDP;"
+                               "unicast 41657 0 mode=play\r\n";
+
+const char kM4Message[] = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"
+                          "CSeq: 3\r\n"
+                          "Content-Type: text/parameters\r\n"
+                          "Content-Length: 209\r\n\r\n"
+                          "wfd_client_rtp_ports: "
+                          "RTP/AVP/UDP;unicast 41657 0 mode=play\r\n"
+                          "wfd_presentation_URL: "
+                          "rtsp://127.0.0.1/wfd1.0/streamid=0 none\r\n"
+                          "wfd_video_formats: "
+                          "00 00 02 10 00000001 00000000 00000000 00 0000 0000 "
+                          "00 none none\r\n";
+
+const char kM4MessageReply[] = "RTSP/1.0 200 OK\r\n"
+                               "CSeq: 3\r\n\r\n";
+
+const char kM5Message[] = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"
+                          "CSeq: 4\r\n"
+                          "Content-Type: text/parameters\r\n"
+                          "Content-Length: 27\r\n\r\n"
+                          "wfd_trigger_method: SETUP\r\n";
+
+const char kM5MessageReply[] = "RTSP/1.0 200 OK\r\n"
+                               "CSeq: 4\r\n\r\n";
+
+const char kM6Message[] = "SETUP rtsp://localhost/wfd1.0/streamid=0 "
+                          "RTSP/1.0\r\n"
+                          "CSeq: 3\r\n"
+                          "Transport: RTP/AVP/UDP;unicast;"
+                          "client_port=41657\r\n\r\n";
+
+const char kM6MessageReply[] = "RTSP/1.0 200 OK\r\n"
+                               "CSeq: 3\r\n"
+                               "Session: 00000000;timeout=60\r\n"
+                               "Transport: RTP/AVP/UDP;unicast;"
+                               "client_port=41657\r\n\r\n";
+
+const char kM7Message[] = "PLAY rtsp://localhost/wfd1.0/streamid=0 RTSP/1.0\r\n"
+                          "CSeq: 4\r\n"
+                          "Session: 00000000\r\n\r\n";
+
+const char kM7MessageReply[] = "RTSP/1.0 200 OK\r\n"
+                               "CSeq: 4\r\n\r\n";
+
+const char kM8Message[] = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"
+                          "CSeq: 5\r\n\r\n";
+} // namespace
 MockDisplaySourceConnectionDelegate::MockDisplaySourceConnectionDelegate()
     : active_sink_(nullptr) {
+  messages_list_.push_back(Message(kM1Message, Message::SourceToSink));
+  messages_list_.push_back(Message(kM1MessageReply, Message::SinkToSource));
+  messages_list_.push_back(Message(kM2Message, Message::SinkToSource));
+  messages_list_.push_back(Message(kM2MessageReply, Message::SourceToSink));
+  messages_list_.push_back(Message(kM3Message, Message::SourceToSink));
+  messages_list_.push_back(Message(kM3MessageReply, Message::SinkToSource));
+  messages_list_.push_back(Message(kM4Message, Message::SourceToSink));
+  messages_list_.push_back(Message(kM4MessageReply, Message::SinkToSource));
+  messages_list_.push_back(Message(kM5Message, Message::SourceToSink));
+  messages_list_.push_back(Message(kM5MessageReply, Message::SinkToSource));
+  messages_list_.push_back(Message(kM6Message, Message::SinkToSource));
+  messages_list_.push_back(Message(kM6MessageReply, Message::SourceToSink));
+  messages_list_.push_back(Message(kM7Message, Message::SinkToSource));
+  messages_list_.push_back(Message(kM7MessageReply, Message::SourceToSink));
+  messages_list_.push_back(Message(kM8Message, Message::SourceToSink));
+
   AddSink(CreateSinkInfo(1, "sink 1"), AUTHENTICATION_METHOD_PIN, "1234");
 }
 
@@ -188,12 +311,23 @@
 }
 
 void MockDisplaySourceConnectionDelegate::SendMessage(
-    const std::string& message) const {
-  ASSERT_STREQ(kWiFiDisplayStartSessionMessage, message.c_str());
+    const std::string& message) {
+  ASSERT_FALSE(messages_list_.empty());
+  ASSERT_FALSE(messages_list_.front().is_from_sink());
+
+  CheckSourceMessageContent(messages_list_.front().data, message);
+  messages_list_.pop_front();
+
+  while (!messages_list_.empty() && messages_list_.front().is_from_sink()) {
+    EnqueueSinkMessage(messages_list_.front().data);
+    messages_list_.pop_front();
+  }
 }
 
 void MockDisplaySourceConnectionDelegate::SetMessageReceivedCallback(
-    const StringCallback& callback) const {}
+    const StringCallback& callback) {
+  message_received_cb_ = callback;
+}
 
 void MockDisplaySourceConnectionDelegate::AddSink(
     DisplaySourceSinkInfo sink,
@@ -215,4 +349,38 @@
                     OnSinksUpdated(sinks_));
 }
 
+void MockDisplaySourceConnectionDelegate::
+EnqueueSinkMessage(std::string message) {
+  const std::size_t found = message.find(kSessionKey);
+  if (found != std::string::npos) {
+    const std::size_t session_id_pos = found +
+        std::char_traits<char>::length(kSessionKey);
+    message.replace(session_id_pos, kSessionIdLength, session_id_);
+  }
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE, base::Bind(message_received_cb_, message));
+}
+
+void MockDisplaySourceConnectionDelegate::
+CheckSourceMessageContent(std::string pattern,
+                          const std::string& message) {
+  // Message M6_reply from Source to Sink has a unique and random session id
+  // generated by Source. The id cannot be predicted and the session id should
+  // be extracted and added to the message pattern for assertion.
+  // The following code checks if messages include "Session" string.
+  // If not, assert the message normally.
+  // If yes, find the session id, add it to the pattern and to the sink message
+  // that has Session: substring inside.
+  const std::size_t found = message.find(kSessionKey);
+
+  if (found != std::string::npos) {
+    const std::size_t session_id_pos = found +
+        std::char_traits<char>::length(kSessionKey);
+    session_id_ = message.substr(session_id_pos, kSessionIdLength);
+
+    pattern.replace(session_id_pos, kSessionIdLength, session_id_);
+  }
+  ASSERT_EQ(pattern, message);
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/api/display_source/display_source_connection_delegate.h b/extensions/browser/api/display_source/display_source_connection_delegate.h
index 74cf844..a589e704 100644
--- a/extensions/browser/api/display_source/display_source_connection_delegate.h
+++ b/extensions/browser/api/display_source/display_source_connection_delegate.h
@@ -41,14 +41,14 @@
 
     // Sends a control message to the connected sink.
     // If an error occurs 'Observer::OnConnectionError' is invoked.
-    virtual void SendMessage(const std::string& message) const = 0;
+    virtual void SendMessage(const std::string& message) = 0;
 
     // Sets a callback to receive control messages from the connected sink.
     // This method should only be called once in the lifetime of each
     // Connection object.
     // If an error occurs 'Observer::OnConnectionError' is invoked.
     virtual void SetMessageReceivedCallback(
-        const StringCallback& callback) const = 0;
+        const StringCallback& callback) = 0;
 
    protected:
     Connection();
@@ -90,7 +90,7 @@
 
   // Returns the Connection object representing the current
   // connection to the sink or NULL if there is no current connection.
-  virtual const Connection* connection() const = 0;
+  virtual Connection* connection() = 0;
 
   // Queries the list of currently available sinks.
   virtual void GetAvailableSinks(const SinkInfoListCallback& sinks_callback,
diff --git a/extensions/renderer/dispatcher.h b/extensions/renderer/dispatcher.h
index 37ab0a31..c53b2add 100644
--- a/extensions/renderer/dispatcher.h
+++ b/extensions/renderer/dispatcher.h
@@ -18,7 +18,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/scoped_observer.h"
 #include "base/timer/timer.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "extensions/common/event_filter.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extensions_client.h"
@@ -67,7 +67,7 @@
 
 // Dispatches extension control messages sent to the renderer and stores
 // renderer extension related state.
-class Dispatcher : public content::RenderProcessObserver,
+class Dispatcher : public content::RenderThreadObserver,
                    public UserScriptSetManager::Observer {
  public:
   explicit Dispatcher(DispatcherDelegate* delegate);
@@ -153,7 +153,7 @@
   FRIEND_TEST_ALL_PREFIXES(RendererPermissionsPolicyDelegateTest,
                            CannotScriptWebstore);
 
-  // RenderProcessObserver implementation:
+  // RenderThreadObserver implementation:
   bool OnControlMessageReceived(const IPC::Message& message) override;
   void IdleNotification() override;
   void OnRenderProcessShutdown() override;
diff --git a/extensions/renderer/user_script_set.h b/extensions/renderer/user_script_set.h
index 128b33f..3ae7e1f 100644
--- a/extensions/renderer/user_script_set.h
+++ b/extensions/renderer/user_script_set.h
@@ -14,7 +14,6 @@
 #include "base/memory/scoped_vector.h"
 #include "base/memory/shared_memory.h"
 #include "base/observer_list.h"
-#include "content/public/renderer/render_process_observer.h"
 #include "extensions/common/user_script.h"
 
 class GURL;
diff --git a/extensions/renderer/user_script_set_manager.h b/extensions/renderer/user_script_set_manager.h
index 5cba81e..290a702 100644
--- a/extensions/renderer/user_script_set_manager.h
+++ b/extensions/renderer/user_script_set_manager.h
@@ -14,7 +14,7 @@
 #include "base/memory/linked_ptr.h"
 #include "base/memory/shared_memory.h"
 #include "base/observer_list.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/user_script.h"
 #include "extensions/renderer/user_script_set.h"
@@ -39,7 +39,7 @@
 //                         only programmatically-declared scripts, instantiated
 //                         when an extension first creates a declarative rule
 //                         that would, if triggered, request a script injection.
-class UserScriptSetManager : public content::RenderProcessObserver {
+class UserScriptSetManager : public content::RenderThreadObserver {
  public:
   // Like a UserScriptSet::Observer, but automatically subscribes to all sets
   // associated with the manager.
@@ -84,7 +84,7 @@
   // Map for per-extension sets that may be defined programmatically.
   typedef std::map<HostID, linked_ptr<UserScriptSet> > UserScriptSetMap;
 
-  // content::RenderProcessObserver implementation.
+  // content::RenderThreadObserver implementation.
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   UserScriptSet* GetProgrammaticScriptsByHostID(const HostID& host_id);
diff --git a/extensions/renderer/wake_event_page.h b/extensions/renderer/wake_event_page.h
index 48bfd4b..08b353b 100644
--- a/extensions/renderer/wake_event_page.h
+++ b/extensions/renderer/wake_event_page.h
@@ -14,7 +14,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
 #include "ipc/ipc_sync_message_filter.h"
 #include "v8/include/v8.h"
 
@@ -30,7 +30,7 @@
 //
 // Note, the function will do a round trip to the browser even if event page is
 // open. Any optimisation to prevent this must be at the JavaScript level.
-class WakeEventPage : public content::RenderProcessObserver {
+class WakeEventPage : public content::RenderThreadObserver {
  public:
   WakeEventPage();
   ~WakeEventPage() override;
@@ -92,7 +92,7 @@
   void MakeRequest(const std::string& extension_id,
                    const OnResponseCallback& on_response);
 
-  // content::RenderProcessObserver:
+  // content::RenderThreadObserver:
   bool OnControlMessageReceived(const IPC::Message& message) override;
 
   // OnControlMessageReceived handlers:
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index da3bb21..1b96799 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -57,6 +57,8 @@
     # TODO(hendrikw): Move egl out of gles2_conform_support.
     "gles2_conform_support/egl/config.cc",
     "gles2_conform_support/egl/config.h",
+    "gles2_conform_support/egl/context.cc",
+    "gles2_conform_support/egl/context.h",
     "gles2_conform_support/egl/display.cc",
     "gles2_conform_support/egl/display.h",
     "gles2_conform_support/egl/egl.cc",
@@ -64,6 +66,8 @@
     "gles2_conform_support/egl/surface.h",
     "gles2_conform_support/egl/test_support.cc",
     "gles2_conform_support/egl/test_support.h",
+    "gles2_conform_support/egl/thread_state.cc",
+    "gles2_conform_support/egl/thread_state.h",
   ]
 
   deps = [
@@ -71,6 +75,7 @@
     "//base",
     "//gpu/command_buffer/client:gles2_c_lib",
     "//gpu/command_buffer/client:gles2_implementation",
+    "//gpu/command_buffer/common:gles2_utils",
     "//ui/gl:gl",
   ]
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 27114203..4009773 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -594,6 +594,7 @@
                   const std::vector<int32_t>& attribs) override;
   void Destroy(bool have_context) override;
   void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
+  void ReleaseSurface() override;
   void ProduceFrontBuffer(const Mailbox& mailbox) override;
   bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
   void UpdateParentTextureInfo();
@@ -3711,6 +3712,7 @@
 // }  // anonymous namespace
 
 bool GLES2DecoderImpl::MakeCurrent() {
+  DCHECK(surface_);
   if (!context_.get())
     return false;
 
@@ -4268,11 +4270,22 @@
 void GLES2DecoderImpl::SetSurface(
     const scoped_refptr<gfx::GLSurface>& surface) {
   DCHECK(context_->IsCurrent(NULL));
-  DCHECK(surface_.get());
+  DCHECK(surface);
   surface_ = surface;
   RestoreCurrentFramebufferBindings();
 }
 
+void GLES2DecoderImpl::ReleaseSurface() {
+  if (!context_.get())
+    return;
+  if (WasContextLost()) {
+    DLOG(ERROR) << "  GLES2DecoderImpl: Trying to release lost context.";
+    return;
+  }
+  context_->ReleaseCurrent(surface_.get());
+  surface_ = nullptr;
+}
+
 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
   if (!offscreen_saved_color_texture_.get()) {
     LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 297b9cf..43e3492 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -159,6 +159,10 @@
   // Set the surface associated with the default FBO.
   virtual void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) = 0;
 
+  // Releases the surface associated with the GL context.
+  // The decoder should not be used until a new surface is set.
+  virtual void ReleaseSurface() = 0;
+
   virtual void ProduceFrontBuffer(const Mailbox& mailbox) = 0;
 
   // Resize an offscreen frame buffer.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 396f531a..636dc14e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -52,6 +52,7 @@
                     const std::vector<int32_t>& attribs));
   MOCK_METHOD1(Destroy, void(bool have_context));
   MOCK_METHOD1(SetSurface, void(const scoped_refptr<gfx::GLSurface>& surface));
+  MOCK_METHOD0(ReleaseSurface, void());
   MOCK_METHOD1(ProduceFrontBuffer, void(const Mailbox& mailbox));
   MOCK_METHOD1(ResizeOffscreenFrameBuffer, bool(const gfx::Size& size));
   MOCK_METHOD0(MakeCurrent, bool());
diff --git a/gpu/command_buffer/tests/command_buffer_gles2_tests_main.cc b/gpu/command_buffer/tests/command_buffer_gles2_tests_main.cc
index f945390..6fda0631 100644
--- a/gpu/command_buffer/tests/command_buffer_gles2_tests_main.cc
+++ b/gpu/command_buffer/tests/command_buffer_gles2_tests_main.cc
@@ -9,8 +9,8 @@
 #endif
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
-#include "gpu/gles2_conform_support/egl/test_support.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "gpu/gles2_conform_support/egl/test_support.h"  // NOLINT
 
 // This file implements the main entry point for tests for command_buffer_gles2,
 // the mode of command buffer where the code is compiled as a standalone dynamic
diff --git a/gpu/command_buffer/tests/egl_test.cc b/gpu/command_buffer/tests/egl_test.cc
index bf7e30e5..e6bf4a9 100644
--- a/gpu/command_buffer/tests/egl_test.cc
+++ b/gpu/command_buffer/tests/egl_test.cc
@@ -6,31 +6,610 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+#include "base/bind.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "gpu/gles2_conform_support/egl/test_support.h"
 
 // This file tests EGL basic interface for command_buffer_gles2, the mode of
 // command buffer where the code is compiled as a standalone dynamic library and
 // exposed through EGL API.
 namespace gpu {
 
-using testing::Test;
+class EGLTest : public testing::Test {
+ public:
+  void TearDown() override;
+};
 
-TEST_F(Test, BasicEGLInitialization) {
+void EGLTest::TearDown() {
+  EXPECT_TRUE(eglReleaseThread());
+}
+
+TEST_F(EGLTest, OnlyReleaseThread) {}
+
+TEST_F(EGLTest, GetDisplay) {
+  EGLDisplay display1 = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_NE(display1, EGL_NO_DISPLAY);
+
+  EGLDisplay display2 = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_EQ(display1, display2);
+
+  EGLNativeDisplayType invalid_display_type =
+      reinterpret_cast<EGLNativeDisplayType>(0x1);
+  EXPECT_NE(invalid_display_type, EGL_DEFAULT_DISPLAY);
+  EXPECT_EQ(EGL_NO_DISPLAY, eglGetDisplay(invalid_display_type));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  // eglTerminate can be called with uninitialized display.
+  EXPECT_TRUE(eglTerminate(display1));
+}
+
+TEST_F(EGLTest, GetError) {
+  // GetError returns success.
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  // "calling eglGetError twice without any other intervening EGL calls will
+  // always return EGL_SUCCESS on the second call"
   EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  ASSERT_NE(display, EGL_NO_DISPLAY);
+  EXPECT_NE(display, EGL_NO_DISPLAY);
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+  EXPECT_EQ(nullptr, eglQueryString(display, EGL_EXTENSIONS));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  EXPECT_TRUE(eglTerminate(display));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+}
+
+TEST_F(EGLTest, Initialize) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_NE(display, EGL_NO_DISPLAY);
 
   // Test for no crash even though passing nullptrs for major, minor.
-  EGLBoolean success = eglInitialize(display, nullptr, nullptr);
-  ASSERT_TRUE(success);
+  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
 
   EGLint major = 0;
   EGLint minor = 0;
-  success = eglInitialize(display, &major, &minor);
-  ASSERT_TRUE(success);
-  ASSERT_EQ(major, 1);
-  ASSERT_EQ(minor, 4);
+  EXPECT_TRUE(eglInitialize(display, &major, &minor));
+  EXPECT_EQ(major, 1);
+  EXPECT_EQ(minor, 4);
 
-  success = eglTerminate(display);
-  ASSERT_TRUE(success);
+  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
+  EXPECT_FALSE(eglInitialize(invalid_display, nullptr, nullptr));
+  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
+}
+
+TEST_F(EGLTest, Terminate) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_NE(display, EGL_NO_DISPLAY);
+
+  // eglTerminate can be called multiple times without initialization.
+  EXPECT_TRUE(eglTerminate(display));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+  EXPECT_TRUE(eglTerminate(display));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
+
+  // eglTerminate can be called multiple times.
+  EXPECT_TRUE(eglTerminate(display));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+  EXPECT_TRUE(eglTerminate(display));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  // After Terminate, an egl call returns not initialized.
+  EXPECT_EQ(nullptr, eglQueryString(display, EGL_EXTENSIONS));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+
+  // Re-initialization of same display.
+  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
+  EXPECT_NE(nullptr, eglQueryString(display, EGL_EXTENSIONS));
+  EXPECT_TRUE(eglTerminate(display));
+
+  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
+  EXPECT_FALSE(eglTerminate(invalid_display));
+  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
+}
+
+TEST_F(EGLTest, QueryString) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_NE(display, EGL_NO_DISPLAY);
+  EXPECT_EQ(nullptr, eglQueryString(display, EGL_EXTENSIONS));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+  EXPECT_STREQ("", eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
+
+  EXPECT_EQ(nullptr, eglQueryString(display, EGL_VERSION));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+  EXPECT_STREQ("1.4", eglQueryString(EGL_NO_DISPLAY, EGL_VERSION));
+
+  EXPECT_EQ(nullptr, eglQueryString(display, EGL_CLIENT_APIS));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+  EXPECT_EQ(nullptr, eglQueryString(EGL_NO_DISPLAY, EGL_CLIENT_APIS));
+  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
+  EXPECT_EQ(nullptr, eglQueryString(display, EGL_VENDOR));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+  EXPECT_EQ(nullptr, eglQueryString(EGL_NO_DISPLAY, EGL_VENDOR));
+  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
+
+  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  EXPECT_STREQ("", eglQueryString(display, EGL_EXTENSIONS));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+  EXPECT_STREQ("1.4", eglQueryString(display, EGL_VERSION));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+  EXPECT_STREQ("OpenGL_ES", eglQueryString(display, EGL_CLIENT_APIS));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+  EXPECT_STREQ("Google Inc.", eglQueryString(display, EGL_VENDOR));
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+}
+
+TEST_F(EGLTest, GetConfigsUninitialized) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_NE(display, EGL_NO_DISPLAY);
+
+  EGLint num_config = 0;
+  const int kConfigsSize = 5;
+  EGLConfig configs[kConfigsSize] = {
+      0,
+  };
+
+  EXPECT_FALSE(eglGetConfigs(display, configs, kConfigsSize, &num_config));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+
+  EXPECT_FALSE(eglGetConfigs(display, configs, kConfigsSize, nullptr));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+}
+
+TEST_F(EGLTest, ChooseConfigUninitialized) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_NE(display, EGL_NO_DISPLAY);
+
+  EGLint num_config = 0;
+  EGLint attrib_list[] = {EGL_NONE};
+  const int kConfigsSize = 5;
+  EGLConfig configs[kConfigsSize] = {
+      0,
+  };
+
+  EXPECT_FALSE(eglChooseConfig(display, attrib_list, configs, kConfigsSize,
+                               &num_config));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+
+  EXPECT_FALSE(
+      eglChooseConfig(display, attrib_list, configs, kConfigsSize, nullptr));
+  EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
+}
+
+class EGLConfigTest : public EGLTest {
+ public:
+  void SetUp() override;
+
+ protected:
+  void CheckConfigsExist(EGLint num_config);
+
+  enum { kConfigsSize = 5 };
+  EGLDisplay display_;
+  EGLConfig configs_[kConfigsSize];
+};
+
+void EGLConfigTest::SetUp() {
+  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  ASSERT_NE(display_, EGL_NO_DISPLAY);
+  EXPECT_TRUE(eglInitialize(display_, nullptr, nullptr));
+  memset(configs_, 0, sizeof(configs_));
+}
+
+void EGLConfigTest::CheckConfigsExist(EGLint num_config) {
+  EGLint i;
+  if (num_config > kConfigsSize)
+    num_config = static_cast<EGLint>(kConfigsSize);
+  for (i = 0; i < num_config; ++i)
+    EXPECT_NE(nullptr, configs_[i]);
+  for (; i < kConfigsSize; ++i)
+    EXPECT_EQ(nullptr, configs_[i]);
+}
+
+TEST_F(EGLConfigTest, GetConfigsBadNumConfigs) {
+  EXPECT_FALSE(eglGetConfigs(display_, configs_, kConfigsSize, nullptr));
+  EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
+}
+
+TEST_F(EGLConfigTest, GetConfigsNullConfigs) {
+  EGLint num_config = 0;
+  EXPECT_TRUE(eglGetConfigs(display_, nullptr, 55, &num_config));
+  EXPECT_GT(num_config, 0);
+}
+
+TEST_F(EGLConfigTest, GetConfigsZeroConfigsSize) {
+  EGLint num_config = 0;
+  EXPECT_TRUE(eglGetConfigs(display_, configs_, 0, &num_config));
+  EXPECT_GT(num_config, 0);
+  EXPECT_EQ(nullptr, configs_[0]);
+}
+
+TEST_F(EGLConfigTest, GetConfigs) {
+  EGLint num_config = 0;
+  EXPECT_TRUE(eglGetConfigs(display_, configs_, kConfigsSize, &num_config));
+  EXPECT_GT(num_config, 0);
+  CheckConfigsExist(num_config);
+}
+
+TEST_F(EGLConfigTest, ChooseConfigBadNumConfigs) {
+  EGLint attrib_list[] = {EGL_NONE};
+  EXPECT_FALSE(
+      eglChooseConfig(display_, attrib_list, configs_, kConfigsSize, nullptr));
+  EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
+}
+
+TEST_F(EGLConfigTest, ChooseConfigNullConfigs) {
+  EGLint num_config = 0;
+  EGLint attrib_list[] = {EGL_NONE};
+  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, nullptr, 55, &num_config));
+  EXPECT_GT(num_config, 0);
+}
+
+TEST_F(EGLConfigTest, ChooseConfigZeroConfigsSize) {
+  EGLint num_config = 0;
+  EGLint attrib_list[] = {EGL_NONE};
+  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, 0, &num_config));
+  EXPECT_GT(num_config, 0);
+  EXPECT_EQ(nullptr, configs_[0]);
+}
+
+TEST_F(EGLConfigTest, ChooseConfig) {
+  EGLint num_config = 0;
+  EGLint attrib_list[] = {EGL_NONE};
+  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
+                              &num_config));
+  EXPECT_GT(num_config, 0);
+  CheckConfigsExist(num_config);
+}
+
+TEST_F(EGLConfigTest, ChooseConfigInvalidAttrib) {
+  const EGLint kNotModified = 55;
+  EGLint num_config = kNotModified;
+  EGLint invalid_attrib_list[] = {0xABCD};
+  EXPECT_FALSE(eglChooseConfig(display_, invalid_attrib_list, configs_,
+                               kConfigsSize, &num_config));
+  EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+  EXPECT_EQ(kNotModified, num_config);
+}
+
+TEST_F(EGLConfigTest, ChooseConfigWindow) {
+  EGLint num_config = 0;
+  EGLint attrib_list[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE};
+  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
+                              &num_config));
+  EXPECT_GT(num_config, 0);
+  for (int i = 0; i < num_config; ++i) {
+    EGLint value = EGL_NONE;
+    eglGetConfigAttrib(display_, configs_[i], EGL_SURFACE_TYPE, &value);
+    EXPECT_NE(0, value & EGL_WINDOW_BIT);
+  }
+}
+
+TEST_F(EGLConfigTest, ChooseConfigPBuffer) {
+  EGLint num_config = 0;
+  EGLint attrib_list[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_NONE};
+  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
+                              &num_config));
+  EXPECT_GT(num_config, 0);
+  for (int i = 0; i < num_config; ++i) {
+    EGLint value = EGL_NONE;
+    eglGetConfigAttrib(display_, configs_[0], EGL_SURFACE_TYPE, &value);
+    EXPECT_NE(0, value & EGL_PBUFFER_BIT);
+  }
+}
+
+TEST_F(EGLConfigTest, ChooseConfigWindowPBufferNotPossible) {
+  EGLint num_config = 0;
+  EGLint attrib_list[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
+                          EGL_NONE};
+  EXPECT_TRUE(eglChooseConfig(display_, attrib_list, configs_, kConfigsSize,
+                              &num_config));
+  EXPECT_EQ(0, num_config);
+}
+
+TEST_F(EGLConfigTest, ChooseConfigBugExample) {
+  static const EGLint kConfigAttribs[] = {
+      EGL_RED_SIZE,       8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE,    8,
+      EGL_ALPHA_SIZE,     8, EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
+      EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES,    4, EGL_NONE};
+  EGLint num_config = 0;
+  EXPECT_TRUE(eglChooseConfig(display_, kConfigAttribs, configs_, kConfigsSize,
+                              &num_config));
+
+  // The EGL attribs are not really implemented at the moment.
+  EGLint value = EGL_NONE;
+  EXPECT_TRUE(eglGetConfigAttrib(display_, configs_[0], EGL_RED_SIZE, &value));
+  EXPECT_EQ(0, value);
+}
+
+TEST_F(EGLTest, MakeCurrent) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_NE(display, EGL_NO_DISPLAY);
+  // "This is the only case where an uninitialized display may be passed to
+  //  eglMakeCurrent."
+  EXPECT_TRUE(
+      eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
+  EXPECT_FALSE(eglMakeCurrent(invalid_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                              EGL_NO_CONTEXT));
+  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
+
+  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
+  EXPECT_TRUE(
+      eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+  EXPECT_FALSE(eglMakeCurrent(invalid_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                              EGL_NO_CONTEXT));
+}
+
+class EGLSurfaceTest : public EGLTest {
+ public:
+  void SetUp() override;
+  void CreateSurfaceAndContext(EGLSurface* surface, EGLContext* context);
+
+ protected:
+  EGLDisplay display_;
+};
+
+void EGLSurfaceTest::SetUp() {
+  EGLTest::SetUp();
+  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_TRUE(eglInitialize(display_, nullptr, nullptr));
+}
+
+void EGLSurfaceTest::CreateSurfaceAndContext(EGLSurface* surface,
+                                             EGLContext* context) {
+  static const EGLint config_attribs[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+                                          EGL_NONE};
+  EGLint num_config;
+  EGLConfig config;
+  EXPECT_TRUE(
+      eglChooseConfig(display_, config_attribs, &config, 1, &num_config));
+  ASSERT_GT(num_config, 0);
+  static const EGLint surface_attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1,
+                                           EGL_NONE};
+  *surface = eglCreatePbufferSurface(display_, config, surface_attribs);
+  static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
+                                           EGL_NONE};
+  *context = eglCreateContext(display_, config, nullptr, context_attribs);
+}
+
+class EGLMultipleSurfacesContextsTest : public EGLSurfaceTest {
+ public:
+  void SetUp() override;
+  void TearDown() override;
+
+ protected:
+  EGLSurface surface1_;
+  EGLSurface surface2_;
+  EGLContext context1_;
+  EGLContext context2_;
+};
+
+void EGLMultipleSurfacesContextsTest::SetUp() {
+  EGLSurfaceTest::SetUp();
+  CreateSurfaceAndContext(&surface1_, &context1_);
+  CreateSurfaceAndContext(&surface2_, &context2_);
+  EXPECT_NE(EGL_NO_SURFACE, surface1_);
+  EXPECT_NE(EGL_NO_SURFACE, surface2_);
+  EXPECT_NE(surface1_, surface2_);
+  EXPECT_NE(EGL_NO_CONTEXT, context1_);
+  EXPECT_NE(EGL_NO_CONTEXT, context2_);
+  EXPECT_NE(context1_, context2_);
+}
+
+void EGLMultipleSurfacesContextsTest::TearDown() {
+  EXPECT_TRUE(eglDestroyContext(display_, context1_));
+  EXPECT_TRUE(eglDestroySurface(display_, surface1_));
+  EXPECT_TRUE(eglDestroyContext(display_, context2_));
+  EXPECT_TRUE(eglDestroySurface(display_, surface2_));
+  EGLTest::TearDown();
+}
+
+TEST_F(EGLMultipleSurfacesContextsTest, NoMakeCurrent) {}
+
+TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSurfaces) {
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context2_));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context1_));
+}
+
+TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSameSurface1) {
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context2_));
+}
+
+TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSameSurface2) {
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context1_));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
+}
+
+TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSurfacesAndReleases) {
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
+  EXPECT_TRUE(
+      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
+  EXPECT_TRUE(
+      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context2_));
+  EXPECT_TRUE(
+      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context1_));
+  EXPECT_TRUE(
+      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+}
+
+TEST_F(EGLMultipleSurfacesContextsTest, MakeCurrentSurfaceFails) {
+  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, surface1_, EGL_NO_CONTEXT));
+  EXPECT_EQ(EGL_BAD_CONTEXT, eglGetError());
+  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, EGL_NO_SURFACE, context1_));
+  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
+  EXPECT_FALSE(eglMakeCurrent(display_, EGL_NO_SURFACE, surface1_, context1_));
+  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
+
+  EGLDisplay invalid_display = reinterpret_cast<EGLDisplay>(0x1);
+  EGLSurface invalid_surface = reinterpret_cast<EGLSurface>(0x1);
+  EGLSurface invalid_context = reinterpret_cast<EGLContext>(0x1);
+  EXPECT_FALSE(
+      eglMakeCurrent(invalid_display, surface1_, surface1_, context1_));
+  EXPECT_EQ(EGL_BAD_DISPLAY, eglGetError());
+  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, surface1_, invalid_context));
+  EXPECT_EQ(EGL_BAD_CONTEXT, eglGetError());
+  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, invalid_surface, context1_));
+  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
+  EXPECT_FALSE(eglMakeCurrent(display_, invalid_surface, surface1_, context1_));
+  EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
+
+  // Command buffer limitation:
+  // Different read and draw surfaces fail.
+  EXPECT_FALSE(eglMakeCurrent(display_, surface1_, surface2_, context1_));
+  EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
+}
+
+TEST_F(EGLMultipleSurfacesContextsTest, CallGLOnMultipleContextNoCrash) {
+  EXPECT_TRUE(eglMakeCurrent(display_, surface1_, surface1_, context1_));
+
+  typedef void(GL_APIENTRY * glEnableProc)(GLenum);
+  glEnableProc glEnable =
+      reinterpret_cast<glEnableProc>(eglGetProcAddress("glEnable"));
+  EXPECT_NE(nullptr, glEnable);
+
+  glEnable(GL_BLEND);
+
+  EXPECT_TRUE(eglMakeCurrent(display_, surface2_, surface2_, context2_));
+  glEnable(GL_BLEND);
+}
+
+class EGLThreadTest : public EGLSurfaceTest {
+ public:
+  EGLThreadTest();
+  void SetUp() override;
+  void TearDown() override;
+  void OtherThreadTearDown(base::WaitableEvent*);
+  void OtherThreadMakeCurrent(EGLSurface surface,
+                              EGLContext context,
+                              EGLBoolean* result,
+                              base::WaitableEvent*);
+  void OtherThreadGetError(EGLint* result, base::WaitableEvent*);
+
+ protected:
+  base::Thread other_thread_;
+};
+
+EGLThreadTest::EGLThreadTest()
+    : EGLSurfaceTest(), other_thread_("EGLThreadTest thread") {}
+void EGLThreadTest::SetUp() {
+  EGLSurfaceTest::SetUp();
+  other_thread_.Start();
+}
+
+void EGLThreadTest::TearDown() {
+  base::WaitableEvent completion(true, false);
+  other_thread_.task_runner()->PostTask(
+      FROM_HERE, base::Bind(&EGLThreadTest::OtherThreadTearDown,
+                            base::Unretained(this), &completion));
+  completion.Wait();
+  other_thread_.Stop();
+  EGLSurfaceTest::TearDown();
+}
+
+void EGLThreadTest::OtherThreadTearDown(base::WaitableEvent* completion) {
+  EXPECT_TRUE(eglReleaseThread());
+  completion->Signal();
+}
+
+void EGLThreadTest::OtherThreadMakeCurrent(EGLSurface surface,
+                                           EGLContext context,
+                                           EGLBoolean* result,
+                                           base::WaitableEvent* completion) {
+  *result = eglMakeCurrent(display_, surface, surface, context);
+  completion->Signal();
+}
+
+void EGLThreadTest::OtherThreadGetError(EGLint* result,
+                                        base::WaitableEvent* completion) {
+  *result = eglGetError();
+  completion->Signal();
+}
+
+TEST_F(EGLThreadTest, OnlyReleaseThreadInOther) {}
+
+TEST_F(EGLThreadTest, Basic) {
+  EGLSurface surface;
+  EGLContext context;
+  CreateSurfaceAndContext(&surface, &context);
+  EXPECT_NE(EGL_NO_SURFACE, surface);
+  EXPECT_NE(EGL_NO_CONTEXT, context);
+
+  EXPECT_TRUE(eglMakeCurrent(display_, surface, surface, context));
+
+  base::WaitableEvent completion(false, false);
+
+  EGLBoolean result = EGL_FALSE;
+  other_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&EGLThreadTest::OtherThreadMakeCurrent, base::Unretained(this),
+                 surface, context, &result, &completion));
+  completion.Wait();
+  EXPECT_FALSE(result);
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  EGLint error = EGL_NONE;
+  other_thread_.task_runner()->PostTask(
+      FROM_HERE, base::Bind(&EGLThreadTest::OtherThreadGetError,
+                            base::Unretained(this), &error, &completion));
+  completion.Wait();
+  EXPECT_EQ(EGL_BAD_ACCESS, error);
+  EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+  other_thread_.task_runner()->PostTask(
+      FROM_HERE, base::Bind(&EGLThreadTest::OtherThreadGetError,
+                            base::Unretained(this), &error, &completion));
+  completion.Wait();
+  EXPECT_EQ(EGL_SUCCESS, error);
+
+  EXPECT_TRUE(
+      eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+
+  other_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&EGLThreadTest::OtherThreadMakeCurrent, base::Unretained(this),
+                 surface, context, &result, &completion));
+  completion.Wait();
+  EXPECT_TRUE(result);
+
+  EXPECT_FALSE(eglMakeCurrent(display_, surface, surface, context));
+  EXPECT_EQ(EGL_BAD_ACCESS, eglGetError());
+
+  EXPECT_TRUE(eglDestroySurface(display_, surface));
+  EXPECT_TRUE(eglDestroyContext(display_, context));
+}
+
+TEST_F(EGLTest, WindowlessNativeWindows) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EXPECT_TRUE(eglInitialize(display, nullptr, nullptr));
+
+  static const EGLint config_attribs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+                                          EGL_NONE};
+  EGLint num_config;
+  EGLConfig config;
+  EXPECT_TRUE(
+      eglChooseConfig(display, config_attribs, &config, 1, &num_config));
+  ASSERT_GT(num_config, 0);
+  static const EGLint surface_attribs[] = {EGL_NONE};
+  CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(display, 100, 100);
+  EGLNativeWindowType win = 0;
+  EGLSurface surface =
+      eglCreateWindowSurface(display, config, win, surface_attribs);
+  EXPECT_NE(EGL_NO_SURFACE, surface);
+  EXPECT_TRUE(eglDestroySurface(display, surface));
 }
 
 }  // namespace gpu
diff --git a/gpu/gles2_conform_support/egl/BUILD.gn b/gpu/gles2_conform_support/egl/BUILD.gn
index 556f053f..f11dd0ad 100644
--- a/gpu/gles2_conform_support/egl/BUILD.gn
+++ b/gpu/gles2_conform_support/egl/BUILD.gn
@@ -8,11 +8,17 @@
   sources = [
     "config.cc",
     "config.h",
+    "context.cc",
+    "context.h",
     "display.cc",
     "display.h",
     "egl.cc",
     "surface.cc",
     "surface.h",
+    "test_support.cc",
+    "test_support.h",
+    "thread_state.cc",
+    "thread_state.h",
   ]
 
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
@@ -28,6 +34,7 @@
     "//gpu:command_buffer_gles2",
     "//gpu/command_buffer/client:gles2_c_lib_nocheck",
     "//gpu/command_buffer/client:gles2_implementation_no_check",
+    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/command_buffer/service",
     "//ui/base",
     "//ui/gfx",
diff --git a/gpu/gles2_conform_support/egl/config.cc b/gpu/gles2_conform_support/egl/config.cc
index d6ce3072..53bd440d 100644
--- a/gpu/gles2_conform_support/egl/config.cc
+++ b/gpu/gles2_conform_support/egl/config.cc
@@ -3,10 +3,11 @@
 // found in the LICENSE file.
 
 #include "gpu/gles2_conform_support/egl/config.h"
+#include "base/logging.h"
 
 namespace egl {
 
-Config::Config()
+Config::Config(EGLint surface_type)
     : buffer_size_(0),
       red_size_(0),
       green_size_(0),
@@ -34,16 +35,37 @@
       sample_buffers_(0),
       samples_(0),
       stencil_size_(0),
-      surface_type_(EGL_WINDOW_BIT),
+      surface_type_(surface_type),
       transparent_type_(EGL_NONE),
       transparent_red_value_(EGL_DONT_CARE),
       transparent_green_value_(EGL_DONT_CARE),
       transparent_blue_value_(EGL_DONT_CARE) {
+  DCHECK(surface_type == EGL_WINDOW_BIT || surface_type == EGL_PBUFFER_BIT);
 }
 
 Config::~Config() {
 }
 
+bool Config::Matches(const EGLint* attrib_list) const {
+  DCHECK(ValidateAttributeList(attrib_list));
+  if (attrib_list) {
+    for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+      switch (attrib_list[i]) {
+        case EGL_SURFACE_TYPE: {
+          EGLint requested_surface_type = attrib_list[i + 1];
+          if (requested_surface_type != EGL_DONT_CARE &&
+              (requested_surface_type & surface_type_) !=
+                  requested_surface_type)
+            return false;
+        }
+        default:
+          break;
+      }
+    }
+  }
+  return true;
+}
+
 bool Config::GetAttrib(EGLint attribute, EGLint* value) const {
   // TODO(alokp): Find out how to get correct values.
   switch (attribute) {
@@ -149,4 +171,52 @@
   return true;
 }
 
+bool Config::ValidateAttributeList(const EGLint* attrib_list) {
+  if (attrib_list) {
+    for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+      switch (attrib_list[i]) {
+        case EGL_ALPHA_MASK_SIZE:
+        case EGL_ALPHA_SIZE:
+        case EGL_BIND_TO_TEXTURE_RGB:
+        case EGL_BIND_TO_TEXTURE_RGBA:
+        case EGL_BLUE_SIZE:
+        case EGL_BUFFER_SIZE:
+        case EGL_COLOR_BUFFER_TYPE:
+        case EGL_CONFIG_CAVEAT:
+        case EGL_CONFIG_ID:
+        case EGL_CONFORMANT:
+        case EGL_DEPTH_SIZE:
+        case EGL_GREEN_SIZE:
+        case EGL_LEVEL:
+        case EGL_LUMINANCE_SIZE:
+        case EGL_MATCH_NATIVE_PIXMAP:
+        case EGL_NATIVE_RENDERABLE:
+        case EGL_MAX_SWAP_INTERVAL:
+        case EGL_MIN_SWAP_INTERVAL:
+        case EGL_RED_SIZE:
+        case EGL_SAMPLE_BUFFERS:
+        case EGL_SAMPLES:
+        case EGL_STENCIL_SIZE:
+        case EGL_RENDERABLE_TYPE:
+        case EGL_SURFACE_TYPE:
+        case EGL_MULTISAMPLE_RESOLVE_BOX_BIT:
+        case EGL_PBUFFER_BIT:
+        case EGL_PIXMAP_BIT:
+        case EGL_SWAP_BEHAVIOR_PRESERVED_BIT:
+        case EGL_VG_ALPHA_FORMAT_PRE_BIT:
+        case EGL_VG_COLORSPACE_LINEAR_BIT:
+        case EGL_WINDOW_BIT:
+        case EGL_TRANSPARENT_TYPE:
+        case EGL_TRANSPARENT_RED_VALUE:
+        case EGL_TRANSPARENT_GREEN_VALUE:
+        case EGL_TRANSPARENT_BLUE_VALUE:
+          break;
+        default:
+          return false;
+      }
+    }
+  }
+  return true;
+}
+
 }  // namespace egl
diff --git a/gpu/gles2_conform_support/egl/config.h b/gpu/gles2_conform_support/egl/config.h
index 53bb568..1ce8156 100644
--- a/gpu/gles2_conform_support/egl/config.h
+++ b/gpu/gles2_conform_support/egl/config.h
@@ -13,10 +13,11 @@
 
 class Config {
  public:
-  Config();
+  explicit Config(EGLint surface_type);
   ~Config();
-
+  bool Matches(const EGLint* attrib_list) const;
   bool GetAttrib(EGLint attribute, EGLint* value) const;
+  static bool ValidateAttributeList(const EGLint* attrib_list);
 
  private:
   // Total color component bits in the color buffer.
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc
new file mode 100644
index 0000000..2f89b8e
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/context.cc
@@ -0,0 +1,398 @@
+// Copyright (c) 2016 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 "gpu/gles2_conform_support/egl/context.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/client/transfer_buffer.h"
+#include "gpu/command_buffer/common/value_state.h"
+#include "gpu/command_buffer/service/context_group.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/memory_tracking.h"
+#include "gpu/command_buffer/service/transfer_buffer_manager.h"
+#include "gpu/command_buffer/service/valuebuffer_manager.h"
+#include "gpu/gles2_conform_support/egl/config.h"
+#include "gpu/gles2_conform_support/egl/display.h"
+#include "gpu/gles2_conform_support/egl/surface.h"
+#include "gpu/gles2_conform_support/egl/thread_state.h"
+
+// The slight complexification in this file comes from following properties:
+// 1) Command buffer connection (context) can not be established without a
+// GLSurface. EGL Context can be created independent of a surface.  This is why
+// the connection is created only during first MakeCurrent.
+// 2) Command buffer MakeCurrent calls need the real gl context and surface be
+// current.
+// 3) Client can change real EGL context behind the scenes and then still expect
+// command buffer MakeCurrent re-set the command buffer context. This is why all
+// MakeCurrent calls must actually reset the real context, even though command
+// buffer current context does not change.
+// 4) EGL context can be destroyed without surface, but command buffer would
+// need the surface to run various cleanups. If context is destroyed
+// surfaceless, the context is marked lost before destruction. This is avoided
+// if possible, since command buffer at the time of writing prints out debug
+// text in this case.
+
+namespace {
+const int32_t kCommandBufferSize = 1024 * 1024;
+const int32_t kTransferBufferSize = 512 * 1024;
+const bool kBindGeneratesResources = true;
+const bool kLoseContextWhenOutOfMemory = false;
+const bool kSupportClientSideArrays = true;
+}
+
+namespace egl {
+Context::Context(Display* display, const Config* config)
+    : display_(display),
+      config_(config),
+      is_current_in_some_thread_(false),
+      is_destroyed_(false) {}
+
+Context::~Context() {
+  // We might not have a surface, so we must lose the context.  Cleanup will
+  // execute GL commands otherwise. TODO: if shared contexts are ever
+  // implemented, this will leak the GL resources. For pbuffer contexts, one
+  // could track the last current surface or create a surface for destroying
+  // purposes only. Other option would be to make the service usable without
+  // surface.
+  if (HasService()) {
+    if (!WasServiceContextLost())
+      MarkServiceContextLost();
+    DestroyService();
+  }
+}
+
+void Context::MarkDestroyed() {
+  is_destroyed_ = true;
+}
+
+void Context::FlushAndSwapBuffers(gfx::GLSurface* current_surface) {
+  DCHECK(HasService() && is_current_in_some_thread_);
+  if (!Flush(current_surface))
+    return;
+  current_surface->SwapBuffers();
+}
+
+bool Context::MakeCurrent(Context* current_context,
+                          gfx::GLSurface* current_surface,
+                          Context* new_context,
+                          gfx::GLSurface* new_surface) {
+  if (!new_context && !current_context) {
+    return true;
+  }
+
+  bool cleanup_old_current_context = false;
+  if (current_context) {
+    if (current_context->Flush(current_surface))
+      cleanup_old_current_context = new_context != current_context;
+  }
+
+  if (new_context) {
+    if (!new_context->IsCompatibleSurface(new_surface))
+      return false;
+
+    if (new_context->HasService()) {
+      if (new_context->WasServiceContextLost())
+        return false;
+      if (new_context != current_context) {
+        // If Flush did not set the current context, set it now. Otherwise
+        // calling into the decoder is not ok.
+        if (!new_context->gl_context_->MakeCurrent(new_surface)) {
+          new_context->MarkServiceContextLost();
+          return false;
+        }
+      }
+      if (new_context != current_context || new_surface != current_surface)
+        new_context->decoder_->SetSurface(new_surface);
+      if (!new_context->decoder_->MakeCurrent()) {
+        new_context->MarkServiceContextLost();
+        return false;
+      }
+    } else {
+      if (!new_context->CreateService(new_surface)) {
+        return false;
+      }
+    }
+  }
+
+  // The current_surface will be released when MakeCurrent succeeds.
+  // Cleanup in this case only.
+  if (cleanup_old_current_context) {
+    if (current_context->is_destroyed_ && current_surface != new_surface) {
+      current_context->gl_context_->MakeCurrent(current_surface);
+      // If we are releasing the context and we have one ref, it means that the
+      // ref will be lost and the object will be destroyed.  Destroy the service
+      // explicitly here, so that cleanup can happen and client GL
+      // implementation does not print errors.
+      current_context->DestroyService();
+    } else {
+      current_context->decoder_->ReleaseSurface();
+    }
+  }
+
+  return true;
+}
+
+bool Context::ValidateAttributeList(const EGLint* attrib_list) {
+  if (attrib_list) {
+    for (int i = 0; attrib_list[i] != EGL_NONE; attrib_list += 2) {
+      switch (attrib_list[i]) {
+        case EGL_CONTEXT_CLIENT_VERSION:
+          break;
+        default:
+          return false;
+      }
+    }
+  }
+  return true;
+}
+
+void Context::SetGpuControlClient(gpu::GpuControlClient*) {
+  // The client is not currently called, so don't store it.
+}
+
+gpu::Capabilities Context::GetCapabilities() {
+  return decoder_->GetCapabilities();
+}
+
+int32_t Context::CreateImage(ClientBuffer buffer,
+                             size_t width,
+                             size_t height,
+                             unsigned internalformat) {
+  NOTIMPLEMENTED();
+  return -1;
+}
+
+void Context::DestroyImage(int32_t id) {
+  NOTIMPLEMENTED();
+}
+
+int32_t Context::CreateGpuMemoryBufferImage(size_t width,
+                                            size_t height,
+                                            unsigned internalformat,
+                                            unsigned usage) {
+  NOTIMPLEMENTED();
+  return -1;
+}
+
+void Context::SignalQuery(uint32_t query, const base::Closure& callback) {
+  NOTIMPLEMENTED();
+}
+
+void Context::SetLock(base::Lock*) {
+  NOTIMPLEMENTED();
+}
+
+bool Context::IsGpuChannelLost() {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void Context::EnsureWorkVisible() {
+  // This is only relevant for out-of-process command buffers.
+}
+
+gpu::CommandBufferNamespace Context::GetNamespaceID() const {
+  return gpu::CommandBufferNamespace::IN_PROCESS;
+}
+
+gpu::CommandBufferId Context::GetCommandBufferID() const {
+  return gpu::CommandBufferId();
+}
+
+int32_t Context::GetExtraCommandBufferData() const {
+  return 0;
+}
+
+uint64_t Context::GenerateFenceSyncRelease() {
+  return display_->GenerateFenceSyncRelease();
+}
+
+bool Context::IsFenceSyncRelease(uint64_t release) {
+  return display_->IsFenceSyncRelease(release);
+}
+
+bool Context::IsFenceSyncFlushed(uint64_t release) {
+  return display_->IsFenceSyncFlushed(release);
+}
+
+bool Context::IsFenceSyncFlushReceived(uint64_t release) {
+  return display_->IsFenceSyncFlushReceived(release);
+}
+
+void Context::SignalSyncToken(const gpu::SyncToken& sync_token,
+                              const base::Closure& callback) {
+  NOTIMPLEMENTED();
+}
+
+bool Context::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) {
+  return false;
+}
+
+void Context::ApplyCurrentContext(gfx::GLSurface* current_surface) {
+  DCHECK(HasService());
+  // The current_surface will be the same as
+  // the surface of the decoder. We can not DCHECK as there is
+  // no accessor.
+  if (!WasServiceContextLost()) {
+    if (!gl_context_->MakeCurrent(current_surface))
+      MarkServiceContextLost();
+  }
+  gles2::SetGLContext(client_gl_context_.get());
+}
+
+void Context::ApplyContextReleased() {
+  gles2::SetGLContext(nullptr);
+}
+
+bool Context::CreateService(gfx::GLSurface* gl_surface) {
+  scoped_refptr<gpu::TransferBufferManager> transfer_buffer_manager(
+      new gpu::TransferBufferManager(nullptr));
+  transfer_buffer_manager->Initialize();
+
+  scoped_ptr<gpu::CommandBufferService> command_buffer(
+      new gpu::CommandBufferService(transfer_buffer_manager.get()));
+  if (!command_buffer->Initialize())
+    return false;
+
+  scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
+      gpu_preferences_, nullptr, nullptr,
+      new gpu::gles2::ShaderTranslatorCache(gpu_preferences_),
+      new gpu::gles2::FramebufferCompletenessCache, nullptr, nullptr, nullptr,
+      true));
+
+  scoped_ptr<gpu::gles2::GLES2Decoder> decoder(
+      gpu::gles2::GLES2Decoder::Create(group.get()));
+  if (!decoder.get())
+    return false;
+
+  scoped_ptr<gpu::CommandExecutor> command_executor(new gpu::CommandExecutor(
+      command_buffer.get(), decoder.get(), decoder.get()));
+
+  decoder->set_engine(command_executor.get());
+
+  scoped_refptr<gfx::GLContext> gl_context(gfx::GLContext::CreateGLContext(
+      nullptr, gl_surface, gfx::PreferDiscreteGpu));
+  if (!gl_context)
+    return false;
+
+  gl_context->MakeCurrent(gl_surface);
+
+  gpu::gles2::ContextCreationAttribHelper helper;
+  config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size);
+  config_->GetAttrib(EGL_BLUE_SIZE, &helper.blue_size);
+  config_->GetAttrib(EGL_GREEN_SIZE, &helper.green_size);
+  config_->GetAttrib(EGL_RED_SIZE, &helper.red_size);
+  config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size);
+  config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size);
+  config_->GetAttrib(EGL_SAMPLES, &helper.samples);
+  config_->GetAttrib(EGL_SAMPLE_BUFFERS, &helper.sample_buffers);
+
+  helper.buffer_preserved = false;
+  helper.bind_generates_resource = kBindGeneratesResources;
+  helper.fail_if_major_perf_caveat = false;
+  helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory;
+  helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2;
+  std::vector<int32_t> attribs;
+  helper.Serialize(&attribs);
+
+  if (!decoder->Initialize(gl_surface, gl_context.get(),
+                           gl_surface->IsOffscreen(), gl_surface->GetSize(),
+                           gpu::gles2::DisallowedFeatures(), attribs)) {
+    return false;
+  }
+
+  command_buffer->SetPutOffsetChangeCallback(
+      base::Bind(&gpu::CommandExecutor::PutChanged,
+                 base::Unretained(command_executor.get())));
+  command_buffer->SetGetBufferChangeCallback(
+      base::Bind(&gpu::CommandExecutor::SetGetBuffer,
+                 base::Unretained(command_executor.get())));
+
+  scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper(
+      new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
+  if (!gles2_cmd_helper->Initialize(kCommandBufferSize)) {
+    decoder->Destroy(true);
+    return false;
+  }
+
+  scoped_ptr<gpu::TransferBuffer> transfer_buffer(
+      new gpu::TransferBuffer(gles2_cmd_helper.get()));
+
+  gles2_cmd_helper_.reset(gles2_cmd_helper.release());
+  transfer_buffer_.reset(transfer_buffer.release());
+  command_buffer_.reset(command_buffer.release());
+  command_executor_.reset(command_executor.release());
+  decoder_.reset(decoder.release());
+  gl_context_ = gl_context.get();
+
+  scoped_ptr<gpu::gles2::GLES2Implementation> context(
+      new gpu::gles2::GLES2Implementation(
+          gles2_cmd_helper_.get(), nullptr, transfer_buffer_.get(),
+          kBindGeneratesResources, kLoseContextWhenOutOfMemory,
+          kSupportClientSideArrays, this));
+
+  if (!context->Initialize(kTransferBufferSize, kTransferBufferSize / 2,
+                           kTransferBufferSize * 2,
+                           gpu::gles2::GLES2Implementation::kNoLimit)) {
+    DestroyService();
+    return false;
+  }
+
+  context->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
+  context->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
+  client_gl_context_.reset(context.release());
+  return true;
+}
+
+void Context::DestroyService() {
+  DCHECK(HasService());
+  bool have_context = !WasServiceContextLost();
+  // The client gl interface might still be set to current global
+  // interface. This will be cleaned up in ApplyContextReleased
+  // with AutoCurrentContextRestore.
+  client_gl_context_.reset();
+  gl_context_ = nullptr;
+
+  transfer_buffer_.reset();
+  command_executor_.reset();
+  if (decoder_)
+    decoder_->Destroy(have_context);
+  gles2_cmd_helper_.reset();
+  command_buffer_.reset();
+}
+
+bool Context::HasService() const {
+  return decoder_ != nullptr;
+}
+
+void Context::MarkServiceContextLost() {
+  decoder_->MarkContextLost(gpu::error::kMakeCurrentFailed);
+}
+
+bool Context::WasServiceContextLost() const {
+  return decoder_->WasContextLost();
+}
+
+bool Context::IsCompatibleSurface(gfx::GLSurface* gl_surface) {
+  EGLint value = EGL_NONE;
+  config_->GetAttrib(EGL_SURFACE_TYPE, &value);
+  bool config_is_offscreen = (value & EGL_PBUFFER_BIT) != 0;
+  return gl_surface->IsOffscreen() == config_is_offscreen;
+}
+
+bool Context::Flush(gfx::GLSurface* gl_surface) {
+  if (WasServiceContextLost())
+    return false;
+  if (!gl_context_->MakeCurrent(gl_surface)) {
+    MarkServiceContextLost();
+    return false;
+  }
+  client_gl_context_->Flush();
+  return true;
+}
+
+}  // namespace egl
diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h
new file mode 100644
index 0000000..e07aaac5
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/context.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_GLES2_CONFORM_TEST_CONTEXT_H_
+#define GPU_GLES2_CONFORM_TEST_CONTEXT_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gpu_control.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/command_executor.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_surface.h"
+#include <EGL/egl.h>
+
+namespace gpu {
+class TransferBuffer;
+class TransferBufferManagerInterface;
+
+namespace gles2 {
+class GLES2CmdHelper;
+class GLES2Interface;
+}  // namespace gles2
+}  // namespace gpu
+
+namespace egl {
+class Display;
+class Surface;
+class Config;
+
+class Context : public base::RefCountedThreadSafe<Context>,
+                private gpu::GpuControl {
+ public:
+  Context(Display* display, const Config* config);
+  bool is_current_in_some_thread() const { return is_current_in_some_thread_; }
+  void set_is_current_in_some_thread(bool flag) {
+    is_current_in_some_thread_ = flag;
+  }
+  void MarkDestroyed();
+  void FlushAndSwapBuffers(gfx::GLSurface* current_surface);
+
+  static bool MakeCurrent(Context* current_context,
+                          gfx::GLSurface* current_surface,
+                          Context* new_context,
+                          gfx::GLSurface* new_surface);
+
+  static bool ValidateAttributeList(const EGLint* attrib_list);
+
+  // GpuControl implementation.
+  void SetGpuControlClient(gpu::GpuControlClient*) override;
+  gpu::Capabilities GetCapabilities() override;
+  int32_t CreateImage(ClientBuffer buffer,
+                      size_t width,
+                      size_t height,
+                      unsigned internalformat) override;
+  void DestroyImage(int32_t id) override;
+  int32_t CreateGpuMemoryBufferImage(size_t width,
+                                     size_t height,
+                                     unsigned internalformat,
+                                     unsigned usage) override;
+  void SignalQuery(uint32_t query, const base::Closure& callback) override;
+  void SetLock(base::Lock*) override;
+  bool IsGpuChannelLost() override;
+  void EnsureWorkVisible() override;
+  gpu::CommandBufferNamespace GetNamespaceID() const override;
+  gpu::CommandBufferId GetCommandBufferID() const override;
+  int32_t GetExtraCommandBufferData() const override;
+  uint64_t GenerateFenceSyncRelease() override;
+  bool IsFenceSyncRelease(uint64_t release) override;
+  bool IsFenceSyncFlushed(uint64_t release) override;
+  bool IsFenceSyncFlushReceived(uint64_t release) override;
+  void SignalSyncToken(const gpu::SyncToken& sync_token,
+                       const base::Closure& callback) override;
+  bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override;
+
+  // Called by ThreadState to set the needed global variables when this context
+  // is current.
+  void ApplyCurrentContext(gfx::GLSurface* current_surface);
+  static void ApplyContextReleased();
+
+ private:
+  friend class base::RefCountedThreadSafe<Context>;
+  ~Context() override;
+  bool CreateService(gfx::GLSurface* gl_surface);
+  void DestroyService();
+  // Returns true if the object has GL service, either a working one or one
+  // that has lost its GL context.
+  bool HasService() const;
+  void MarkServiceContextLost();
+  bool WasServiceContextLost() const;
+  bool IsCompatibleSurface(gfx::GLSurface* gl_surface);
+  bool Flush(gfx::GLSurface* gl_surface);
+
+  Display* display_;
+  const Config* config_;
+  bool is_current_in_some_thread_;
+  bool is_destroyed_;
+  gpu::GpuPreferences gpu_preferences_;
+  scoped_ptr<gpu::CommandBufferService> command_buffer_;
+  scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_;
+  scoped_ptr<gpu::gles2::GLES2Decoder> decoder_;
+  scoped_ptr<gpu::CommandExecutor> command_executor_;
+  scoped_ptr<gpu::TransferBuffer> transfer_buffer_;
+
+  scoped_refptr<gfx::GLContext> gl_context_;
+
+  scoped_ptr<gpu::gles2::GLES2Interface> client_gl_context_;
+  DISALLOW_COPY_AND_ASSIGN(Context);
+};
+
+}  // namespace egl
+
+#endif  // GPU_GLES2_CONFORM_TEST_CONTEXT_H_
diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc
index a19718b..2053f7d 100644
--- a/gpu/gles2_conform_support/egl/display.cc
+++ b/gpu/gles2_conform_support/egl/display.cc
@@ -4,133 +4,114 @@
 
 #include "gpu/gles2_conform_support/egl/display.h"
 
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/lazy_instance.h"
-#include "gpu/command_buffer/client/gles2_implementation.h"
-#include "gpu/command_buffer/client/gles2_lib.h"
-#include "gpu/command_buffer/client/transfer_buffer.h"
-#include "gpu/command_buffer/common/value_state.h"
-#include "gpu/command_buffer/service/context_group.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "gpu/command_buffer/service/memory_tracking.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
-#include "gpu/command_buffer/service/valuebuffer_manager.h"
 #include "gpu/gles2_conform_support/egl/config.h"
+#include "gpu/gles2_conform_support/egl/context.h"
 #include "gpu/gles2_conform_support/egl/surface.h"
-#include "gpu/gles2_conform_support/egl/test_support.h"
-
-namespace {
-const int32_t kCommandBufferSize = 1024 * 1024;
-const int32_t kTransferBufferSize = 512 * 1024;
-}
+#include "gpu/gles2_conform_support/egl/thread_state.h"
 
 namespace egl {
-#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
-// egl::Display is used for comformance tests and command_buffer_gles.  We only
-// need the exit manager for the command_buffer_gles library.
-// TODO(hendrikw): Find a cleaner solution for this.
-namespace {
-base::LazyInstance<base::Lock>::Leaky g_exit_manager_lock;
-int g_exit_manager_use_count;
-base::AtExitManager* g_exit_manager;
-void RefAtExitManager() {
-  base::AutoLock lock(g_exit_manager_lock.Get());
-#if defined(COMPONENT_BUILD)
-  if (g_command_buffer_gles_has_atexit_manager) {
-    return;
-  }
-#endif
-  if (g_exit_manager_use_count == 0) {
-    g_exit_manager = new base::AtExitManager;
-  }
-  ++g_exit_manager_use_count;
-}
-void ReleaseAtExitManager() {
-  base::AutoLock lock(g_exit_manager_lock.Get());
-#if defined(COMPONENT_BUILD)
-  if (g_command_buffer_gles_has_atexit_manager) {
-    return;
-  }
-#endif
-  --g_exit_manager_use_count;
-  if (g_exit_manager_use_count == 0) {
-    delete g_exit_manager;
-    g_exit_manager = nullptr;
-  }
-}
-}
-#endif
 
-Display::Display(EGLNativeDisplayType display_id)
-    : display_id_(display_id),
-      is_initialized_(false),
-      create_offscreen_(false),
-      create_offscreen_width_(0),
-      create_offscreen_height_(0),
-      next_fence_sync_release_(1) {
-#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
-  RefAtExitManager();
-#endif
-}
+Display::Display()
+    : is_initialized_(false),
+      next_create_window_surface_creates_pbuffer_(false),
+      window_surface_pbuffer_width_(0),
+      window_surface_pbuffer_height_(0) {}
 
 Display::~Display() {
-  gles2::Terminate();
-#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
-  ReleaseAtExitManager();
-#endif
+  surfaces_.clear();
+  contexts_.clear();
+}
+void Display::SetNextCreateWindowSurfaceCreatesPBuffer(EGLint width,
+                                                       EGLint height) {
+  next_create_window_surface_creates_pbuffer_ = true;
+  window_surface_pbuffer_width_ = width;
+  window_surface_pbuffer_height_ = height;
 }
 
-bool Display::Initialize() {
-  gles2::Initialize();
+EGLBoolean Display::Initialize(ThreadState* ts, EGLint* major, EGLint* minor) {
+  base::AutoLock auto_lock(lock_);
   is_initialized_ = true;
-  return true;
+
+  if (major)
+    *major = 1;
+  if (minor)
+    *minor = 4;
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
-bool Display::IsValidConfig(EGLConfig config) {
-  return (config != NULL) && (config == config_.get());
+EGLBoolean Display::Terminate(ThreadState* ts) {
+  base::AutoLock auto_lock(lock_);
+  is_initialized_ = false;
+  surfaces_.clear();
+  for (const auto& context : contexts_)
+    context->MarkDestroyed();
+  contexts_.clear();
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
-bool Display::ChooseConfigs(EGLConfig* configs,
-                            EGLint config_size,
-                            EGLint* num_config) {
-  // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
-  // does not support finding or choosing configs.
-  *num_config = 1;
-  if (configs != NULL) {
-    if (config_ == NULL) {
-      config_.reset(new Config);
-    }
-    configs[0] = config_.get();
+const char* Display::QueryString(ThreadState* ts, EGLint name) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError<const char*>(EGL_NOT_INITIALIZED, nullptr);
+  switch (name) {
+    case EGL_CLIENT_APIS:
+      return ts->ReturnSuccess("OpenGL_ES");
+    case EGL_EXTENSIONS:
+      return ts->ReturnSuccess("");
+    case EGL_VENDOR:
+      return ts->ReturnSuccess("Google Inc.");
+    case EGL_VERSION:
+      return ts->ReturnSuccess("1.4");
+    default:
+      return ts->ReturnError<const char*>(EGL_BAD_PARAMETER, nullptr);
   }
-  return true;
 }
 
-bool Display::GetConfigs(EGLConfig* configs,
-                         EGLint config_size,
-                         EGLint* num_config) {
-  // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
-  // does not support finding or choosing configs.
-  *num_config = 1;
-  if (configs != NULL) {
-    if (config_ == NULL) {
-      config_.reset(new Config);
+EGLBoolean Display::ChooseConfig(ThreadState* ts,
+                                 const EGLint* attrib_list,
+                                 EGLConfig* configs,
+                                 EGLint config_size,
+                                 EGLint* num_config) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
+  if (num_config == nullptr)
+    return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE);
+  if (!Config::ValidateAttributeList(attrib_list))
+    return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+  InitializeConfigsIfNeeded();
+  if (!configs)
+    config_size = 0;
+  *num_config = 0;
+  for (size_t i = 0; i < arraysize(configs_); ++i) {
+    if (configs_[i]->Matches(attrib_list)) {
+      if (*num_config < config_size) {
+        configs[*num_config] = configs_[i].get();
+      }
+      ++*num_config;
     }
-    configs[0] = config_.get();
   }
-  return true;
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
-bool Display::GetConfigAttrib(EGLConfig config,
-                              EGLint attribute,
-                              EGLint* value) {
-  const egl::Config* cfg = static_cast<egl::Config*>(config);
-  return cfg->GetAttrib(attribute, value);
+EGLBoolean Display::GetConfigs(ThreadState* ts,
+                               EGLConfig* configs,
+                               EGLint config_size,
+                               EGLint* num_config) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
+  if (num_config == nullptr)
+    return ts->ReturnError(EGL_BAD_PARAMETER, EGL_FALSE);
+  InitializeConfigsIfNeeded();
+  if (!configs)
+    config_size = 0;
+  *num_config = arraysize(configs_);
+  size_t count =
+      std::min(arraysize(configs_), static_cast<size_t>(config_size));
+  for (size_t i = 0; i < count; ++i)
+    configs[i] = configs_[i].get();
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
 bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
@@ -142,248 +123,229 @@
 #endif  // OS_WIN
 }
 
-bool Display::IsValidSurface(EGLSurface surface) {
-  return (surface != NULL) && (surface == surface_.get());
+EGLBoolean Display::GetConfigAttrib(ThreadState* ts,
+                                    EGLConfig cfg,
+                                    EGLint attribute,
+                                    EGLint* value) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
+  const egl::Config* config = GetConfig(cfg);
+  if (!config)
+    return ts->ReturnError(EGL_BAD_CONFIG, EGL_FALSE);
+  if (!config->GetAttrib(attribute, value))
+    return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
-EGLSurface Display::CreateWindowSurface(EGLConfig config,
+EGLSurface Display::CreatePbufferSurface(ThreadState* ts,
+                                         EGLConfig cfg,
+                                         const EGLint* attrib_list) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
+  const egl::Config* config = GetConfig(cfg);
+  if (!config)
+    return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
+  EGLint value = EGL_NONE;
+  config->GetAttrib(EGL_SURFACE_TYPE, &value);
+  if ((value & EGL_PBUFFER_BIT) == 0)
+    return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+  if (!egl::Surface::ValidatePbufferAttributeList(attrib_list))
+    return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+
+  int width = 1;
+  int height = 1;
+  if (attrib_list) {
+    for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
+      switch (attr[0]) {
+        case EGL_WIDTH:
+          width = attr[1];
+          break;
+        case EGL_HEIGHT:
+          height = attr[1];
+          break;
+      }
+    }
+  }
+  return DoCreatePbufferSurface(ts, width, height);
+}
+
+EGLSurface Display::DoCreatePbufferSurface(ThreadState* ts,
+                                           EGLint width,
+                                           EGLint height) {
+  lock_.AssertAcquired();
+  scoped_refptr<gfx::GLSurface> gl_surface;
+  gl_surface =
+      gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(width, height));
+  if (!gl_surface)
+    return ts->ReturnError(EGL_BAD_ALLOC, nullptr);
+  surfaces_.emplace_back(new Surface(gl_surface.get()));
+  return ts->ReturnSuccess<EGLSurface>(surfaces_.back().get());
+}
+
+EGLSurface Display::CreateWindowSurface(ThreadState* ts,
+                                        EGLConfig cfg,
                                         EGLNativeWindowType win,
                                         const EGLint* attrib_list) {
-  if (surface_ != NULL) {
-    // We do not support more than one window surface.
-    return EGL_NO_SURFACE;
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_SURFACE);
+  const egl::Config* config = GetConfig(cfg);
+  if (!config)
+    return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
+  EGLint value = EGL_NONE;
+  config->GetAttrib(EGL_SURFACE_TYPE, &value);
+  if ((value & EGL_WINDOW_BIT) == 0)
+    return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
+  if (!next_create_window_surface_creates_pbuffer_ && !IsValidNativeWindow(win))
+    return ts->ReturnError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+  if (!Surface::ValidateWindowAttributeList(attrib_list))
+    return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+  if (next_create_window_surface_creates_pbuffer_) {
+    next_create_window_surface_creates_pbuffer_ = false;
+    window_surface_pbuffer_width_ = 0;
+    window_surface_pbuffer_height_ = 0;
+    return DoCreatePbufferSurface(ts, window_surface_pbuffer_width_,
+                                  window_surface_pbuffer_height_);
   }
-
-  {
-    gpu::TransferBufferManager* manager =
-        new gpu::TransferBufferManager(nullptr);
-    transfer_buffer_manager_ = manager;
-    manager->Initialize();
-  }
-  scoped_ptr<gpu::CommandBufferService> command_buffer(
-      new gpu::CommandBufferService(transfer_buffer_manager_.get()));
-  if (!command_buffer->Initialize())
-    return NULL;
-
-  scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
-      gpu_preferences_, NULL, NULL,
-      new gpu::gles2::ShaderTranslatorCache(gpu_preferences_),
-      new gpu::gles2::FramebufferCompletenessCache, NULL, NULL, NULL, true));
-
-  decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get()));
-  if (!decoder_.get())
-    return EGL_NO_SURFACE;
-
-  executor_.reset(
-      new gpu::CommandExecutor(command_buffer.get(), decoder_.get(), NULL));
-
-  decoder_->set_engine(executor_.get());
-  gfx::Size size(create_offscreen_width_, create_offscreen_height_);
-  if (create_offscreen_) {
-    gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
-    create_offscreen_ = false;
-    create_offscreen_width_ = 0;
-    create_offscreen_height_ = 0;
-  } else {
-    gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win);
-  }
-  if (!gl_surface_.get())
-    return EGL_NO_SURFACE;
-
-  gl_context_ = gfx::GLContext::CreateGLContext(NULL,
-                                                gl_surface_.get(),
-                                                gfx::PreferDiscreteGpu);
-  if (!gl_context_.get())
-    return EGL_NO_SURFACE;
-
-  gl_context_->MakeCurrent(gl_surface_.get());
-
-  EGLint depth_size = 0;
-  EGLint alpha_size = 0;
-  EGLint stencil_size = 0;
-  GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size);
-  GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size);
-  GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size);
-  std::vector<int32_t> attribs;
-  attribs.push_back(EGL_DEPTH_SIZE);
-  attribs.push_back(depth_size);
-  attribs.push_back(EGL_ALPHA_SIZE);
-  attribs.push_back(alpha_size);
-  attribs.push_back(EGL_STENCIL_SIZE);
-  attribs.push_back(stencil_size);
-  // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null
-  attribs.push_back(EGL_NONE);
-
-  if (!decoder_->Initialize(gl_surface_.get(),
-                            gl_context_.get(),
-                            gl_surface_->IsOffscreen(),
-                            size,
-                            gpu::gles2::DisallowedFeatures(),
-                            attribs)) {
-    return EGL_NO_SURFACE;
-  }
-
-  command_buffer->SetPutOffsetChangeCallback(base::Bind(
-      &gpu::CommandExecutor::PutChanged, base::Unretained(executor_.get())));
-  command_buffer->SetGetBufferChangeCallback(base::Bind(
-      &gpu::CommandExecutor::SetGetBuffer, base::Unretained(executor_.get())));
-
-  scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper(
-      new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
-  if (!cmd_helper->Initialize(kCommandBufferSize))
-    return NULL;
-
-  scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer(
-      cmd_helper.get()));
-
-  command_buffer_.reset(command_buffer.release());
-  transfer_buffer_.reset(transfer_buffer.release());
-  gles2_cmd_helper_.reset(cmd_helper.release());
-  surface_.reset(new Surface(win));
-
-  return surface_.get();
+  scoped_refptr<gfx::GLSurface> gl_surface;
+  gl_surface = gfx::GLSurface::CreateViewGLSurface(win);
+  if (!gl_surface)
+    return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+  surfaces_.emplace_back(new Surface(gl_surface.get()));
+  return ts->ReturnSuccess(surfaces_.back().get());
 }
 
-void Display::DestroySurface(EGLSurface surface) {
-  DCHECK(IsValidSurface(surface));
-  executor_.reset();
-  if (decoder_.get()) {
-    decoder_->Destroy(true);
+EGLBoolean Display::DestroySurface(ThreadState* ts, EGLSurface sfe) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
+  auto it = std::find(surfaces_.begin(), surfaces_.end(), sfe);
+  if (it == surfaces_.end())
+    return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
+  surfaces_.erase(it);
+  return ts->ReturnSuccess(EGL_TRUE);
+}
+
+EGLBoolean Display::ReleaseCurrent(ThreadState* ts) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnSuccess(EGL_TRUE);
+  ThreadState::AutoCurrentContextRestore accr(ts);
+  if (ts->current_context()) {
+    Context::MakeCurrent(ts->current_context(),
+                         ts->current_surface()->gl_surface(), nullptr, nullptr);
+    accr.SetCurrent(nullptr, nullptr);
   }
-  decoder_.reset();
-  gl_surface_ = NULL;
-  gl_context_ = NULL;
-  surface_.reset();
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
-void Display::SwapBuffers(EGLSurface surface) {
-  DCHECK(IsValidSurface(surface));
-  context_->SwapBuffers();
+EGLBoolean Display::MakeCurrent(ThreadState* ts,
+                                EGLSurface draw,
+                                EGLSurface read,
+                                EGLSurface ctx) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
+  ThreadState::AutoCurrentContextRestore accr(ts);
+  // Client might have called use because it changed some other gl binding
+  // global state. For example, the client might have called eglMakeCurrent on
+  // the same EGL as what command buffer uses. The client probably knows that
+  // this invalidates the internal state of command buffer, too. So reset the
+  // current context with accr in any case, regardless whether context or
+  // surface pointer changes.
+  Surface* new_surface = GetSurface(draw);
+  if (!new_surface)
+    return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
+  new_surface = GetSurface(read);
+  if (!new_surface)
+    return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
+  egl::Context* new_context = GetContext(ctx);
+  if (!new_context)
+    return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE);
+  if (draw != read)
+    return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE);
+
+  Surface* current_surface = ts->current_surface();
+  Context* current_context = ts->current_context();
+
+  if (current_context != new_context &&
+      new_context->is_current_in_some_thread())
+    return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE);
+
+  if (current_surface != new_surface &&
+      new_surface->is_current_in_some_thread())
+    return ts->ReturnError(EGL_BAD_ACCESS, EGL_FALSE);
+
+  if (!Context::MakeCurrent(
+          current_context,
+          current_context ? current_surface->gl_surface() : nullptr,
+          new_context, new_context ? new_surface->gl_surface() : nullptr))
+    return ts->ReturnError(EGL_BAD_MATCH, EGL_FALSE);
+
+  accr.SetCurrent(new_surface, new_context);
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
-bool Display::IsValidContext(EGLContext ctx) {
-  return (ctx != NULL) && (ctx == context_.get());
+EGLBoolean Display::SwapBuffers(ThreadState* ts, EGLSurface sfe) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
+  egl::Surface* surface = GetSurface(sfe);
+  if (!surface)
+    return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
+  if (ts->current_surface() != surface)
+    return ts->ReturnError(EGL_BAD_SURFACE, EGL_FALSE);
+  ts->current_context()->FlushAndSwapBuffers(surface->gl_surface());
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
-EGLContext Display::CreateContext(EGLConfig config,
+EGLContext Display::CreateContext(ThreadState* ts,
+                                  EGLConfig cfg,
                                   EGLContext share_ctx,
                                   const EGLint* attrib_list) {
-  DCHECK(IsValidConfig(config));
-  // TODO(alokp): Add support for shared contexts.
-  if (share_ctx != NULL)
-    return EGL_NO_CONTEXT;
-
-  DCHECK(command_buffer_ != NULL);
-  DCHECK(transfer_buffer_.get());
-
-  bool bind_generates_resources = true;
-  bool lose_context_when_out_of_memory = false;
-  bool support_client_side_arrays = true;
-
-  context_.reset(
-      new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(),
-                                          NULL,
-                                          transfer_buffer_.get(),
-                                          bind_generates_resources,
-                                          lose_context_when_out_of_memory,
-                                          support_client_side_arrays,
-                                          this));
-
-  if (!context_->Initialize(
-      kTransferBufferSize,
-      kTransferBufferSize / 2,
-      kTransferBufferSize * 2,
-      gpu::gles2::GLES2Implementation::kNoLimit)) {
-    return EGL_NO_CONTEXT;
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_NO_CONTEXT);
+  if (share_ctx != EGL_NO_CONTEXT) {
+    egl::Context* share_context = GetContext(share_ctx);
+    if (!share_context)
+      return ts->ReturnError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
+    // TODO(alokp): Add support for shared contexts.
+    return ts->ReturnError(EGL_BAD_MATCH, EGL_NO_CONTEXT);
   }
-
-  context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
-  context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
-
-  return context_.get();
+  if (!egl::Context::ValidateAttributeList(attrib_list))
+    return ts->ReturnError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+  const egl::Config* config = GetConfig(cfg);
+  if (!config)
+    return ts->ReturnError(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+  scoped_refptr<Context> context(new Context(this, config));
+  if (!context)
+    return ts->ReturnError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+  contexts_.emplace_back(context.get());
+  return ts->ReturnSuccess<EGLContext>(context.get());
 }
 
-void Display::DestroyContext(EGLContext ctx) {
-  DCHECK(IsValidContext(ctx));
-  context_.reset();
-  transfer_buffer_.reset();
-}
-
-bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) {
-  if (ctx == EGL_NO_CONTEXT) {
-    gles2::SetGLContext(NULL);
-  } else {
-    DCHECK(IsValidSurface(draw));
-    DCHECK(IsValidSurface(read));
-    DCHECK(IsValidContext(ctx));
-    gles2::SetGLContext(context_.get());
-    gl_context_->MakeCurrent(gl_surface_.get());
-  }
-  return true;
-}
-
-void Display::SetGpuControlClient(gpu::GpuControlClient*) {
-  // The client is not currently called, so don't store it.
-}
-
-gpu::Capabilities Display::GetCapabilities() {
-  return decoder_->GetCapabilities();
-}
-
-int32_t Display::CreateImage(ClientBuffer buffer,
-                             size_t width,
-                             size_t height,
-                             unsigned internalformat) {
-  NOTIMPLEMENTED();
-  return -1;
-}
-
-void Display::DestroyImage(int32_t id) {
-  NOTIMPLEMENTED();
-}
-
-int32_t Display::CreateGpuMemoryBufferImage(size_t width,
-                                            size_t height,
-                                            unsigned internalformat,
-                                            unsigned usage) {
-  NOTIMPLEMENTED();
-  return -1;
-}
-
-void Display::SignalQuery(uint32_t query, const base::Closure& callback) {
-  NOTIMPLEMENTED();
-}
-
-void Display::SetLock(base::Lock*) {
-  NOTIMPLEMENTED();
-}
-
-bool Display::IsGpuChannelLost() {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-void Display::EnsureWorkVisible() {
-  // This is only relevant for out-of-process command buffers.
-}
-
-gpu::CommandBufferNamespace Display::GetNamespaceID() const {
-  return gpu::CommandBufferNamespace::IN_PROCESS;
-}
-
-gpu::CommandBufferId Display::GetCommandBufferID() const {
-  return gpu::CommandBufferId();
-}
-
-int32_t Display::GetExtraCommandBufferData() const {
-  return 0;
+EGLBoolean Display::DestroyContext(ThreadState* ts, EGLContext ctx) {
+  base::AutoLock auto_lock(lock_);
+  if (!is_initialized_)
+    return ts->ReturnError(EGL_NOT_INITIALIZED, EGL_FALSE);
+  auto it = std::find(contexts_.begin(), contexts_.end(), ctx);
+  if (it == contexts_.end())
+    return ts->ReturnError(EGL_BAD_CONTEXT, EGL_FALSE);
+  (*it)->MarkDestroyed();
+  contexts_.erase(it);
+  return ts->ReturnSuccess(EGL_TRUE);
 }
 
 uint64_t Display::GenerateFenceSyncRelease() {
+  base::AutoLock auto_lock(lock_);
   return next_fence_sync_release_++;
 }
 
 bool Display::IsFenceSyncRelease(uint64_t release) {
+  base::AutoLock auto_lock(lock_);
   return release > 0 && release < next_fence_sync_release_;
 }
 
@@ -395,13 +357,41 @@
   return IsFenceSyncRelease(release);
 }
 
-void Display::SignalSyncToken(const gpu::SyncToken& sync_token,
-                              const base::Closure& callback) {
-  NOTIMPLEMENTED();
+void Display::InitializeConfigsIfNeeded() {
+  lock_.AssertAcquired();
+  if (!configs_[0]) {
+    // The interface offers separate configs for window and pbuffer.
+    // This way we can record the client intention at context creation time.
+    // The GL implementation (gfx::GLContext and gfx::GLSurface) needs this
+    // distinction when creating a context.
+    configs_[0].reset(new Config(EGL_WINDOW_BIT));
+    configs_[1].reset(new Config(EGL_PBUFFER_BIT));
+  }
 }
 
-bool Display::CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) {
-  return false;
+const Config* Display::GetConfig(EGLConfig cfg) {
+  lock_.AssertAcquired();
+  for (const auto& config : configs_) {
+    if (config.get() == cfg)
+      return config.get();
+  }
+  return nullptr;
+}
+
+Surface* Display::GetSurface(EGLSurface surface) {
+  lock_.AssertAcquired();
+  auto it = std::find(surfaces_.begin(), surfaces_.end(), surface);
+  if (it == surfaces_.end())
+    return nullptr;
+  return it->get();
+}
+
+Context* Display::GetContext(EGLContext context) {
+  lock_.AssertAcquired();
+  auto it = std::find(contexts_.begin(), contexts_.end(), context);
+  if (it == contexts_.end())
+    return nullptr;
+  return it->get();
 }
 
 }  // namespace egl
diff --git a/gpu/gles2_conform_support/egl/display.h b/gpu/gles2_conform_support/egl/display.h
index 52252323..8ed12a4 100644
--- a/gpu/gles2_conform_support/egl/display.h
+++ b/gpu/gles2_conform_support/egl/display.h
@@ -9,125 +9,98 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <vector>
+
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "gpu/command_buffer/client/gles2_cmd_helper.h"
-#include "gpu/command_buffer/client/gpu_control.h"
-#include "gpu/command_buffer/service/command_buffer_service.h"
-#include "gpu/command_buffer/service/command_executor.h"
-#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "gpu/command_buffer/service/gpu_preferences.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_surface.h"
-
-namespace gpu {
-class CommandBufferService;
-class GpuControl;
-class CommandExecutor;
-class TransferBuffer;
-class TransferBufferManagerInterface;
-
-namespace gles2 {
-class GLES2CmdHelper;
-class GLES2Implementation;
-}  // namespace gles2
-}  // namespace gpu
+#include "base/synchronization/lock.h"
 
 namespace egl {
 
 class Config;
+class Context;
 class Surface;
+class ThreadState;
 
-class Display : private gpu::GpuControl {
+class Display {
  public:
-  explicit Display(EGLNativeDisplayType display_id);
-  ~Display() override;
-
-  void SetCreateOffscreen(int width, int height) {
-    create_offscreen_ = true;
-    create_offscreen_width_ = width;
-    create_offscreen_height_ = height;
-  }
+  explicit Display();
+  ~Display();
 
   bool is_initialized() const { return is_initialized_; }
-  bool Initialize();
+
+  void ReleaseCurrentForReleaseThread(ThreadState*);
+
+  // A function for windowless GTF tests.
+  void SetNextCreateWindowSurfaceCreatesPBuffer(EGLint width, EGLint height);
+
+  EGLBoolean Initialize(ThreadState* ts, EGLint* major, EGLint* minor);
+  EGLBoolean Terminate(ThreadState* ts);
+  const char* QueryString(ThreadState* ts, EGLint name);
 
   // Config routines.
-  bool IsValidConfig(EGLConfig config);
-  bool ChooseConfigs(
-      EGLConfig* configs, EGLint config_size, EGLint* num_config);
-  bool GetConfigs(EGLConfig* configs, EGLint config_size, EGLint* num_config);
-  bool GetConfigAttrib(EGLConfig config, EGLint attribute, EGLint* value);
+  EGLBoolean GetConfigAttrib(ThreadState* ts,
+                             EGLConfig cfg,
+                             EGLint attribute,
+                             EGLint* value);
+  EGLBoolean ChooseConfig(ThreadState* ts,
+                          const EGLint* attrib_list,
+                          EGLConfig* configs,
+                          EGLint config_size,
+                          EGLint* num_config);
+  EGLBoolean GetConfigs(ThreadState*,
+                        EGLConfig*,
+                        EGLint config_size,
+                        EGLint* num_config);
 
   // Surface routines.
-  bool IsValidNativeWindow(EGLNativeWindowType win);
-  bool IsValidSurface(EGLSurface surface);
-  EGLSurface CreateWindowSurface(EGLConfig config,
+  static bool IsValidNativeWindow(EGLNativeWindowType);
+  EGLSurface CreatePbufferSurface(ThreadState*,
+                                  EGLConfig,
+                                  const EGLint* attrib_list);
+  EGLSurface CreateWindowSurface(ThreadState*,
+                                 EGLConfig,
                                  EGLNativeWindowType win,
                                  const EGLint* attrib_list);
-  void DestroySurface(EGLSurface surface);
-  void SwapBuffers(EGLSurface surface);
+  EGLBoolean DestroySurface(ThreadState*, EGLSurface);
+  EGLBoolean SwapBuffers(ThreadState*, EGLSurface);
 
   // Context routines.
-  bool IsValidContext(EGLContext ctx);
-  EGLContext CreateContext(EGLConfig config,
-                           EGLContext share_ctx,
+  EGLContext CreateContext(ThreadState*,
+                           EGLConfig,
+                           EGLSurface share_ctx,
                            const EGLint* attrib_list);
-  void DestroyContext(EGLContext ctx);
-  bool MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx);
+  EGLBoolean DestroyContext(ThreadState*, EGLContext);
 
-  // GpuControl implementation.
-  void SetGpuControlClient(gpu::GpuControlClient*) override;
-  gpu::Capabilities GetCapabilities() override;
-  int32_t CreateImage(ClientBuffer buffer,
-                      size_t width,
-                      size_t height,
-                      unsigned internalformat) override;
-  void DestroyImage(int32_t id) override;
-  int32_t CreateGpuMemoryBufferImage(size_t width,
-                                     size_t height,
-                                     unsigned internalformat,
-                                     unsigned usage) override;
-  void SignalQuery(uint32_t query, const base::Closure& callback) override;
-  void SetLock(base::Lock*) override;
-  bool IsGpuChannelLost() override;
-  void EnsureWorkVisible() override;
-  gpu::CommandBufferNamespace GetNamespaceID() const override;
-  gpu::CommandBufferId GetCommandBufferID() const override;
-  int32_t GetExtraCommandBufferData() const override;
-  uint64_t GenerateFenceSyncRelease() override;
-  bool IsFenceSyncRelease(uint64_t release) override;
-  bool IsFenceSyncFlushed(uint64_t release) override;
-  bool IsFenceSyncFlushReceived(uint64_t release) override;
-  void SignalSyncToken(const gpu::SyncToken& sync_token,
-                       const base::Closure& callback) override;
-  bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override;
+  EGLBoolean ReleaseCurrent(ThreadState*);
+  EGLBoolean MakeCurrent(ThreadState*, EGLSurface, EGLSurface, EGLContext);
+
+  uint64_t GenerateFenceSyncRelease();
+  bool IsFenceSyncRelease(uint64_t release);
+  bool IsFenceSyncFlushed(uint64_t release);
+  bool IsFenceSyncFlushReceived(uint64_t release);
 
  private:
-  EGLNativeDisplayType display_id_;
+  void InitializeConfigsIfNeeded();
+  const Config* GetConfig(EGLConfig);
+  Surface* GetSurface(EGLSurface);
+  Context* GetContext(EGLContext);
+  EGLSurface DoCreatePbufferSurface(ThreadState* ts,
+                                    EGLint width,
+                                    EGLint height);
 
-  gpu::GpuPreferences gpu_preferences_;
+  base::Lock lock_;
   bool is_initialized_;
-
-  bool create_offscreen_;
-  int create_offscreen_width_;
-  int create_offscreen_height_;
   uint64_t next_fence_sync_release_;
+  std::vector<scoped_refptr<Surface>> surfaces_;
+  std::vector<scoped_refptr<Context>> contexts_;
+  scoped_ptr<Config> configs_[2];
 
-  scoped_refptr<gpu::TransferBufferManagerInterface> transfer_buffer_manager_;
-  scoped_ptr<gpu::CommandBufferService> command_buffer_;
-  scoped_ptr<gpu::CommandExecutor> executor_;
-  scoped_ptr<gpu::gles2::GLES2Decoder> decoder_;
-  scoped_refptr<gfx::GLContext> gl_context_;
-  scoped_refptr<gfx::GLSurface> gl_surface_;
-  scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_;
-  scoped_ptr<gpu::TransferBuffer> transfer_buffer_;
-
-  // TODO(alokp): Support more than one config, surface, and context.
-  scoped_ptr<Config> config_;
-  scoped_ptr<Surface> surface_;
-  scoped_ptr<gpu::gles2::GLES2Implementation> context_;
+  // GTF windowless support.
+  bool next_create_window_surface_creates_pbuffer_;
+  EGLint window_surface_pbuffer_width_;
+  EGLint window_surface_pbuffer_height_;
 
   DISALLOW_COPY_AND_ASSIGN(Display);
 };
diff --git a/gpu/gles2_conform_support/egl/egl.cc b/gpu/gles2_conform_support/egl/egl.cc
index 5a81954b..b14479bc3 100644
--- a/gpu/gles2_conform_support/egl/egl.cc
+++ b/gpu/gles2_conform_support/egl/egl.cc
@@ -5,184 +5,58 @@
 #include <EGL/egl.h>
 #include <stdint.h>
 
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "gpu/command_buffer/client/gles2_lib.h"
-#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/config/gpu_info_collector.h"
-#include "gpu/config/gpu_util.h"
+#include "gpu/gles2_conform_support/egl/config.h"
+#include "gpu/gles2_conform_support/egl/context.h"
 #include "gpu/gles2_conform_support/egl/display.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_surface.h"
-
-#if REGAL_STATIC_EGL
-extern "C" {
-
-typedef EGLContext RegalSystemContext;
-#define REGAL_DECL
-REGAL_DECL void RegalMakeCurrent( RegalSystemContext ctx );
-
-}  // extern "C"
-#endif
-
-namespace {
-void SetCurrentError(EGLint error_code) {
-}
-
-template<typename T>
-T EglError(EGLint error_code, T return_value) {
-  SetCurrentError(error_code);
-  return return_value;
-}
-
-template<typename T>
-T EglSuccess(T return_value) {
-  SetCurrentError(EGL_SUCCESS);
-  return return_value;
-}
-
-EGLint ValidateDisplay(EGLDisplay dpy) {
-  if (dpy == EGL_NO_DISPLAY)
-    return EGL_BAD_DISPLAY;
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->is_initialized())
-    return EGL_NOT_INITIALIZED;
-
-  return EGL_SUCCESS;
-}
-
-EGLint ValidateDisplayConfig(EGLDisplay dpy, EGLConfig config) {
-  EGLint error_code = ValidateDisplay(dpy);
-  if (error_code != EGL_SUCCESS)
-    return error_code;
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->IsValidConfig(config))
-    return EGL_BAD_CONFIG;
-
-  return EGL_SUCCESS;
-}
-
-EGLint ValidateDisplaySurface(EGLDisplay dpy, EGLSurface surface) {
-  EGLint error_code = ValidateDisplay(dpy);
-  if (error_code != EGL_SUCCESS)
-    return error_code;
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->IsValidSurface(surface))
-    return EGL_BAD_SURFACE;
-
-  return EGL_SUCCESS;
-}
-
-EGLint ValidateDisplayContext(EGLDisplay dpy, EGLContext context) {
-  EGLint error_code = ValidateDisplay(dpy);
-  if (error_code != EGL_SUCCESS)
-    return error_code;
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->IsValidContext(context))
-    return EGL_BAD_CONTEXT;
-
-  return EGL_SUCCESS;
-}
-}  // namespace
+#include "gpu/gles2_conform_support/egl/surface.h"
+#include "gpu/gles2_conform_support/egl/thread_state.h"
 
 extern "C" {
 EGLAPI EGLint EGLAPIENTRY eglGetError() {
-  // TODO(alokp): Fix me.
-  return EGL_SUCCESS;
+  return egl::ThreadState::Get()->ConsumeErrorCode();
 }
 
 EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) {
-  return new egl::Display(display_id);
+  if (display_id != EGL_DEFAULT_DISPLAY)
+    return EGL_NO_DISPLAY;
+  return egl::ThreadState::Get()->GetDefaultDisplay();
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy,
                                             EGLint* major,
                                             EGLint* minor) {
-  if (dpy == EGL_NO_DISPLAY)
-    return EglError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->Initialize())
-    return EglError(EGL_NOT_INITIALIZED, EGL_FALSE);
-
-  // eglInitialize can be called multiple times, prevent InitializeOneOff from
-  // being called multiple times.
-  if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
-    base::CommandLine::StringVector argv;
-    scoped_ptr<base::Environment> env(base::Environment::Create());
-    std::string env_string;
-    env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string);
-#if defined(OS_WIN)
-    argv = base::SplitString(base::UTF8ToUTF16(env_string),
-                             base::kWhitespaceUTF16, base::TRIM_WHITESPACE,
-                             base::SPLIT_WANT_NONEMPTY);
-    argv.insert(argv.begin(), base::UTF8ToUTF16("dummy"));
-#else
-    argv = base::SplitString(env_string,
-                             base::kWhitespaceASCII, base::TRIM_WHITESPACE,
-                             base::SPLIT_WANT_NONEMPTY);
-    argv.insert(argv.begin(), "dummy");
-#endif
-    base::CommandLine::Init(0, nullptr);
-    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    // Need to call both Init and InitFromArgv, since Windows does not use
-    // argc, argv in CommandLine::Init(argc, argv).
-    command_line->InitFromArgv(argv);
-    if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
-      gpu::GPUInfo gpu_info;
-      gpu::CollectBasicGraphicsInfo(&gpu_info);
-      gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line);
-    }
-
-    gfx::GLSurface::InitializeOneOff();
-  }
-  if (major)
-    *major = 1;
-  if (minor)
-    *minor = 4;
-  return EglSuccess(EGL_TRUE);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->Initialize(ts, major, minor);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) {
-  EGLint error_code = ValidateDisplay(dpy);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  delete display;
-
-  // TODO: EGL specifies that the objects are marked for deletion and they will
-  // remain alive as long as "contexts or surfaces associated with display is
-  // current to any thread".
-  // Currently we delete the display here, and may also call exit handlers.
-
-  return EglSuccess(EGL_TRUE);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->Terminate(ts);
 }
 
 EGLAPI const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) {
-  EGLint error_code = ValidateDisplay(dpy);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, static_cast<const char*>(NULL));
-
-  switch (name) {
-    case EGL_CLIENT_APIS:
-      return EglSuccess("OpenGL_ES");
-    case EGL_EXTENSIONS:
-      return EglSuccess("");
-    case EGL_VENDOR:
-      return EglSuccess("Google Inc.");
-    case EGL_VERSION:
-      return EglSuccess("1.4");
-    default:
-      return EglError(EGL_BAD_PARAMETER, static_cast<const char*>(NULL));
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  if (dpy == EGL_NO_DISPLAY) {
+    switch (name) {
+      case EGL_EXTENSIONS:
+        return ts->ReturnSuccess("");
+      case EGL_VERSION:
+        return ts->ReturnSuccess("1.4");
+      default:
+        break;
+    }
   }
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError<const char*>(EGL_BAD_DISPLAY, nullptr);
+  return display->QueryString(ts, name);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy,
@@ -190,103 +64,57 @@
                                               EGLConfig* configs,
                                               EGLint config_size,
                                               EGLint* num_config) {
-  EGLint error_code = ValidateDisplay(dpy);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_FALSE);
-
-  if (num_config == NULL)
-    return EglError(EGL_BAD_PARAMETER, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->ChooseConfigs(configs, config_size, num_config))
-    return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-
-  return EglSuccess(EGL_TRUE);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->ChooseConfig(ts, attrib_list, configs, config_size,
+                               num_config);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy,
                                             EGLConfig* configs,
                                             EGLint config_size,
                                             EGLint* num_config) {
-  EGLint error_code = ValidateDisplay(dpy);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_FALSE);
-
-  if (num_config == NULL)
-    return EglError(EGL_BAD_PARAMETER, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->GetConfigs(configs, config_size, num_config))
-    return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-
-  return EglSuccess(EGL_TRUE);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->GetConfigs(ts, configs, config_size, num_config);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy,
-                                                 EGLConfig config,
+                                                 EGLConfig cfg,
                                                  EGLint attribute,
                                                  EGLint* value) {
-  EGLint error_code = ValidateDisplayConfig(dpy, config);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->GetConfigAttrib(config, attribute, value))
-    return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-
-  return EglSuccess(EGL_TRUE);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->GetConfigAttrib(ts, cfg, attribute, value);
 }
 
 EGLAPI EGLSurface EGLAPIENTRY
 eglCreateWindowSurface(EGLDisplay dpy,
-                       EGLConfig config,
+                       EGLConfig cfg,
                        EGLNativeWindowType win,
                        const EGLint* attrib_list) {
-  EGLint error_code = ValidateDisplayConfig(dpy, config);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_NO_SURFACE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->IsValidNativeWindow(win))
-    return EglError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
-
-  EGLSurface surface = display->CreateWindowSurface(config, win, attrib_list);
-  if (surface == EGL_NO_SURFACE)
-    return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-
-  return EglSuccess(surface);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+  return display->CreateWindowSurface(ts, cfg, win, attrib_list);
 }
 
 EGLAPI EGLSurface EGLAPIENTRY
 eglCreatePbufferSurface(EGLDisplay dpy,
-                        EGLConfig config,
+                        EGLConfig cfg,
                         const EGLint* attrib_list) {
-  EGLint error_code = ValidateDisplayConfig(dpy, config);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_NO_SURFACE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  int width = 1;
-  int height = 1;
-  if (attrib_list) {
-    for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
-      switch (attr[0]) {
-        case EGL_WIDTH:
-          width = attr[1];
-          break;
-        case EGL_HEIGHT:
-          height = attr[1];
-          break;
-      }
-    }
-  }
-  display->SetCreateOffscreen(width, height);
-
-  EGLSurface surface = display->CreateWindowSurface(config, 0, attrib_list);
-  if (surface == EGL_NO_SURFACE)
-    return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-
-  return EglSuccess(surface);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+  return display->CreatePbufferSurface(ts, cfg, attrib_list);
 }
 
 EGLAPI EGLSurface EGLAPIENTRY
@@ -298,14 +126,12 @@
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy,
-                                                EGLSurface surface) {
-  EGLint error_code = ValidateDisplaySurface(dpy, surface);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  display->DestroySurface(surface);
-  return EglSuccess(EGL_TRUE);
+                                                EGLSurface sfe) {
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->DestroySurface(ts, sfe);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy,
@@ -328,7 +154,8 @@
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) {
-  return EGL_FALSE;
+  egl::ThreadState::ReleaseThread();
+  return EGL_TRUE;
 }
 
 EGLAPI EGLSurface EGLAPIENTRY
@@ -364,64 +191,42 @@
 }
 
 EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy,
-                                               EGLConfig config,
-                                               EGLContext share_context,
+                                               EGLConfig cfg,
+                                               EGLContext share_ctx,
                                                const EGLint* attrib_list) {
-  EGLint error_code = ValidateDisplayConfig(dpy, config);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_NO_CONTEXT);
-
-  if (share_context != EGL_NO_CONTEXT) {
-    error_code = ValidateDisplayContext(dpy, share_context);
-    if (error_code != EGL_SUCCESS)
-      return EglError(error_code, EGL_NO_CONTEXT);
-  }
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  EGLContext context = display->CreateContext(
-      config, share_context, attrib_list);
-  if (context == EGL_NO_CONTEXT)
-    return EglError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
-
-  return EglSuccess(context);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_CONTEXT);
+  return display->CreateContext(ts, cfg, share_ctx, attrib_list);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy,
                                                 EGLContext ctx) {
-  EGLint error_code = ValidateDisplayContext(dpy, ctx);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  display->DestroyContext(ctx);
-  return EGL_TRUE;
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->DestroyContext(ts, ctx);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy,
                                              EGLSurface draw,
                                              EGLSurface read,
                                              EGLContext ctx) {
-  if (ctx != EGL_NO_CONTEXT) {
-    EGLint error_code = ValidateDisplaySurface(dpy, draw);
-    if (error_code != EGL_SUCCESS)
-      return EglError(error_code, EGL_FALSE);
-    error_code = ValidateDisplaySurface(dpy, read);
-    if (error_code != EGL_SUCCESS)
-      return EglError(error_code, EGL_FALSE);
-    error_code = ValidateDisplayContext(dpy, ctx);
-    if (error_code != EGL_SUCCESS)
-      return EglError(error_code, EGL_FALSE);
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  if (draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE &&
+      ctx == EGL_NO_CONTEXT) {
+    egl::Display* display =
+        dpy == EGL_NO_DISPLAY ? ts->GetDefaultDisplay() : ts->GetDisplay(dpy);
+    if (!display)
+      return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+    return display->ReleaseCurrent(ts);
   }
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  if (!display->MakeCurrent(draw, read, ctx))
-    return EglError(EGL_CONTEXT_LOST, EGL_FALSE);
-
-#if REGAL_STATIC_EGL
-  RegalMakeCurrent(ctx);
-#endif
-
-  return EGL_TRUE;
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->MakeCurrent(ts, draw, read, ctx);
 }
 
 EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext() {
@@ -451,15 +256,12 @@
   return EGL_FALSE;
 }
 
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy,
-                                             EGLSurface surface) {
-  EGLint error_code = ValidateDisplaySurface(dpy, surface);
-  if (error_code != EGL_SUCCESS)
-    return EglError(error_code, EGL_FALSE);
-
-  egl::Display* display = static_cast<egl::Display*>(dpy);
-  display->SwapBuffers(surface);
-  return EglSuccess(EGL_TRUE);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface sfe) {
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
+  return display->SwapBuffers(ts, sfe);
 }
 
 EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy,
diff --git a/gpu/gles2_conform_support/egl/surface.cc b/gpu/gles2_conform_support/egl/surface.cc
index 423fe275..9899cb3 100644
--- a/gpu/gles2_conform_support/egl/surface.cc
+++ b/gpu/gles2_conform_support/egl/surface.cc
@@ -3,13 +3,40 @@
 // found in the LICENSE file.
 
 #include "gpu/gles2_conform_support/egl/surface.h"
+#include "ui/gl/gl_surface.h"
 
 namespace egl {
 
-Surface::Surface(EGLNativeWindowType win) : window_(win) {
-}
+Surface::Surface(gfx::GLSurface* gl_surface)
+    : is_current_in_some_thread_(false), gl_surface_(gl_surface) {}
 
 Surface::~Surface() {
 }
 
+gfx::GLSurface* Surface::gl_surface() const {
+  return gl_surface_.get();
+}
+
+bool Surface::ValidatePbufferAttributeList(const EGLint* attrib_list) {
+  if (attrib_list) {
+    for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+      switch (attrib_list[i]) {
+        case EGL_WIDTH:
+        case EGL_HEIGHT:
+          break;
+        default:
+          return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool Surface::ValidateWindowAttributeList(const EGLint* attrib_list) {
+  if (attrib_list) {
+    if (attrib_list[0] != EGL_NONE)
+      return false;
+  }
+  return true;
+}
 }  // namespace egl
diff --git a/gpu/gles2_conform_support/egl/surface.h b/gpu/gles2_conform_support/egl/surface.h
index 3db553e..84ba0aa 100644
--- a/gpu/gles2_conform_support/egl/surface.h
+++ b/gpu/gles2_conform_support/egl/surface.h
@@ -8,19 +8,28 @@
 #include <EGL/egl.h>
 
 #include "base/macros.h"
-
+#include "base/memory/ref_counted.h"
+namespace gfx {
+class GLSurface;
+}
 namespace egl {
 
-class Surface {
+class Surface : public base::RefCountedThreadSafe<Surface> {
  public:
-  explicit Surface(EGLNativeWindowType win);
-  ~Surface();
-
-  EGLNativeWindowType window() { return window_; }
+  explicit Surface(gfx::GLSurface* gl_surface);
+  void set_is_current_in_some_thread(bool flag) {
+    is_current_in_some_thread_ = flag;
+  }
+  bool is_current_in_some_thread() const { return is_current_in_some_thread_; }
+  gfx::GLSurface* gl_surface() const;
+  static bool ValidatePbufferAttributeList(const EGLint* attrib_list);
+  static bool ValidateWindowAttributeList(const EGLint* attrib_list);
 
  private:
-  EGLNativeWindowType window_;
-
+  friend class base::RefCountedThreadSafe<Surface>;
+  ~Surface();
+  bool is_current_in_some_thread_;
+  scoped_refptr<gfx::GLSurface> gl_surface_;
   DISALLOW_COPY_AND_ASSIGN(Surface);
 };
 
diff --git a/gpu/gles2_conform_support/egl/test_support.cc b/gpu/gles2_conform_support/egl/test_support.cc
index 938abcfd4..84fb3ef 100644
--- a/gpu/gles2_conform_support/egl/test_support.cc
+++ b/gpu/gles2_conform_support/egl/test_support.cc
@@ -3,7 +3,22 @@
 // found in the LICENSE file.
 
 #include "test_support.h"
+#include "gpu/gles2_conform_support/egl/display.h"
+#include "gpu/gles2_conform_support/egl/thread_state.h"
 
 #if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
 bool g_command_buffer_gles_has_atexit_manager;
 #endif
+
+extern "C" {
+EGLAPI void EGLAPIENTRY
+CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(EGLDisplay dpy,
+                                                          EGLint width,
+                                                          EGLint height) {
+  egl::ThreadState* ts = egl::ThreadState::Get();
+  egl::Display* display = ts->GetDisplay(dpy);
+  if (!display)
+    return;
+  display->SetNextCreateWindowSurfaceCreatesPBuffer(width, height);
+}
+}
diff --git a/gpu/gles2_conform_support/egl/test_support.h b/gpu/gles2_conform_support/egl/test_support.h
index b1a70885..f5cca7f 100644
--- a/gpu/gles2_conform_support/egl/test_support.h
+++ b/gpu/gles2_conform_support/egl/test_support.h
@@ -5,6 +5,8 @@
 #ifndef GPU_GLES2_CONFORM_SUPPORT_EGL_TEST_SUPPORT_H_
 #define GPU_GLES2_CONFORM_SUPPORT_EGL_TEST_SUPPORT_H_
 
+#include <EGL/egl.h>
+
 #if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
 // A variable used for communicating whether the app has initialized the global
 // variables.
@@ -16,4 +18,15 @@
 EGLAPI extern EGLAPIENTRY bool g_command_buffer_gles_has_atexit_manager;
 #endif
 
+extern "C" {
+// A function to support GTF windowless tests. gles2_conform_test_windowless and
+// khronos_glcts_test_windowless create "windowless" native windows and render
+// to those. The test runners do not at the moment implement creating said
+// windowless native windows. This call sets the system so that it will create a
+// pbuffer when eglCreateWindow is called.
+EGLAPI EGLAPIENTRY void
+CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(EGLDisplay eglDisplay,
+                                                          EGLint width,
+                                                          EGLint height);
+}
 #endif
diff --git a/gpu/gles2_conform_support/egl/thread_state.cc b/gpu/gles2_conform_support/egl/thread_state.cc
new file mode 100644
index 0000000..5f2e691
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/thread_state.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2016 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 "gpu/gles2_conform_support/egl/thread_state.h"
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/lazy_instance.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/command_buffer/common/thread_local.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_util.h"
+#include "gpu/gles2_conform_support/egl/context.h"
+#include "gpu/gles2_conform_support/egl/display.h"
+#include "gpu/gles2_conform_support/egl/surface.h"
+#include "gpu/gles2_conform_support/egl/test_support.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+
+// Thread local key for ThreadState instance. Accessed when holding g_egl_lock
+// only, since the initialization can not be Guaranteed otherwise.  Not in
+// anonymous namespace due to Mac OS X 10.6 linker. See gles2_lib.cc.
+static gpu::ThreadLocalKey g_egl_thread_state_key;
+
+namespace {
+base::LazyInstance<base::Lock>::Leaky g_egl_lock;
+int g_egl_active_thread_count;
+
+egl::Display* g_egl_default_display;
+
+#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
+// egl::Display is used for comformance tests and command_buffer_gles.  We only
+// need the exit manager for the command_buffer_gles library.
+base::AtExitManager* g_exit_manager;
+#endif
+}  // namespace
+
+namespace egl {
+
+egl::ThreadState* ThreadState::Get() {
+  base::AutoLock lock(g_egl_lock.Get());
+  if (g_egl_active_thread_count == 0) {
+#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
+#if defined(COMPONENT_BUILD)
+    if (!g_command_buffer_gles_has_atexit_manager)
+      g_exit_manager = new base::AtExitManager;
+#else
+    g_exit_manager = new base::AtExitManager;
+#endif
+#endif
+    gles2::Initialize();
+
+    if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
+      base::CommandLine::StringVector argv;
+      scoped_ptr<base::Environment> env(base::Environment::Create());
+      std::string env_string;
+      env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string);
+#if defined(OS_WIN)
+      argv = base::SplitString(base::UTF8ToUTF16(env_string),
+                               base::kWhitespaceUTF16, base::TRIM_WHITESPACE,
+                               base::SPLIT_WANT_NONEMPTY);
+      argv.insert(argv.begin(), base::UTF8ToUTF16("dummy"));
+#else
+      argv =
+          base::SplitString(env_string, base::kWhitespaceASCII,
+                            base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+      argv.insert(argv.begin(), "dummy");
+#endif
+      base::CommandLine::Init(0, nullptr);
+      base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+      // Need to call both Init and InitFromArgv, since Windows does not use
+      // argc, argv in CommandLine::Init(argc, argv).
+      command_line->InitFromArgv(argv);
+      if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
+        gpu::GPUInfo gpu_info;
+        gpu::CollectBasicGraphicsInfo(&gpu_info);
+        gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line);
+      }
+
+      gfx::GLSurface::InitializeOneOff();
+    }
+
+    g_egl_default_display = new egl::Display();
+    g_egl_thread_state_key = gpu::ThreadLocalAlloc();
+  }
+  egl::ThreadState* thread_state = static_cast<egl::ThreadState*>(
+      gpu::ThreadLocalGetValue(g_egl_thread_state_key));
+  if (!thread_state) {
+    thread_state = new egl::ThreadState;
+    gpu::ThreadLocalSetValue(g_egl_thread_state_key, thread_state);
+    ++g_egl_active_thread_count;
+  }
+  return thread_state;
+}
+
+void ThreadState::ReleaseThread() {
+  base::AutoLock lock(g_egl_lock.Get());
+  if (g_egl_active_thread_count == 0)
+    return;
+
+  egl::ThreadState* thread_state = static_cast<egl::ThreadState*>(
+      gpu::ThreadLocalGetValue(g_egl_thread_state_key));
+  if (!thread_state)
+    return;
+
+  --g_egl_active_thread_count;
+  if (g_egl_active_thread_count > 0) {
+    g_egl_default_display->ReleaseCurrent(thread_state);
+    delete thread_state;
+  } else {
+    gpu::ThreadLocalFree(g_egl_thread_state_key);
+
+    // First delete the display object, so that it drops the possible refs to
+    // current context.
+    delete g_egl_default_display;
+    g_egl_default_display = nullptr;
+
+    // We can use Surface and Context without lock, since there's no threads
+    // left anymore. Destroy the current context explicitly, in an attempt to
+    // reduce the number of error messages abandoned context would produce.
+    if (thread_state->current_context()) {
+      Context::MakeCurrent(thread_state->current_context(),
+                           thread_state->current_surface()->gl_surface(),
+                           nullptr, nullptr);
+    }
+    delete thread_state;
+
+    gles2::Terminate();
+#if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
+#if defined(COMPONENT_BUILD)
+    if (g_command_buffer_gles_has_atexit_manager)
+      delete g_exit_manager;
+#else
+    delete g_exit_manager;
+#endif
+    g_exit_manager = nullptr;
+#endif
+  }
+}
+
+ThreadState::ThreadState() : error_code_(EGL_SUCCESS) {}
+
+ThreadState::~ThreadState() {}
+
+EGLint ThreadState::ConsumeErrorCode() {
+  EGLint current_error_code = error_code_;
+  error_code_ = EGL_SUCCESS;
+  return current_error_code;
+}
+
+Display* ThreadState::GetDisplay(EGLDisplay dpy) {
+  if (dpy == g_egl_default_display)
+    return g_egl_default_display;
+  return nullptr;
+}
+
+Display* ThreadState::GetDefaultDisplay() {
+  return g_egl_default_display;
+}
+
+void ThreadState::SetCurrent(Surface* surface, Context* context) {
+  DCHECK((surface == nullptr) == (context == nullptr));
+  if (current_context_) {
+    current_context_->set_is_current_in_some_thread(false);
+    current_surface_->set_is_current_in_some_thread(false);
+  }
+  current_surface_ = surface;
+  current_context_ = context;
+  if (current_context_) {
+    current_context_->set_is_current_in_some_thread(true);
+    current_surface_->set_is_current_in_some_thread(true);
+  }
+}
+
+ThreadState::AutoCurrentContextRestore::AutoCurrentContextRestore(
+    ThreadState* thread_state)
+    : thread_state_(thread_state) {}
+
+ThreadState::AutoCurrentContextRestore::~AutoCurrentContextRestore() {
+  if (Context* current_context = thread_state_->current_context()) {
+    current_context->ApplyCurrentContext(
+        thread_state_->current_surface()->gl_surface());
+  } else {
+    Context::ApplyContextReleased();
+  }
+}
+
+void ThreadState::AutoCurrentContextRestore::SetCurrent(Surface* surface,
+                                                        Context* context) {
+  thread_state_->SetCurrent(surface, context);
+}
+
+}  // namespace egl
diff --git a/gpu/gles2_conform_support/egl/thread_state.h b/gpu/gles2_conform_support/egl/thread_state.h
new file mode 100644
index 0000000..963ac5c6
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/thread_state.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2016 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 GPU_GLES2_CONFORM_SUPPORT_EGL_STATE_H_
+#define GPU_GLES2_CONFORM_SUPPORT_EGL_STATE_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include <EGL/egl.h>
+
+namespace egl {
+
+class Context;
+class Display;
+class Surface;
+
+// Thread-local API state of EGL.
+class ThreadState {
+ public:
+  // Factory getter for the class. Should only be called by the API layer, and
+  // then passed through Display in order to avoid lock issues.
+  static ThreadState* Get();
+  static void ReleaseThread();
+
+  Surface* current_surface() const { return current_surface_.get(); }
+  Context* current_context() const { return current_context_.get(); }
+
+  template <typename T>
+  T ReturnError(EGLint error, T return_value) {
+    error_code_ = error;
+    return return_value;
+  }
+  template <typename T>
+  T ReturnSuccess(T return_value) {
+    error_code_ = EGL_SUCCESS;
+    return return_value;
+  }
+  EGLint ConsumeErrorCode();
+
+  Display* GetDefaultDisplay();
+  Display* GetDisplay(EGLDisplay);
+
+  // RAII class for ensuring that ThreadState current context
+  // is reflected in the gfx:: and gles:: global variables.
+  class AutoCurrentContextRestore {
+   public:
+    AutoCurrentContextRestore(ThreadState*);
+    ~AutoCurrentContextRestore();
+    void SetCurrent(Surface*, Context*);
+
+   private:
+    ThreadState* thread_state_;
+    DISALLOW_COPY_AND_ASSIGN(AutoCurrentContextRestore);
+  };
+
+ private:
+  ThreadState();
+  ~ThreadState();
+  void SetCurrent(Surface*, Context*);
+
+  EGLint error_code_;
+  scoped_refptr<Surface> current_surface_;
+  scoped_refptr<Context> current_context_;
+  DISALLOW_COPY_AND_ASSIGN(ThreadState);
+};
+
+}  // namespace egl
+
+#endif
diff --git a/gpu/gles2_conform_support/gles2_conform_support.gyp b/gpu/gles2_conform_support/gles2_conform_support.gyp
index d4f18708..0316ddb 100644
--- a/gpu/gles2_conform_support/gles2_conform_support.gyp
+++ b/gpu/gles2_conform_support/gles2_conform_support.gyp
@@ -27,6 +27,7 @@
       'type': 'static_library',
       'dependencies': [
         '../../base/base.gyp:base',
+	'../../gpu/command_buffer/command_buffer.gyp:gles2_utils',
         '../../gpu/gpu.gyp:command_buffer_service',
         '../../gpu/gpu.gyp:gles2_implementation_no_check',
         '../../gpu/gpu.gyp:gpu',
@@ -38,11 +39,17 @@
       'sources': [
         'egl/config.cc',
         'egl/config.h',
+        'egl/context.cc',
+        'egl/context.h',
         'egl/display.cc',
         'egl/display.h',
         'egl/egl.cc',
         'egl/surface.cc',
         'egl/surface.h',
+        'egl/test_support.cc',
+        'egl/test_support.h',
+        'egl/thread_state.cc',
+        'egl/thread_state.h',
       ],
       'defines': [
         'EGLAPI=',
diff --git a/gpu/gles2_conform_support/native/egl_native_windowless.cc b/gpu/gles2_conform_support/native/egl_native_windowless.cc
index 725d0a0..94d6daca 100644
--- a/gpu/gles2_conform_support/native/egl_native_windowless.cc
+++ b/gpu/gles2_conform_support/native/egl_native_windowless.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "gpu/gles2_conform_support/egl/display.h"
+#include "gpu/gles2_conform_support/egl/test_support.h"
 
 extern "C" {
 #if defined(GLES2_CONFORM_SUPPORT_ONLY)
@@ -24,8 +24,8 @@
                               EGLDisplay eglDisplay, EGLConfig eglConfig,
                               const char* title, int width, int height,
                               EGLNativeWindowType *pNativeWindow) {
-  egl::Display* display = static_cast<egl::Display*>(eglDisplay);
-  display->SetCreateOffscreen(width, height);
+  CommandBufferGLESSetNextCreateWindowSurfaceCreatesPBuffer(eglDisplay, width,
+                                                            height);
   return GTFtrue;
 }
 
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 8dcbb291..fe2aa61b 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -518,6 +518,7 @@
         '../gpu/gpu.gyp:command_buffer_service',
         '../ui/gfx/gfx.gyp:gfx_geometry',
         '../ui/gl/gl.gyp:gl',
+        'command_buffer/command_buffer.gyp:gles2_utils',
         'gles2_c_lib',
         'gles2_implementation',
       ],
@@ -526,6 +527,8 @@
         # TODO(hendrikw): Move egl out of gles2_conform_support.
         'gles2_conform_support/egl/config.cc',
         'gles2_conform_support/egl/config.h',
+        'gles2_conform_support/egl/context.cc',
+        'gles2_conform_support/egl/context.h',
         'gles2_conform_support/egl/display.cc',
         'gles2_conform_support/egl/display.h',
         'gles2_conform_support/egl/egl.cc',
@@ -533,6 +536,8 @@
         'gles2_conform_support/egl/surface.h',
         'gles2_conform_support/egl/test_support.cc',
         'gles2_conform_support/egl/test_support.h',
+        'gles2_conform_support/egl/thread_state.cc',
+        'gles2_conform_support/egl/thread_state.h',
       ],
           'defines': [
         'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY',
diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc
index 1a6846a1..2429dd1a 100644
--- a/media/audio/mac/audio_low_latency_input_mac.cc
+++ b/media/audio/mac/audio_low_latency_input_mac.cc
@@ -642,6 +642,11 @@
     // only when input audio fails to start.
     UMA_HISTOGRAM_BOOLEAN("Media.Audio.InputBufferSizeWasChangedAudioWorkedMac",
                           buffer_size_was_changed_);
+    // Logs the total number of times RestartAudio() has been called.
+    DVLOG(1) << "Total number of restart attempts: "
+             << total_number_of_restart_attempts_;
+    UMA_HISTOGRAM_COUNTS_1000("Media.Audio.InputRestartAttemptsMac",
+                              total_number_of_restart_attempts_);
     // TODO(henrika): possibly add more values here...
   }
   // Inform the audio manager that we have been closed. This will cause our
@@ -1633,10 +1638,6 @@
   if (last_sample_time_ == 0)
     return;  // No stats gathered to report.
 
-  // TODO(henrika): perhaps add this value to UMA stats as well.
-  DVLOG(1) << "Total number of restart attempts: "
-           << total_number_of_restart_attempts_;
-
   // A value of 0 indicates that we got the buffer size we asked for.
   UMA_HISTOGRAM_COUNTS_10000("Media.Audio.Capture.FramesProvided",
                              number_of_frames_provided_);
diff --git a/third_party/WebKit/LayoutTests/ASANExpectations b/third_party/WebKit/LayoutTests/ASANExpectations
index fb79de5..bbf9d12 100644
--- a/third_party/WebKit/LayoutTests/ASANExpectations
+++ b/third_party/WebKit/LayoutTests/ASANExpectations
@@ -20,6 +20,19 @@
 crbug.com/144118 [ Linux ] plugins/destroy-on-setwindow.html [ Skip ]
 
 
+# heap-use-after-free in bluethooth notifications tests. http://crbug.com/604318
+#0 0xd038118 in size buildtools/third_party/libc++/trunk/include/vector:639:46
+#1 0xd038118 in size base/observer_list.h:114:0
+#2 0xd038118 in might_have_observers base/observer_list.h:232:0
+#3 0xd038118 in DoNotify device/bluetooth/test/mock_bluetooth_gatt_notify_session.cc:44:0
+crbug.com/604318 bluetooth/notifications/concurrent-starts.html [ Skip ]
+crbug.com/604318 bluetooth/notifications/start-before-stop-resolves.html [ Skip ]
+crbug.com/604318 bluetooth/notifications/add-listener-after-promise.html [ Skip ]
+crbug.com/604318 bluetooth/notifications/gc-with-pending-start.html [ Skip ]
+crbug.com/604318 bluetooth/notifications/start-twice-in-a-row.html [ Skip ]
+crbug.com/604318 bluetooth/notifications/start-succeeds.html [ Skip ]
+
+
 # Use-after-free in NPP_DestroyStream, http://crbug.com/166932
 # ==17332== ERROR: AddressSanitizer: heap-use-after-free on address 0x7f48e8a05a58
 # WRITE of size 1 at 0x7f48e8a05a58 thread T0
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 904acfe..49d0d384 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -520,6 +520,7 @@
 crbug.com/108417 imported/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1.html [ Failure ]
 crbug.com/490511 imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/color.html [ Failure Pass ]
 crbug.com/490511 imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/width.html [ Failure Pass ]
+crbug.com/490511 imported/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html [ Failure ]
 crbug.com/490511 imported/web-platform-tests/html/semantics/document-metadata/styling/LinkStyle.html [ Failure Pass ]
 crbug.com/490511 imported/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html [ Failure ]
 crbug.com/525889 imported/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setInterval.html [ Failure ]
@@ -527,21 +528,6 @@
 crbug.com/525889 imported/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html [ Failure ]
 crbug.com/525889 imported/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout.html [ Failure ]
 
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html [ Failure Crash ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html  [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/styles/css-variables/test-001.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/styles/test-003.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/styles/test-010.html [ Failure Crash ]
-crbug.com/413731 imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html [ Failure Crash ]
-
 crbug.com/602483 fast/repaint/delete-into-nested-block.html [ Pass Failure ]
 
 crbug.com/552532 [ Win10 ] fast/replaced/no-focus-ring-embed.html [ Pass Crash ]
@@ -551,12 +537,6 @@
 
 crbug.com/602110 hittesting/border-hittest-with-image-fallback.html [ Failure ]
 
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html [ Failure ]
-crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html [ Failure ]
-crbug.com/505364 crbug.com/520616 imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-009.html [ Failure ]
-
 crbug.com/387740 imported/web-platform-tests/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.html [ Skip ]
 crbug.com/387740 imported/web-platform-tests/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.html [ Skip ]
 crbug.com/387740 imported/web-platform-tests/mediacapture-streams/MediaStreamTrack-end.html [ Skip ]
@@ -574,6 +554,9 @@
 crbug.com/325673 imported/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars.html [ Failure Timeout ]
 crbug.com/325673 imported/web-platform-tests/custom-elements/concepts/custom-elements-type-naming.html [ Failure ]
 
+crbug.com/396825 fast/repaint/outline-change-invalidation.html [ NeedsManualRebaseline ]
+crbug.com/396825 fast/repaint/outline-clip-change.html [ NeedsManualRebaseline ]
+
 crbug.com/542660 fast/css/absolute-inline-alignment-2.html [ Failure ]
 
 # Ref tests that needs investigation.
@@ -584,6 +567,11 @@
 crbug.com/404597 fast/css/text-overflow-ellipsis-button.html [ Pass Failure ]
 crbug.com/404597 [ Win ] fast/selectors/007a.html [ Pass Failure ]
 
+# Web Components related tests (Shadow DOM, Custom Elements) failures.
+crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/styles/test-003.html [ Failure ]
+crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html [ Failure ]
+crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html [ Failure ]
+crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html [ Failure ]
 crbug.com/505364 imported/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html [ Failure ]
 
 crbug.com/517840 imported/web-platform-tests/webrtc/rtcpeerconnection/rtcpeerconnection-idl.html [ Failure Timeout ]
@@ -1525,7 +1513,6 @@
 crbug.com/601166 [ Mac10.9 ]  ietestcenter/css3/text/textshadow-004.htm [ Failure ]
 
 crbug.com/600261 imported/web-platform-tests/mediacapture-streams/GUM-deny.html [ Failure ]
-crbug.com/600261 imported/web-platform-tests/mediacapture-streams/MediaDevices-getUserMedia.html [ Failure ]
 crbug.com/600261 imported/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.html [ Failure ]
 
 crbug.com/593679 virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ NeedsManualRebaseline ]
@@ -1538,4 +1525,3 @@
 crbug.com/600248 imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming-currentIteration.html [ Crash Failure ]
 crbug.com/600248 imported/web-platform-tests/web-animations/animation-effect-timing/endDelay.html [ Failure ]
 crbug.com/600248 imported/web-platform-tests/web-animations/animation/constructor.html [ Failure Timeout ]
-crbug.com/600248 imported/web-platform-tests/web-animations/animation-node/idlharness.html [ Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 0a61e3d..55b9f4be 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -197,6 +197,7 @@
 imported/web-platform-tests/app-uri [ Skip ]
 imported/web-platform-tests/battery-status [ Skip ]
 imported/web-platform-tests/common [ Skip ]
+imported/web-platform-tests/compat [ Skip ]
 imported/web-platform-tests/config.default.json [ Skip ]
 imported/web-platform-tests/conformance-checkers [ Skip ]
 imported/web-platform-tests/content-security-policy [ Skip ]
@@ -221,6 +222,7 @@
 imported/web-platform-tests/fonts [ Skip ]
 ## Owners: bajones@chromium.org
 # imported/web-platform-tests/gamepad [ Pass ]
+imported/web-platform-tests/generic-sensor [ Skip ]
 imported/web-platform-tests/geolocation-API [ Skip ]
 ## Owners: jsbell@chromium.org
 # imported/web-platform-tests/hr-time [ Pass ]
@@ -362,6 +364,7 @@
 imported/web-platform-tests/html/browsers/browsing-the-web/read-text/load-text-plain.html [ Skip ]
 
 # crbug.com/498120: Using absolute URL links.
+imported/web-platform-tests/dom/events/EventTarget-dispatchEvent.html [ Skip ]
 imported/web-platform-tests/html/browsers/history/the-location-interface/location-stringifier.html [ Skip ]
 imported/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-07.html [ Skip ]
 imported/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.currentScript.sub.html [ Skip ]
@@ -611,8 +614,14 @@
 imported/web-platform-tests/html/browsers/history/the-history-interface/008.html [ Skip ]
 imported/web-platform-tests/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain.html [ Skip ]
 imported/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html [ Skip ]
+imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-utf8.js [ Skip ]
+imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-windows1250.js [ Skip ]
 imported/web-platform-tests/html/semantics/scripting-1/the-script-element/script-charset-01.html [ Skip ]
 imported/web-platform-tests/html/semantics/scripting-1/the-script-element/script-charset-02.html [ Skip ]
+imported/web-platform-tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py [ Skip ]
+imported/web-platform-tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html [ Skip ]
+imported/web-platform-tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py [ Skip ]
+imported/web-platform-tests/html/semantics/scripting-1/the-script-element/serve-with-content-type.py [ Skip ]
 
 # Requires http server. Moved the following test to http/tests/custom-elements/.
 imported/web-platform-tests/custom-elements/creating-and-passing-registries/no-registry-test.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/fast/layout/border-image-outset-no-relayout-expected.txt b/third_party/WebKit/LayoutTests/fast/layout/border-image-outset-no-relayout-expected.txt
new file mode 100644
index 0000000..43e5eeed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/layout/border-image-outset-no-relayout-expected.txt
@@ -0,0 +1,4 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/layout/border-image-outset-no-relayout.html b/third_party/WebKit/LayoutTests/fast/layout/border-image-outset-no-relayout.html
new file mode 100644
index 0000000..94604da7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/layout/border-image-outset-no-relayout.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<style>
+    div {
+        border-width: 21px 30px 30px 21px;
+        width: 75px;
+        height: 75px;
+        display: inline-block;
+        border-image-source: url("../borders/resources/border-image.png");
+        border-image-slice: 21 30 30 21 fill;
+        border-image-width: 1;
+        border-image-outset: 1;
+    }
+</style>
+<script src="../../resources/js-test.js"></script>
+<div id="test"></div>
+<script>
+// Force style recalc and layout.
+document.body.offsetTop;
+
+if (window.internals)
+    shouldBe("window.internals.needsLayoutCount()", "0", true);
+
+// Changing border-image-outset will cause a repaint but no layout.
+document.getElementById("test").style['border-image-outset'] = '5';
+
+if (window.internals) {
+    shouldBe("window.internals.needsLayoutCount()", "0", true);
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/layout/outline-no-relayout-expected.txt b/third_party/WebKit/LayoutTests/fast/layout/outline-no-relayout-expected.txt
new file mode 100644
index 0000000..43e5eeed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/layout/outline-no-relayout-expected.txt
@@ -0,0 +1,4 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/layout/outline-no-relayout.html b/third_party/WebKit/LayoutTests/fast/layout/outline-no-relayout.html
new file mode 100644
index 0000000..37b133c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/layout/outline-no-relayout.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script src="../../resources/js-test.js"></script>
+<div id="test" style="background-color: green; width: 100px; height: 100px;"></div>
+<script>
+// Force style recalc and layout.
+document.body.offsetTop;
+
+if (window.internals)
+    shouldBe("window.internals.needsLayoutCount()", "0", true);
+
+// Adding box-shadow will cause a repaint but no layout.
+document.getElementById("test").style['outline'] = 'solid black 5px;';
+
+if (window.internals) {
+    shouldBe("window.internals.needsLayoutCount()", "0", true);
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/layout/shadow-box-no-relayout-expected.txt b/third_party/WebKit/LayoutTests/fast/layout/shadow-box-no-relayout-expected.txt
new file mode 100644
index 0000000..43e5eeed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/layout/shadow-box-no-relayout-expected.txt
@@ -0,0 +1,4 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/layout/shadow-box-no-relayout.html b/third_party/WebKit/LayoutTests/fast/layout/shadow-box-no-relayout.html
new file mode 100644
index 0000000..9698f9cb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/layout/shadow-box-no-relayout.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script src="../../resources/js-test.js"></script>
+<div id="test" style="background-color: green; width: 100px; height: 100px;"></div>
+<script>
+// Force style recalc and layout.
+document.body.offsetTop;
+
+if (window.internals)
+    shouldBe("window.internals.needsLayoutCount()", "0", true);
+
+// Adding box-shadow will cause a repaint but no layout.
+document.getElementById("test").style['box-shadow'] = '5px 5px 5px rgba(0,0,0,0.3)';
+
+if (window.internals) {
+    shouldBe("window.internals.needsLayoutCount()", "0", true);
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-add-repaint-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-add-repaint-expected.txt
new file mode 100644
index 0000000..cc100b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-add-repaint-expected.txt
@@ -0,0 +1,18 @@
+{
+  "bounds": [800, 600],
+  "children": [
+    {
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='test'",
+          "rect": [8, 8, 75, 75],
+          "reason": "style change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-add-repaint.html b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-add-repaint.html
new file mode 100644
index 0000000..7ef7f65e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-add-repaint.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<style>
+    div {
+        border-width: 21px 30px 30px 21px;
+        width: 75px;
+        height: 75px;
+        display: inline-block;
+        border-image-source: url("../borders/resources/border-image.png");
+        border-image-slice: 21 30 30 21 fill;
+        border-image-width: 1;
+    }
+</style>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+    function repaintTest()
+    {
+        // Adding border-image-outset will cause a repaint but no layout.
+        document.getElementById("test").style['border-image-outset'] = '5';
+    }
+    window.onload = runRepaintTest;
+</script>
+<div id="test"></div>
+<p>
+Tests the repainting of border-image-outset when added.
+</p>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-change-repaint-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-change-repaint-expected.txt
new file mode 100644
index 0000000..cc100b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-change-repaint-expected.txt
@@ -0,0 +1,18 @@
+{
+  "bounds": [800, 600],
+  "children": [
+    {
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='test'",
+          "rect": [8, 8, 75, 75],
+          "reason": "style change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-change-repaint.html b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-change-repaint.html
new file mode 100644
index 0000000..219612c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/border-image-outset-change-repaint.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<style>
+    div {
+        border-width: 21px 30px 30px 21px;
+        width: 75px;
+        height: 75px;
+        display: inline-block;
+        border-image-source: url("../borders/resources/border-image.png");
+        border-image-slice: 21 30 30 21 fill;
+        border-image-width: 1;
+        border-image-outset: 1;
+    }
+</style>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+    function repaintTest()
+    {
+        // Changing border-image-outset will cause a repaint but no layout.
+        document.getElementById("test").style['border-image-outset'] = '5';
+    }
+    window.onload = runRepaintTest;
+</script>
+<div id="test"></div>
+<p>
+Tests the repainting of border-image-outset when changed.
+</p>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-add-repaint-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-add-repaint-expected.txt
new file mode 100644
index 0000000..7379aa2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-add-repaint-expected.txt
@@ -0,0 +1,18 @@
+{
+  "bounds": [800, 600],
+  "children": [
+    {
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='test'",
+          "rect": [8, 8, 110, 110],
+          "reason": "style change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-add-repaint.html b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-add-repaint.html
new file mode 100644
index 0000000..7b7e145c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-add-repaint.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+    function repaintTest()
+    {
+        // Adding box-shadow will cause a repaint but no layout.
+        document.getElementById("test").style['box-shadow'] = '5px 5px 5px rgba(0,0,0,0.3)';
+    }
+    window.onload = runRepaintTest;
+</script>
+<div id="test" style="background-color: green; width: 100px; height: 100px;"></div>
+<p>
+Tests the repainting of box shadows when added.
+</p>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-change-repaint-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-change-repaint-expected.txt
new file mode 100644
index 0000000..f0f4e2e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-change-repaint-expected.txt
@@ -0,0 +1,18 @@
+{
+  "bounds": [800, 600],
+  "children": [
+    {
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='test'",
+          "rect": [8, 8, 120, 120],
+          "reason": "style change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-change-repaint.html b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-change-repaint.html
new file mode 100644
index 0000000..54a771d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/box-shadow-change-repaint.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+    function repaintTest()
+    {
+        // Adding box-shadow will cause a repaint but no layout.
+        document.getElementById("test").style['box-shadow'] = '5px 5px 5px rgba(0,0,0,0.3)';
+    }
+    window.onload = runRepaintTest;
+</script>
+<div id="test" style="background-color: green; width: 100px; height: 100px; box-shadow: 10px 10px 10px rgba(0,0,0,0.3);"></div>
+<p>
+Tests the repainting of box shadows when changed.
+</p>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/outline-add-repaint-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/outline-add-repaint-expected.txt
new file mode 100644
index 0000000..3046b67f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/outline-add-repaint-expected.txt
@@ -0,0 +1,28 @@
+{
+  "bounds": [800, 600],
+  "children": [
+    {
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow BODY",
+          "rect": [-10, -10, 810, 120],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutBlockFlow HTML",
+          "rect": [-10, -10, 810, 120],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='test'",
+          "rect": [-10, -10, 120, 120],
+          "reason": "style change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/outline-add-repaint.html b/third_party/WebKit/LayoutTests/fast/repaint/outline-add-repaint.html
new file mode 100644
index 0000000..c024074
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/outline-add-repaint.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+    function repaintTest()
+    {
+        // Adding outline will cause a repaint but no layout.
+        document.getElementById("test").style['outline'] = 'solid black 10px';
+    }
+    window.onload = runRepaintTest;
+</script>
+<style>
+    body {
+        margin: 0;
+    }
+</style>
+<div id="test" style="background-color: green; width: 100px; height: 100px;"></div>
+<!-- Tests the repainting of outline when added. -->
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/outline-change-offset-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/outline-change-offset-expected.txt
index ff9e960..995270b 100644
--- a/third_party/WebKit/LayoutTests/fast/repaint/outline-change-offset-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/repaint/outline-change-offset-expected.txt
@@ -7,11 +7,6 @@
       "drawsContent": true,
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow (positioned) DIV id='indicator'",
-          "rect": [35, 35, 130, 130],
-          "reason": "outline"
-        },
-        {
           "object": "LayoutBlockFlow (positioned) DIV id='target'",
           "rect": [35, 35, 130, 130],
           "reason": "style change"
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/outline-change-repaint-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/outline-change-repaint-expected.txt
new file mode 100644
index 0000000..3046b67f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/outline-change-repaint-expected.txt
@@ -0,0 +1,28 @@
+{
+  "bounds": [800, 600],
+  "children": [
+    {
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow BODY",
+          "rect": [-10, -10, 810, 120],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutBlockFlow HTML",
+          "rect": [-10, -10, 810, 120],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='test'",
+          "rect": [-10, -10, 120, 120],
+          "reason": "style change"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/outline-change-repaint.html b/third_party/WebKit/LayoutTests/fast/repaint/outline-change-repaint.html
new file mode 100644
index 0000000..1a56de9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/outline-change-repaint.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+    function repaintTest()
+    {
+        // Changing outline will cause a repaint but no layout.
+        document.getElementById("test").style['outline'] = 'solid black 10px';
+    }
+    window.onload = runRepaintTest;
+</script>
+<style>
+    body {
+        margin: 0;
+    }
+</style>
+<div id="test" style="background-color: green; width: 100px; height: 100px; outline: solid black 5px;"></div>
+<!-- Tests the repainting of outline when changed. -->
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration-service-worker-attributes.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration-service-worker-attributes.html
index dce8b11..2ee1784 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration-service-worker-attributes.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/registration-service-worker-attributes.html
@@ -3,14 +3,18 @@
 <script src="../resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.js"></script>
 <script>
-async_test(function(t) {
+promise_test(function(t) {
     var scope = 'resources/scope/installing-waiting-active-after-registration';
     var worker_url = 'resources/empty-worker.js';
     var expected_url = normalizeURL(worker_url);
+    var installing_worker;
+    var registration;
 
-    service_worker_unregister_and_register(t, worker_url, scope)
+    return service_worker_unregister_and_register(t, worker_url, scope)
       .then(function(r) {
+          add_completion_callback(function() { r.unregister(); });
           registration = r;
+          installing_worker = registration.installing;
           assert_equals(registration.installing.scriptURL, expected_url,
                         'installing before updatefound');
           assert_equals(registration.waiting, null,
@@ -19,8 +23,8 @@
                         'active before updatefound');
           return wait_for_update(t, registration);
         })
-      .then(function(worker) {
-          assert_equals(registration.installing.scriptURL, expected_url,
+      .then(function() {
+          assert_equals(registration.installing, installing_worker,
                         'installing after updatefound');
           assert_equals(registration.waiting, null,
                         'waiting after updatefound');
@@ -31,7 +35,7 @@
       .then(function() {
           assert_equals(registration.installing, null,
                         'installing after installed');
-          assert_equals(registration.waiting.scriptURL, expected_url,
+          assert_equals(registration.waiting, installing_worker,
                         'waiting after installed');
           assert_equals(registration.active, null,
                         'active after installed');
@@ -42,7 +46,7 @@
                         'installing after activated');
           assert_equals(registration.waiting, null,
                         'waiting after activated');
-          assert_equals(registration.active.scriptURL, expected_url,
+          assert_equals(registration.active, installing_worker,
                         'active after activated');
           return Promise.all([
               wait_for_state(t, registration.active, 'redundant'),
@@ -60,8 +64,6 @@
           // resolved, this will be gone.
           assert_equals(registration.active, null,
                         'active should be null after redundant');
-          t.done();
-        })
-      .catch(unreached_rejection(t));
+        });
   }, 'installing/waiting/active after registration');
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/synced-state.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/synced-state.html
index 63a6e5b23..52940e0d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/synced-state.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/synced-state.html
@@ -5,53 +5,70 @@
 <script src="resources/test-helpers.js"></script>
 <script>
 // Tests that ServiceWorker objects representing the same Service Worker
-// entity have the same state. JS object equality is not tested, since the spec
-// does not require it.
+// entity have the same state. JS-level equality is now required according to
+// the spec.
 promise_test(function(t) {
     var scope = 'resources/synced-state';
     var script = 'resources/empty-worker.js';
+    var registration;
     return service_worker_unregister_and_register(t, script, scope)
-      .then(function(registration) {
+      .then(function(r) {
+          var step = 0;
+          registration = r;
+          add_completion_callback(function() { r.unregister(); });
           return new Promise(function(resolve) {
-              var step = 0;
-              registration.installing.addEventListener('statechange',
-                                                       function(e) {
+              r.installing.addEventListener('statechange', function(e) {
                   step++;
                   if (step == 1) {
                     assert_equals(e.currentTarget.state, 'installed',
                                   'original SW should be installed');
-                    assert_equals(registration.installing, null,
+                    assert_equals(r.installing, null,
                                   'in installed, .installing should be null');
-                    assert_equals(registration.waiting.state, 'installed',
-                                  'in installed, .waiting should be installed');
-                    assert_equals(registration.active, null,
+                    assert_equals(r.waiting.state, 'installed',
+                                  'in installed, the state of .waiting ' +
+                                  'should be installed');
+                    assert_equals(r.active, null,
                                   'in installed, .active should be null');
+                    assert_equals(r.waiting, e.currentTarget,
+                                  '.waiting should be equal to the original ' +
+                                  'SW in installed');
                   } else if (step == 2) {
                     assert_equals(e.currentTarget.state, 'activating',
                                   'original SW should be activating');
-                    assert_equals(registration.installing, null,
+                    assert_equals(r.installing, null,
                                   'in activating, .installing should be null');
-                    assert_equals(registration.waiting, null,
+                    assert_equals(r.waiting, null,
                                   'in activating, .waiting should be null');
-                    assert_equals(
-                        registration.active.state, 'activating',
-                        'in activating, .active should be activating');
+                    assert_equals(r.active.state, 'activating',
+                                  'in activating, the state of .active ' +
+                                  'should be activating');
+                    assert_equals(r.active, e.currentTarget,
+                                  '.active should be equal to the original ' +
+                                  'SW in activating');
                   } else if (step == 3) {
                     assert_equals(e.currentTarget.state, 'activated',
                                   'original SW should be activated');
-                    assert_equals(registration.installing, null,
+                    assert_equals(r.installing, null,
                                   'in activated, .installing should be null');
-                    assert_equals(registration.waiting, null,
+                    assert_equals(r.waiting, null,
                                   'in activated, .waiting should be null');
-                    assert_equals(registration.active.state, 'activated',
-                                  'in activated .active should be activated');
+                    assert_equals(r.active.state, 'activated',
+                                  'in activated, the state of .active should ' +
+                                  'be activated');
+                    assert_equals(r.active, e.currentTarget,
+                                  '.active should be equal to the original ' +
+                                  'SW in activated');
                     resolve();
                   }
-                })
-            })
+                });
+            });
         })
       .then(function() {
-          return service_worker_unregister_and_done(t, scope);
+          return navigator.serviceWorker.getRegistration(scope);
+        })
+      .then(function(r) {
+          assert_equals(r, registration, 'getRegistration should return the ' +
+                                         'same object with the registered one');
         });
   }, 'worker objects for the same entity have the same state');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-as-proto-length-get-throws.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-as-proto-length-get-throws.html
new file mode 100644
index 0000000..85f797b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/collections/HTMLCollection-as-proto-length-get-throws.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Make sure browsers throw when getting .length on some random object whose proto is an HTMLCollection</title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<script>
+test(function() {
+  var obj = Object.create(document.getElementsByTagName("script"));
+  assert_throws(new TypeError(), function() {
+    obj.length;
+  });
+}, "HTMLcollection as a prototype should not allow getting .length on the base object")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors-expected.txt
deleted file mode 100644
index a3966081..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-This is a testharness.js-based test.
-PASS Event constructors 
-PASS Event constructors 1 
-PASS Event constructors 2 
-PASS Event constructors 3 
-FAIL Event constructors 4 Failed to construct 'Event': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
-PASS Event constructors 5 
-PASS Event constructors 6 
-PASS Event constructors 7 
-PASS Event constructors 8 
-PASS Event constructors 9 
-PASS Event constructors 10 
-PASS Event constructors 11 
-PASS Event constructors 12 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors.html
index a3247af..5732d7f3 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/events/Event-constructors.html
@@ -42,17 +42,8 @@
   assert_true("initEvent" in ev)
 })
 test(function() {
-  var ev = Event("test")
-  assert_equals(ev.type, "test")
-  assert_equals(ev.target, null)
-  assert_equals(ev.currentTarget, null)
-  assert_equals(ev.eventPhase, Event.NONE)
-  assert_equals(ev.bubbles, false)
-  assert_equals(ev.cancelable, false)
-  assert_equals(ev.defaultPrevented, false)
-  assert_equals(ev.isTrusted, false)
-  assert_true(ev.timeStamp > 0)
-  assert_true("initEvent" in ev)
+  assert_throws(new TypeError(), function() { Event("test") },
+                'Calling Event constructor without "new" must throw');
 })
 test(function() {
   var ev = new Event("I am an event", { bubbles: true, cancelable: false})
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces-expected.txt
index ee028d9..32a49ad 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces-expected.txt
@@ -100,8 +100,8 @@
 PASS EventTarget interface object name 
 FAIL EventTarget interface: existence and properties of interface prototype object assert_equals: class string of EventTarget.prototype expected "[object EventTargetPrototype]" but got "[object EventTarget]"
 PASS EventTarget interface: existence and properties of interface prototype object's "constructor" property 
-PASS EventTarget interface: operation addEventListener(DOMString,EventListener,boolean) 
-PASS EventTarget interface: operation removeEventListener(DOMString,EventListener,boolean) 
+PASS EventTarget interface: operation addEventListener(DOMString,EventListener,[object Object],[object Object]) 
+PASS EventTarget interface: operation removeEventListener(DOMString,EventListener,[object Object],[object Object]) 
 PASS EventTarget interface: operation dispatchEvent(Event) 
 PASS EventListener interface: existence and properties of interface object 
 PASS EventListener interface: existence and properties of interface prototype object 
@@ -188,6 +188,7 @@
 PASS Node interface: attribute nodeType 
 PASS Node interface: attribute nodeName 
 PASS Node interface: attribute baseURI 
+PASS Node interface: attribute isConnected 
 PASS Node interface: attribute ownerDocument 
 PASS Node interface: attribute rootNode 
 PASS Node interface: attribute parentNode 
@@ -203,6 +204,7 @@
 PASS Node interface: operation normalize() 
 PASS Node interface: operation cloneNode(boolean) 
 PASS Node interface: operation isEqualNode(Node) 
+PASS Node interface: operation isSameNode(Node) 
 PASS Node interface: constant DOCUMENT_POSITION_DISCONNECTED on interface object 
 PASS Node interface: constant DOCUMENT_POSITION_DISCONNECTED on interface prototype object 
 PASS Node interface: constant DOCUMENT_POSITION_PRECEDING on interface object 
@@ -243,8 +245,8 @@
 PASS Document interface: operation getElementsByTagName(DOMString) 
 PASS Document interface: operation getElementsByTagNameNS(DOMString,DOMString) 
 PASS Document interface: operation getElementsByClassName(DOMString) 
-PASS Document interface: operation createElement(DOMString) 
-PASS Document interface: operation createElementNS(DOMString,DOMString) 
+PASS Document interface: operation createElement(DOMString,ElementCreationOptions) 
+PASS Document interface: operation createElementNS(DOMString,DOMString,ElementCreationOptions) 
 PASS Document interface: operation createDocumentFragment() 
 PASS Document interface: operation createTextNode(DOMString) 
 PASS Document interface: operation createComment(DOMString) 
@@ -264,8 +266,6 @@
 PASS Document interface: attribute childElementCount 
 FAIL Document interface: operation prepend([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "prepend" missing
 FAIL Document interface: operation append([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "append" missing
-FAIL Document interface: operation query(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "query" missing
-FAIL Document interface: operation queryAll(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "queryAll" missing
 PASS Document interface: operation querySelector(DOMString) 
 PASS Document interface: operation querySelectorAll(DOMString) 
 FAIL Document must be primary interface of new Document() assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
@@ -288,9 +288,9 @@
 FAIL Document interface: new Document() must inherit property "getElementsByClassName" with the proper type (13) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: calling getElementsByClassName(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: new Document() must inherit property "createElement" with the proper type (14) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createElement(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Document interface: calling createElement(DOMString,ElementCreationOptions) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: new Document() must inherit property "createElementNS" with the proper type (15) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createElementNS(DOMString,DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Document interface: calling createElementNS(DOMString,DOMString,ElementCreationOptions) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: new Document() must inherit property "createDocumentFragment" with the proper type (16) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: new Document() must inherit property "createTextNode" with the proper type (17) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: calling createTextNode(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
@@ -323,13 +323,9 @@
 FAIL Document interface: calling prepend([object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: new Document() must inherit property "append" with the proper type (34) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: calling append([object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "query" with the proper type (35) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling query(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "queryAll" with the proper type (36) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling queryAll(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "querySelector" with the proper type (37) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Document interface: new Document() must inherit property "querySelector" with the proper type (35) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: calling querySelector(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "querySelectorAll" with the proper type (38) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Document interface: new Document() must inherit property "querySelectorAll" with the proper type (36) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Document interface: calling querySelectorAll(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: new Document() must inherit property "ELEMENT_NODE" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: new Document() must inherit property "ATTRIBUTE_NODE" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
@@ -346,51 +342,54 @@
 FAIL Node interface: new Document() must inherit property "nodeType" with the proper type (12) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: new Document() must inherit property "nodeName" with the proper type (13) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: new Document() must inherit property "baseURI" with the proper type (14) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "ownerDocument" with the proper type (15) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "rootNode" with the proper type (16) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "parentNode" with the proper type (17) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "parentElement" with the proper type (18) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "hasChildNodes" with the proper type (19) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "childNodes" with the proper type (20) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "firstChild" with the proper type (21) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "lastChild" with the proper type (22) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "previousSibling" with the proper type (23) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "nextSibling" with the proper type (24) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "nodeValue" with the proper type (25) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "textContent" with the proper type (26) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "normalize" with the proper type (27) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "cloneNode" with the proper type (28) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "isConnected" with the proper type (15) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "ownerDocument" with the proper type (16) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "rootNode" with the proper type (17) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "parentNode" with the proper type (18) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "parentElement" with the proper type (19) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "hasChildNodes" with the proper type (20) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "childNodes" with the proper type (21) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "firstChild" with the proper type (22) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "lastChild" with the proper type (23) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "previousSibling" with the proper type (24) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "nextSibling" with the proper type (25) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "nodeValue" with the proper type (26) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "textContent" with the proper type (27) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "normalize" with the proper type (28) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "cloneNode" with the proper type (29) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling cloneNode(boolean) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "isEqualNode" with the proper type (29) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "isEqualNode" with the proper type (30) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling isEqualNode(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "compareDocumentPosition" with the proper type (36) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "isSameNode" with the proper type (31) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: calling isSameNode(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "compareDocumentPosition" with the proper type (38) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling compareDocumentPosition(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "contains" with the proper type (37) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "contains" with the proper type (39) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling contains(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "lookupPrefix" with the proper type (38) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "lookupPrefix" with the proper type (40) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling lookupPrefix(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "lookupNamespaceURI" with the proper type (39) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "lookupNamespaceURI" with the proper type (41) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling lookupNamespaceURI(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "isDefaultNamespace" with the proper type (40) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "isDefaultNamespace" with the proper type (42) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling isDefaultNamespace(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "insertBefore" with the proper type (41) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "insertBefore" with the proper type (43) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling insertBefore(Node,Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "appendChild" with the proper type (42) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "appendChild" with the proper type (44) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling appendChild(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "replaceChild" with the proper type (43) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "replaceChild" with the proper type (45) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling replaceChild(Node,Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "removeChild" with the proper type (44) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL Node interface: new Document() must inherit property "removeChild" with the proper type (46) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL Node interface: calling removeChild(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL EventTarget interface: new Document() must inherit property "addEventListener" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL EventTarget interface: new Document() must inherit property "removeEventListener" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+FAIL EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL EventTarget interface: new Document() must inherit property "dispatchEvent" with the proper type (2) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 FAIL EventTarget interface: calling dispatchEvent(Event) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
 PASS XMLDocument interface: existence and properties of interface object 
@@ -418,9 +417,9 @@
 PASS Document interface: xmlDoc must inherit property "getElementsByClassName" with the proper type (13) 
 PASS Document interface: calling getElementsByClassName(DOMString) on xmlDoc with too few arguments must throw TypeError 
 PASS Document interface: xmlDoc must inherit property "createElement" with the proper type (14) 
-PASS Document interface: calling createElement(DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: calling createElement(DOMString,ElementCreationOptions) on xmlDoc with too few arguments must throw TypeError 
 PASS Document interface: xmlDoc must inherit property "createElementNS" with the proper type (15) 
-PASS Document interface: calling createElementNS(DOMString,DOMString) on xmlDoc with too few arguments must throw TypeError 
+PASS Document interface: calling createElementNS(DOMString,DOMString,ElementCreationOptions) on xmlDoc with too few arguments must throw TypeError 
 PASS Document interface: xmlDoc must inherit property "createDocumentFragment" with the proper type (16) 
 PASS Document interface: xmlDoc must inherit property "createTextNode" with the proper type (17) 
 PASS Document interface: calling createTextNode(DOMString) on xmlDoc with too few arguments must throw TypeError 
@@ -453,13 +452,9 @@
 FAIL Document interface: calling prepend([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "prepend" not found in prototype chain
 FAIL Document interface: xmlDoc must inherit property "append" with the proper type (34) assert_inherits: property "append" not found in prototype chain
 FAIL Document interface: calling append([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "append" not found in prototype chain
-FAIL Document interface: xmlDoc must inherit property "query" with the proper type (35) assert_inherits: property "query" not found in prototype chain
-FAIL Document interface: calling query(DOMString) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "query" not found in prototype chain
-FAIL Document interface: xmlDoc must inherit property "queryAll" with the proper type (36) assert_inherits: property "queryAll" not found in prototype chain
-FAIL Document interface: calling queryAll(DOMString) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "queryAll" not found in prototype chain
-PASS Document interface: xmlDoc must inherit property "querySelector" with the proper type (37) 
+PASS Document interface: xmlDoc must inherit property "querySelector" with the proper type (35) 
 PASS Document interface: calling querySelector(DOMString) on xmlDoc with too few arguments must throw TypeError 
-PASS Document interface: xmlDoc must inherit property "querySelectorAll" with the proper type (38) 
+PASS Document interface: xmlDoc must inherit property "querySelectorAll" with the proper type (36) 
 PASS Document interface: calling querySelectorAll(DOMString) on xmlDoc with too few arguments must throw TypeError 
 PASS Node interface: xmlDoc must inherit property "ELEMENT_NODE" with the proper type (0) 
 PASS Node interface: xmlDoc must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
@@ -475,52 +470,55 @@
 PASS Node interface: xmlDoc must inherit property "NOTATION_NODE" with the proper type (11) 
 PASS Node interface: xmlDoc must inherit property "nodeType" with the proper type (12) 
 PASS Node interface: xmlDoc must inherit property "nodeName" with the proper type (13) 
-PASS Node interface: xmlDoc must inherit property "baseURI" with the proper type (14) 
-PASS Node interface: xmlDoc must inherit property "ownerDocument" with the proper type (15) 
-PASS Node interface: xmlDoc must inherit property "rootNode" with the proper type (16) 
-PASS Node interface: xmlDoc must inherit property "parentNode" with the proper type (17) 
-PASS Node interface: xmlDoc must inherit property "parentElement" with the proper type (18) 
-PASS Node interface: xmlDoc must inherit property "hasChildNodes" with the proper type (19) 
-PASS Node interface: xmlDoc must inherit property "childNodes" with the proper type (20) 
-PASS Node interface: xmlDoc must inherit property "firstChild" with the proper type (21) 
-PASS Node interface: xmlDoc must inherit property "lastChild" with the proper type (22) 
-PASS Node interface: xmlDoc must inherit property "previousSibling" with the proper type (23) 
-PASS Node interface: xmlDoc must inherit property "nextSibling" with the proper type (24) 
-PASS Node interface: xmlDoc must inherit property "nodeValue" with the proper type (25) 
-PASS Node interface: xmlDoc must inherit property "textContent" with the proper type (26) 
-PASS Node interface: xmlDoc must inherit property "normalize" with the proper type (27) 
-PASS Node interface: xmlDoc must inherit property "cloneNode" with the proper type (28) 
+FAIL Node interface: xmlDoc must inherit property "baseURI" with the proper type (14) assert_equals: expected "string" but got "object"
+PASS Node interface: xmlDoc must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: xmlDoc must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: xmlDoc must inherit property "rootNode" with the proper type (17) 
+PASS Node interface: xmlDoc must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: xmlDoc must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: xmlDoc must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: xmlDoc must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: xmlDoc must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: xmlDoc must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: xmlDoc must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: xmlDoc must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: xmlDoc must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: xmlDoc must inherit property "textContent" with the proper type (27) 
+PASS Node interface: xmlDoc must inherit property "normalize" with the proper type (28) 
+PASS Node interface: xmlDoc must inherit property "cloneNode" with the proper type (29) 
 PASS Node interface: calling cloneNode(boolean) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "isEqualNode" with the proper type (29) 
+PASS Node interface: xmlDoc must inherit property "isEqualNode" with the proper type (30) 
 PASS Node interface: calling isEqualNode(Node) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) 
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) 
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) 
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) 
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) 
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) 
-PASS Node interface: xmlDoc must inherit property "compareDocumentPosition" with the proper type (36) 
+PASS Node interface: xmlDoc must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on xmlDoc with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: xmlDoc must inherit property "compareDocumentPosition" with the proper type (38) 
 PASS Node interface: calling compareDocumentPosition(Node) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "contains" with the proper type (37) 
+PASS Node interface: xmlDoc must inherit property "contains" with the proper type (39) 
 PASS Node interface: calling contains(Node) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "lookupPrefix" with the proper type (38) 
+PASS Node interface: xmlDoc must inherit property "lookupPrefix" with the proper type (40) 
 PASS Node interface: calling lookupPrefix(DOMString) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "lookupNamespaceURI" with the proper type (39) 
+PASS Node interface: xmlDoc must inherit property "lookupNamespaceURI" with the proper type (41) 
 PASS Node interface: calling lookupNamespaceURI(DOMString) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "isDefaultNamespace" with the proper type (40) 
+PASS Node interface: xmlDoc must inherit property "isDefaultNamespace" with the proper type (42) 
 PASS Node interface: calling isDefaultNamespace(DOMString) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "insertBefore" with the proper type (41) 
+PASS Node interface: xmlDoc must inherit property "insertBefore" with the proper type (43) 
 PASS Node interface: calling insertBefore(Node,Node) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "appendChild" with the proper type (42) 
+PASS Node interface: xmlDoc must inherit property "appendChild" with the proper type (44) 
 PASS Node interface: calling appendChild(Node) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "replaceChild" with the proper type (43) 
+PASS Node interface: xmlDoc must inherit property "replaceChild" with the proper type (45) 
 PASS Node interface: calling replaceChild(Node,Node) on xmlDoc with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc must inherit property "removeChild" with the proper type (44) 
+PASS Node interface: xmlDoc must inherit property "removeChild" with the proper type (46) 
 PASS Node interface: calling removeChild(Node) on xmlDoc with too few arguments must throw TypeError 
 PASS EventTarget interface: xmlDoc must inherit property "addEventListener" with the proper type (0) 
-PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on xmlDoc with too few arguments must throw TypeError 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError 
 PASS EventTarget interface: xmlDoc must inherit property "removeEventListener" with the proper type (1) 
-PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on xmlDoc with too few arguments must throw TypeError 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError 
 PASS EventTarget interface: xmlDoc must inherit property "dispatchEvent" with the proper type (2) 
 PASS EventTarget interface: calling dispatchEvent(Event) on xmlDoc with too few arguments must throw TypeError 
 PASS DOMImplementation interface: existence and properties of interface object 
@@ -541,104 +539,6 @@
 PASS DOMImplementation interface: document.implementation must inherit property "createHTMLDocument" with the proper type (2) 
 PASS DOMImplementation interface: calling createHTMLDocument(DOMString) on document.implementation with too few arguments must throw TypeError 
 PASS DOMImplementation interface: document.implementation must inherit property "hasFeature" with the proper type (3) 
-PASS DocumentFragment interface: existence and properties of interface object 
-PASS DocumentFragment interface object length 
-PASS DocumentFragment interface object name 
-FAIL DocumentFragment interface: existence and properties of interface prototype object assert_equals: class string of DocumentFragment.prototype expected "[object DocumentFragmentPrototype]" but got "[object DocumentFragment]"
-PASS DocumentFragment interface: existence and properties of interface prototype object's "constructor" property 
-PASS DocumentFragment interface: operation getElementById(DOMString) 
-PASS DocumentFragment interface: attribute children 
-PASS DocumentFragment interface: attribute firstElementChild 
-PASS DocumentFragment interface: attribute lastElementChild 
-PASS DocumentFragment interface: attribute childElementCount 
-FAIL DocumentFragment interface: operation prepend([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "prepend" missing
-FAIL DocumentFragment interface: operation append([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "append" missing
-FAIL DocumentFragment interface: operation query(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "query" missing
-FAIL DocumentFragment interface: operation queryAll(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "queryAll" missing
-PASS DocumentFragment interface: operation querySelector(DOMString) 
-PASS DocumentFragment interface: operation querySelectorAll(DOMString) 
-PASS DocumentFragment must be primary interface of document.createDocumentFragment() 
-PASS Stringification of document.createDocumentFragment() 
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "getElementById" with the proper type (0) 
-PASS DocumentFragment interface: calling getElementById(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "children" with the proper type (1) 
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "firstElementChild" with the proper type (2) 
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "lastElementChild" with the proper type (3) 
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "childElementCount" with the proper type (4) 
-FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "prepend" with the proper type (5) assert_inherits: property "prepend" not found in prototype chain
-FAIL DocumentFragment interface: calling prepend([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "prepend" not found in prototype chain
-FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "append" with the proper type (6) assert_inherits: property "append" not found in prototype chain
-FAIL DocumentFragment interface: calling append([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "append" not found in prototype chain
-FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "query" with the proper type (7) assert_inherits: property "query" not found in prototype chain
-FAIL DocumentFragment interface: calling query(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "query" not found in prototype chain
-FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "queryAll" with the proper type (8) assert_inherits: property "queryAll" not found in prototype chain
-FAIL DocumentFragment interface: calling queryAll(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "queryAll" not found in prototype chain
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelector" with the proper type (9) 
-PASS DocumentFragment interface: calling querySelector(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelectorAll" with the proper type (10) 
-PASS DocumentFragment interface: calling querySelectorAll(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "ELEMENT_NODE" with the proper type (0) 
-PASS Node interface: document.createDocumentFragment() must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
-PASS Node interface: document.createDocumentFragment() must inherit property "TEXT_NODE" with the proper type (2) 
-PASS Node interface: document.createDocumentFragment() must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
-PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
-PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_NODE" with the proper type (5) 
-PASS Node interface: document.createDocumentFragment() must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
-PASS Node interface: document.createDocumentFragment() must inherit property "COMMENT_NODE" with the proper type (7) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_NODE" with the proper type (8) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
-PASS Node interface: document.createDocumentFragment() must inherit property "NOTATION_NODE" with the proper type (11) 
-PASS Node interface: document.createDocumentFragment() must inherit property "nodeType" with the proper type (12) 
-PASS Node interface: document.createDocumentFragment() must inherit property "nodeName" with the proper type (13) 
-PASS Node interface: document.createDocumentFragment() must inherit property "baseURI" with the proper type (14) 
-PASS Node interface: document.createDocumentFragment() must inherit property "ownerDocument" with the proper type (15) 
-PASS Node interface: document.createDocumentFragment() must inherit property "rootNode" with the proper type (16) 
-PASS Node interface: document.createDocumentFragment() must inherit property "parentNode" with the proper type (17) 
-PASS Node interface: document.createDocumentFragment() must inherit property "parentElement" with the proper type (18) 
-PASS Node interface: document.createDocumentFragment() must inherit property "hasChildNodes" with the proper type (19) 
-PASS Node interface: document.createDocumentFragment() must inherit property "childNodes" with the proper type (20) 
-PASS Node interface: document.createDocumentFragment() must inherit property "firstChild" with the proper type (21) 
-PASS Node interface: document.createDocumentFragment() must inherit property "lastChild" with the proper type (22) 
-PASS Node interface: document.createDocumentFragment() must inherit property "previousSibling" with the proper type (23) 
-PASS Node interface: document.createDocumentFragment() must inherit property "nextSibling" with the proper type (24) 
-PASS Node interface: document.createDocumentFragment() must inherit property "nodeValue" with the proper type (25) 
-PASS Node interface: document.createDocumentFragment() must inherit property "textContent" with the proper type (26) 
-PASS Node interface: document.createDocumentFragment() must inherit property "normalize" with the proper type (27) 
-PASS Node interface: document.createDocumentFragment() must inherit property "cloneNode" with the proper type (28) 
-PASS Node interface: calling cloneNode(boolean) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "isEqualNode" with the proper type (29) 
-PASS Node interface: calling isEqualNode(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) 
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) 
-PASS Node interface: document.createDocumentFragment() must inherit property "compareDocumentPosition" with the proper type (36) 
-PASS Node interface: calling compareDocumentPosition(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "contains" with the proper type (37) 
-PASS Node interface: calling contains(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "lookupPrefix" with the proper type (38) 
-PASS Node interface: calling lookupPrefix(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "lookupNamespaceURI" with the proper type (39) 
-PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "isDefaultNamespace" with the proper type (40) 
-PASS Node interface: calling isDefaultNamespace(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "insertBefore" with the proper type (41) 
-PASS Node interface: calling insertBefore(Node,Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "appendChild" with the proper type (42) 
-PASS Node interface: calling appendChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "replaceChild" with the proper type (43) 
-PASS Node interface: calling replaceChild(Node,Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS Node interface: document.createDocumentFragment() must inherit property "removeChild" with the proper type (44) 
-PASS Node interface: calling removeChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS EventTarget interface: document.createDocumentFragment() must inherit property "addEventListener" with the proper type (0) 
-PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS EventTarget interface: document.createDocumentFragment() must inherit property "removeEventListener" with the proper type (1) 
-PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.createDocumentFragment() with too few arguments must throw TypeError 
-PASS EventTarget interface: document.createDocumentFragment() must inherit property "dispatchEvent" with the proper type (2) 
-PASS EventTarget interface: calling dispatchEvent(Event) on document.createDocumentFragment() with too few arguments must throw TypeError 
 PASS DocumentType interface: existence and properties of interface object 
 PASS DocumentType interface object length 
 PASS DocumentType interface object name 
@@ -678,53 +578,158 @@
 PASS Node interface: document.doctype must inherit property "nodeType" with the proper type (12) 
 PASS Node interface: document.doctype must inherit property "nodeName" with the proper type (13) 
 PASS Node interface: document.doctype must inherit property "baseURI" with the proper type (14) 
-PASS Node interface: document.doctype must inherit property "ownerDocument" with the proper type (15) 
-PASS Node interface: document.doctype must inherit property "rootNode" with the proper type (16) 
-PASS Node interface: document.doctype must inherit property "parentNode" with the proper type (17) 
-PASS Node interface: document.doctype must inherit property "parentElement" with the proper type (18) 
-PASS Node interface: document.doctype must inherit property "hasChildNodes" with the proper type (19) 
-PASS Node interface: document.doctype must inherit property "childNodes" with the proper type (20) 
-PASS Node interface: document.doctype must inherit property "firstChild" with the proper type (21) 
-PASS Node interface: document.doctype must inherit property "lastChild" with the proper type (22) 
-PASS Node interface: document.doctype must inherit property "previousSibling" with the proper type (23) 
-PASS Node interface: document.doctype must inherit property "nextSibling" with the proper type (24) 
-PASS Node interface: document.doctype must inherit property "nodeValue" with the proper type (25) 
-PASS Node interface: document.doctype must inherit property "textContent" with the proper type (26) 
-PASS Node interface: document.doctype must inherit property "normalize" with the proper type (27) 
-PASS Node interface: document.doctype must inherit property "cloneNode" with the proper type (28) 
+PASS Node interface: document.doctype must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: document.doctype must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: document.doctype must inherit property "rootNode" with the proper type (17) 
+PASS Node interface: document.doctype must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: document.doctype must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: document.doctype must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: document.doctype must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: document.doctype must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: document.doctype must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: document.doctype must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: document.doctype must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: document.doctype must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: document.doctype must inherit property "textContent" with the proper type (27) 
+PASS Node interface: document.doctype must inherit property "normalize" with the proper type (28) 
+PASS Node interface: document.doctype must inherit property "cloneNode" with the proper type (29) 
 PASS Node interface: calling cloneNode(boolean) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "isEqualNode" with the proper type (29) 
+PASS Node interface: document.doctype must inherit property "isEqualNode" with the proper type (30) 
 PASS Node interface: calling isEqualNode(Node) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) 
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) 
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) 
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) 
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) 
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) 
-PASS Node interface: document.doctype must inherit property "compareDocumentPosition" with the proper type (36) 
+PASS Node interface: document.doctype must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on document.doctype with too few arguments must throw TypeError 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: document.doctype must inherit property "compareDocumentPosition" with the proper type (38) 
 PASS Node interface: calling compareDocumentPosition(Node) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "contains" with the proper type (37) 
+PASS Node interface: document.doctype must inherit property "contains" with the proper type (39) 
 PASS Node interface: calling contains(Node) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "lookupPrefix" with the proper type (38) 
+PASS Node interface: document.doctype must inherit property "lookupPrefix" with the proper type (40) 
 PASS Node interface: calling lookupPrefix(DOMString) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "lookupNamespaceURI" with the proper type (39) 
+PASS Node interface: document.doctype must inherit property "lookupNamespaceURI" with the proper type (41) 
 PASS Node interface: calling lookupNamespaceURI(DOMString) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "isDefaultNamespace" with the proper type (40) 
+PASS Node interface: document.doctype must inherit property "isDefaultNamespace" with the proper type (42) 
 PASS Node interface: calling isDefaultNamespace(DOMString) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "insertBefore" with the proper type (41) 
+PASS Node interface: document.doctype must inherit property "insertBefore" with the proper type (43) 
 PASS Node interface: calling insertBefore(Node,Node) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "appendChild" with the proper type (42) 
+PASS Node interface: document.doctype must inherit property "appendChild" with the proper type (44) 
 PASS Node interface: calling appendChild(Node) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "replaceChild" with the proper type (43) 
+PASS Node interface: document.doctype must inherit property "replaceChild" with the proper type (45) 
 PASS Node interface: calling replaceChild(Node,Node) on document.doctype with too few arguments must throw TypeError 
-PASS Node interface: document.doctype must inherit property "removeChild" with the proper type (44) 
+PASS Node interface: document.doctype must inherit property "removeChild" with the proper type (46) 
 PASS Node interface: calling removeChild(Node) on document.doctype with too few arguments must throw TypeError 
 PASS EventTarget interface: document.doctype must inherit property "addEventListener" with the proper type (0) 
-PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.doctype with too few arguments must throw TypeError 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on document.doctype with too few arguments must throw TypeError 
 PASS EventTarget interface: document.doctype must inherit property "removeEventListener" with the proper type (1) 
-PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.doctype with too few arguments must throw TypeError 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on document.doctype with too few arguments must throw TypeError 
 PASS EventTarget interface: document.doctype must inherit property "dispatchEvent" with the proper type (2) 
 PASS EventTarget interface: calling dispatchEvent(Event) on document.doctype with too few arguments must throw TypeError 
+PASS DocumentFragment interface: existence and properties of interface object 
+PASS DocumentFragment interface object length 
+PASS DocumentFragment interface object name 
+FAIL DocumentFragment interface: existence and properties of interface prototype object assert_equals: class string of DocumentFragment.prototype expected "[object DocumentFragmentPrototype]" but got "[object DocumentFragment]"
+PASS DocumentFragment interface: existence and properties of interface prototype object's "constructor" property 
+PASS DocumentFragment interface: operation getElementById(DOMString) 
+PASS DocumentFragment interface: attribute children 
+PASS DocumentFragment interface: attribute firstElementChild 
+PASS DocumentFragment interface: attribute lastElementChild 
+PASS DocumentFragment interface: attribute childElementCount 
+FAIL DocumentFragment interface: operation prepend([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "prepend" missing
+FAIL DocumentFragment interface: operation append([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "append" missing
+PASS DocumentFragment interface: operation querySelector(DOMString) 
+PASS DocumentFragment interface: operation querySelectorAll(DOMString) 
+PASS DocumentFragment must be primary interface of document.createDocumentFragment() 
+PASS Stringification of document.createDocumentFragment() 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "getElementById" with the proper type (0) 
+PASS DocumentFragment interface: calling getElementById(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "children" with the proper type (1) 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "firstElementChild" with the proper type (2) 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "lastElementChild" with the proper type (3) 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "childElementCount" with the proper type (4) 
+FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "prepend" with the proper type (5) assert_inherits: property "prepend" not found in prototype chain
+FAIL DocumentFragment interface: calling prepend([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "prepend" not found in prototype chain
+FAIL DocumentFragment interface: document.createDocumentFragment() must inherit property "append" with the proper type (6) assert_inherits: property "append" not found in prototype chain
+FAIL DocumentFragment interface: calling append([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "append" not found in prototype chain
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelector" with the proper type (7) 
+PASS DocumentFragment interface: calling querySelector(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelectorAll" with the proper type (8) 
+PASS DocumentFragment interface: calling querySelectorAll(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: document.createDocumentFragment() must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: document.createDocumentFragment() must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: document.createDocumentFragment() must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: document.createDocumentFragment() must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: document.createDocumentFragment() must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: document.createDocumentFragment() must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: document.createDocumentFragment() must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: document.createDocumentFragment() must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: document.createDocumentFragment() must inherit property "rootNode" with the proper type (17) 
+PASS Node interface: document.createDocumentFragment() must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: document.createDocumentFragment() must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: document.createDocumentFragment() must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: document.createDocumentFragment() must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: document.createDocumentFragment() must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: document.createDocumentFragment() must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: document.createDocumentFragment() must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: document.createDocumentFragment() must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: document.createDocumentFragment() must inherit property "textContent" with the proper type (27) 
+PASS Node interface: document.createDocumentFragment() must inherit property "normalize" with the proper type (28) 
+PASS Node interface: document.createDocumentFragment() must inherit property "cloneNode" with the proper type (29) 
+PASS Node interface: calling cloneNode(boolean) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "isEqualNode" with the proper type (30) 
+PASS Node interface: calling isEqualNode(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: document.createDocumentFragment() must inherit property "compareDocumentPosition" with the proper type (38) 
+PASS Node interface: calling compareDocumentPosition(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "contains" with the proper type (39) 
+PASS Node interface: calling contains(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "lookupPrefix" with the proper type (40) 
+PASS Node interface: calling lookupPrefix(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "lookupNamespaceURI" with the proper type (41) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "isDefaultNamespace" with the proper type (42) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "insertBefore" with the proper type (43) 
+PASS Node interface: calling insertBefore(Node,Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "appendChild" with the proper type (44) 
+PASS Node interface: calling appendChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "replaceChild" with the proper type (45) 
+PASS Node interface: calling replaceChild(Node,Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS Node interface: document.createDocumentFragment() must inherit property "removeChild" with the proper type (46) 
+PASS Node interface: calling removeChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createDocumentFragment() must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createDocumentFragment() must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS EventTarget interface: document.createDocumentFragment() must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on document.createDocumentFragment() with too few arguments must throw TypeError 
+PASS ShadowRoot interface: existence and properties of interface object 
+PASS ShadowRoot interface object length 
+PASS ShadowRoot interface object name 
+FAIL ShadowRoot interface: existence and properties of interface prototype object assert_equals: class string of ShadowRoot.prototype expected "[object ShadowRootPrototype]" but got "[object ShadowRoot]"
+PASS ShadowRoot interface: existence and properties of interface prototype object's "constructor" property 
+PASS ShadowRoot interface: attribute mode 
+PASS ShadowRoot interface: attribute host 
 PASS Element interface: existence and properties of interface object 
 PASS Element interface object length 
 PASS Element interface object name 
@@ -737,6 +742,7 @@
 PASS Element interface: attribute id 
 PASS Element interface: attribute className 
 PASS Element interface: attribute classList 
+PASS Element interface: attribute slot 
 PASS Element interface: operation hasAttributes() 
 PASS Element interface: attribute attributes 
 FAIL Element interface: operation getAttributeNames() assert_own_property: interface prototype object missing non-static operation expected property "getAttributeNames" missing
@@ -753,19 +759,22 @@
 PASS Element interface: operation setAttributeNode(Attr) 
 PASS Element interface: operation setAttributeNodeNS(Attr) 
 PASS Element interface: operation removeAttributeNode(Attr) 
+PASS Element interface: operation attachShadow(ShadowRootInit) 
+PASS Element interface: attribute shadowRoot 
 PASS Element interface: operation closest(DOMString) 
 PASS Element interface: operation matches(DOMString) 
+PASS Element interface: operation webkitMatchesSelector(DOMString) 
 PASS Element interface: operation getElementsByTagName(DOMString) 
 PASS Element interface: operation getElementsByTagNameNS(DOMString,DOMString) 
 PASS Element interface: operation getElementsByClassName(DOMString) 
+PASS Element interface: operation insertAdjacentElement(DOMString,Element) 
+PASS Element interface: operation insertAdjacentText(DOMString,DOMString) 
 PASS Element interface: attribute children 
 PASS Element interface: attribute firstElementChild 
 PASS Element interface: attribute lastElementChild 
 PASS Element interface: attribute childElementCount 
 FAIL Element interface: operation prepend([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "prepend" missing
 FAIL Element interface: operation append([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "append" missing
-FAIL Element interface: operation query(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "query" missing
-FAIL Element interface: operation queryAll(DOMString) assert_own_property: interface prototype object missing non-static operation expected property "queryAll" missing
 PASS Element interface: operation querySelector(DOMString) 
 PASS Element interface: operation querySelectorAll(DOMString) 
 PASS Element interface: attribute previousElementSibling 
@@ -774,6 +783,7 @@
 FAIL Element interface: operation after([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "after" missing
 FAIL Element interface: operation replaceWith([object Object],[object Object]) assert_own_property: interface prototype object missing non-static operation expected property "replaceWith" missing
 PASS Element interface: operation remove() 
+PASS Element interface: attribute assignedSlot 
 PASS Element must be primary interface of element 
 PASS Stringification of element 
 PASS Element interface: element must inherit property "namespaceURI" with the proper type (0) 
@@ -783,70 +793,77 @@
 PASS Element interface: element must inherit property "id" with the proper type (4) 
 PASS Element interface: element must inherit property "className" with the proper type (5) 
 PASS Element interface: element must inherit property "classList" with the proper type (6) 
-PASS Element interface: element must inherit property "hasAttributes" with the proper type (7) 
-PASS Element interface: element must inherit property "attributes" with the proper type (8) 
-FAIL Element interface: element must inherit property "getAttributeNames" with the proper type (9) assert_inherits: property "getAttributeNames" not found in prototype chain
-PASS Element interface: element must inherit property "getAttribute" with the proper type (10) 
+PASS Element interface: element must inherit property "slot" with the proper type (7) 
+PASS Element interface: element must inherit property "hasAttributes" with the proper type (8) 
+PASS Element interface: element must inherit property "attributes" with the proper type (9) 
+FAIL Element interface: element must inherit property "getAttributeNames" with the proper type (10) assert_inherits: property "getAttributeNames" not found in prototype chain
+PASS Element interface: element must inherit property "getAttribute" with the proper type (11) 
 PASS Element interface: calling getAttribute(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "getAttributeNS" with the proper type (11) 
+PASS Element interface: element must inherit property "getAttributeNS" with the proper type (12) 
 PASS Element interface: calling getAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "setAttribute" with the proper type (12) 
+PASS Element interface: element must inherit property "setAttribute" with the proper type (13) 
 PASS Element interface: calling setAttribute(DOMString,DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "setAttributeNS" with the proper type (13) 
+PASS Element interface: element must inherit property "setAttributeNS" with the proper type (14) 
 PASS Element interface: calling setAttributeNS(DOMString,DOMString,DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "removeAttribute" with the proper type (14) 
+PASS Element interface: element must inherit property "removeAttribute" with the proper type (15) 
 PASS Element interface: calling removeAttribute(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "removeAttributeNS" with the proper type (15) 
+PASS Element interface: element must inherit property "removeAttributeNS" with the proper type (16) 
 PASS Element interface: calling removeAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "hasAttribute" with the proper type (16) 
+PASS Element interface: element must inherit property "hasAttribute" with the proper type (17) 
 PASS Element interface: calling hasAttribute(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "hasAttributeNS" with the proper type (17) 
+PASS Element interface: element must inherit property "hasAttributeNS" with the proper type (18) 
 PASS Element interface: calling hasAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "getAttributeNode" with the proper type (18) 
+PASS Element interface: element must inherit property "getAttributeNode" with the proper type (19) 
 PASS Element interface: calling getAttributeNode(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "getAttributeNodeNS" with the proper type (19) 
+PASS Element interface: element must inherit property "getAttributeNodeNS" with the proper type (20) 
 PASS Element interface: calling getAttributeNodeNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "setAttributeNode" with the proper type (20) 
+PASS Element interface: element must inherit property "setAttributeNode" with the proper type (21) 
 PASS Element interface: calling setAttributeNode(Attr) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "setAttributeNodeNS" with the proper type (21) 
+PASS Element interface: element must inherit property "setAttributeNodeNS" with the proper type (22) 
 PASS Element interface: calling setAttributeNodeNS(Attr) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "removeAttributeNode" with the proper type (22) 
+PASS Element interface: element must inherit property "removeAttributeNode" with the proper type (23) 
 PASS Element interface: calling removeAttributeNode(Attr) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "closest" with the proper type (23) 
+PASS Element interface: element must inherit property "attachShadow" with the proper type (24) 
+PASS Element interface: calling attachShadow(ShadowRootInit) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "shadowRoot" with the proper type (25) 
+PASS Element interface: element must inherit property "closest" with the proper type (26) 
 PASS Element interface: calling closest(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "matches" with the proper type (24) 
+PASS Element interface: element must inherit property "matches" with the proper type (27) 
 PASS Element interface: calling matches(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "getElementsByTagName" with the proper type (25) 
+PASS Element interface: element must inherit property "webkitMatchesSelector" with the proper type (28) 
+PASS Element interface: calling webkitMatchesSelector(DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "getElementsByTagName" with the proper type (29) 
 PASS Element interface: calling getElementsByTagName(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "getElementsByTagNameNS" with the proper type (26) 
+PASS Element interface: element must inherit property "getElementsByTagNameNS" with the proper type (30) 
 PASS Element interface: calling getElementsByTagNameNS(DOMString,DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "getElementsByClassName" with the proper type (27) 
+PASS Element interface: element must inherit property "getElementsByClassName" with the proper type (31) 
 PASS Element interface: calling getElementsByClassName(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "children" with the proper type (28) 
-PASS Element interface: element must inherit property "firstElementChild" with the proper type (29) 
-PASS Element interface: element must inherit property "lastElementChild" with the proper type (30) 
-PASS Element interface: element must inherit property "childElementCount" with the proper type (31) 
-FAIL Element interface: element must inherit property "prepend" with the proper type (32) assert_inherits: property "prepend" not found in prototype chain
+PASS Element interface: element must inherit property "insertAdjacentElement" with the proper type (32) 
+PASS Element interface: calling insertAdjacentElement(DOMString,Element) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "insertAdjacentText" with the proper type (33) 
+PASS Element interface: calling insertAdjacentText(DOMString,DOMString) on element with too few arguments must throw TypeError 
+PASS Element interface: element must inherit property "children" with the proper type (34) 
+PASS Element interface: element must inherit property "firstElementChild" with the proper type (35) 
+PASS Element interface: element must inherit property "lastElementChild" with the proper type (36) 
+PASS Element interface: element must inherit property "childElementCount" with the proper type (37) 
+FAIL Element interface: element must inherit property "prepend" with the proper type (38) assert_inherits: property "prepend" not found in prototype chain
 FAIL Element interface: calling prepend([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "prepend" not found in prototype chain
-FAIL Element interface: element must inherit property "append" with the proper type (33) assert_inherits: property "append" not found in prototype chain
+FAIL Element interface: element must inherit property "append" with the proper type (39) assert_inherits: property "append" not found in prototype chain
 FAIL Element interface: calling append([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "append" not found in prototype chain
-FAIL Element interface: element must inherit property "query" with the proper type (34) assert_inherits: property "query" not found in prototype chain
-FAIL Element interface: calling query(DOMString) on element with too few arguments must throw TypeError assert_inherits: property "query" not found in prototype chain
-FAIL Element interface: element must inherit property "queryAll" with the proper type (35) assert_inherits: property "queryAll" not found in prototype chain
-FAIL Element interface: calling queryAll(DOMString) on element with too few arguments must throw TypeError assert_inherits: property "queryAll" not found in prototype chain
-PASS Element interface: element must inherit property "querySelector" with the proper type (36) 
+PASS Element interface: element must inherit property "querySelector" with the proper type (40) 
 PASS Element interface: calling querySelector(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "querySelectorAll" with the proper type (37) 
+PASS Element interface: element must inherit property "querySelectorAll" with the proper type (41) 
 PASS Element interface: calling querySelectorAll(DOMString) on element with too few arguments must throw TypeError 
-PASS Element interface: element must inherit property "previousElementSibling" with the proper type (38) 
-PASS Element interface: element must inherit property "nextElementSibling" with the proper type (39) 
-FAIL Element interface: element must inherit property "before" with the proper type (40) assert_inherits: property "before" not found in prototype chain
+PASS Element interface: element must inherit property "previousElementSibling" with the proper type (42) 
+PASS Element interface: element must inherit property "nextElementSibling" with the proper type (43) 
+FAIL Element interface: element must inherit property "before" with the proper type (44) assert_inherits: property "before" not found in prototype chain
 FAIL Element interface: calling before([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "before" not found in prototype chain
-FAIL Element interface: element must inherit property "after" with the proper type (41) assert_inherits: property "after" not found in prototype chain
+FAIL Element interface: element must inherit property "after" with the proper type (45) assert_inherits: property "after" not found in prototype chain
 FAIL Element interface: calling after([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "after" not found in prototype chain
-FAIL Element interface: element must inherit property "replaceWith" with the proper type (42) assert_inherits: property "replaceWith" not found in prototype chain
+FAIL Element interface: element must inherit property "replaceWith" with the proper type (46) assert_inherits: property "replaceWith" not found in prototype chain
 FAIL Element interface: calling replaceWith([object Object],[object Object]) on element with too few arguments must throw TypeError assert_inherits: property "replaceWith" not found in prototype chain
-PASS Element interface: element must inherit property "remove" with the proper type (43) 
+PASS Element interface: element must inherit property "remove" with the proper type (47) 
+PASS Element interface: element must inherit property "assignedSlot" with the proper type (48) 
 PASS Node interface: element must inherit property "ELEMENT_NODE" with the proper type (0) 
 PASS Node interface: element must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
 PASS Node interface: element must inherit property "TEXT_NODE" with the proper type (2) 
@@ -861,52 +878,55 @@
 PASS Node interface: element must inherit property "NOTATION_NODE" with the proper type (11) 
 PASS Node interface: element must inherit property "nodeType" with the proper type (12) 
 PASS Node interface: element must inherit property "nodeName" with the proper type (13) 
-PASS Node interface: element must inherit property "baseURI" with the proper type (14) 
-PASS Node interface: element must inherit property "ownerDocument" with the proper type (15) 
-PASS Node interface: element must inherit property "rootNode" with the proper type (16) 
-PASS Node interface: element must inherit property "parentNode" with the proper type (17) 
-PASS Node interface: element must inherit property "parentElement" with the proper type (18) 
-PASS Node interface: element must inherit property "hasChildNodes" with the proper type (19) 
-PASS Node interface: element must inherit property "childNodes" with the proper type (20) 
-PASS Node interface: element must inherit property "firstChild" with the proper type (21) 
-PASS Node interface: element must inherit property "lastChild" with the proper type (22) 
-PASS Node interface: element must inherit property "previousSibling" with the proper type (23) 
-PASS Node interface: element must inherit property "nextSibling" with the proper type (24) 
-PASS Node interface: element must inherit property "nodeValue" with the proper type (25) 
-PASS Node interface: element must inherit property "textContent" with the proper type (26) 
-PASS Node interface: element must inherit property "normalize" with the proper type (27) 
-PASS Node interface: element must inherit property "cloneNode" with the proper type (28) 
+FAIL Node interface: element must inherit property "baseURI" with the proper type (14) assert_equals: expected "string" but got "object"
+PASS Node interface: element must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: element must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: element must inherit property "rootNode" with the proper type (17) 
+PASS Node interface: element must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: element must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: element must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: element must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: element must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: element must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: element must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: element must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: element must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: element must inherit property "textContent" with the proper type (27) 
+PASS Node interface: element must inherit property "normalize" with the proper type (28) 
+PASS Node interface: element must inherit property "cloneNode" with the proper type (29) 
 PASS Node interface: calling cloneNode(boolean) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "isEqualNode" with the proper type (29) 
+PASS Node interface: element must inherit property "isEqualNode" with the proper type (30) 
 PASS Node interface: calling isEqualNode(Node) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) 
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) 
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) 
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) 
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) 
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) 
-PASS Node interface: element must inherit property "compareDocumentPosition" with the proper type (36) 
+PASS Node interface: element must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on element with too few arguments must throw TypeError 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: element must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: element must inherit property "compareDocumentPosition" with the proper type (38) 
 PASS Node interface: calling compareDocumentPosition(Node) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "contains" with the proper type (37) 
+PASS Node interface: element must inherit property "contains" with the proper type (39) 
 PASS Node interface: calling contains(Node) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "lookupPrefix" with the proper type (38) 
+PASS Node interface: element must inherit property "lookupPrefix" with the proper type (40) 
 PASS Node interface: calling lookupPrefix(DOMString) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "lookupNamespaceURI" with the proper type (39) 
+PASS Node interface: element must inherit property "lookupNamespaceURI" with the proper type (41) 
 PASS Node interface: calling lookupNamespaceURI(DOMString) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "isDefaultNamespace" with the proper type (40) 
+PASS Node interface: element must inherit property "isDefaultNamespace" with the proper type (42) 
 PASS Node interface: calling isDefaultNamespace(DOMString) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "insertBefore" with the proper type (41) 
+PASS Node interface: element must inherit property "insertBefore" with the proper type (43) 
 PASS Node interface: calling insertBefore(Node,Node) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "appendChild" with the proper type (42) 
+PASS Node interface: element must inherit property "appendChild" with the proper type (44) 
 PASS Node interface: calling appendChild(Node) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "replaceChild" with the proper type (43) 
+PASS Node interface: element must inherit property "replaceChild" with the proper type (45) 
 PASS Node interface: calling replaceChild(Node,Node) on element with too few arguments must throw TypeError 
-PASS Node interface: element must inherit property "removeChild" with the proper type (44) 
+PASS Node interface: element must inherit property "removeChild" with the proper type (46) 
 PASS Node interface: calling removeChild(Node) on element with too few arguments must throw TypeError 
 PASS EventTarget interface: element must inherit property "addEventListener" with the proper type (0) 
-PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on element with too few arguments must throw TypeError 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on element with too few arguments must throw TypeError 
 PASS EventTarget interface: element must inherit property "removeEventListener" with the proper type (1) 
-PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on element with too few arguments must throw TypeError 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on element with too few arguments must throw TypeError 
 PASS EventTarget interface: element must inherit property "dispatchEvent" with the proper type (2) 
 PASS EventTarget interface: calling dispatchEvent(Event) on element with too few arguments must throw TypeError 
 PASS NamedNodeMap interface: existence and properties of interface object 
@@ -931,6 +951,7 @@
 PASS Attr interface: attribute prefix 
 PASS Attr interface: attribute localName 
 PASS Attr interface: attribute name 
+FAIL Attr interface: attribute nodeName assert_own_property: expected property "nodeName" missing
 PASS Attr interface: attribute value 
 PASS Attr interface: attribute nodeValue 
 PASS Attr interface: attribute textContent 
@@ -942,11 +963,12 @@
 PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "prefix" with the proper type (1) 
 PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "localName" with the proper type (2) 
 PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "name" with the proper type (3) 
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "value" with the proper type (4) 
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "nodeValue" with the proper type (5) 
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "textContent" with the proper type (6) 
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "ownerElement" with the proper type (7) 
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "specified" with the proper type (8) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "nodeName" with the proper type (4) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "value" with the proper type (5) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "nodeValue" with the proper type (6) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "textContent" with the proper type (7) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "ownerElement" with the proper type (8) 
+PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "specified" with the proper type (9) 
 PASS CharacterData interface: existence and properties of interface object 
 PASS CharacterData interface object length 
 PASS CharacterData interface object name 
@@ -972,11 +994,13 @@
 PASS Text interface: existence and properties of interface prototype object's "constructor" property 
 PASS Text interface: operation splitText(unsigned long) 
 PASS Text interface: attribute wholeText 
+PASS Text interface: attribute assignedSlot 
 PASS Text must be primary interface of document.createTextNode("abc") 
 PASS Stringification of document.createTextNode("abc") 
 PASS Text interface: document.createTextNode("abc") must inherit property "splitText" with the proper type (0) 
 PASS Text interface: calling splitText(unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError 
 PASS Text interface: document.createTextNode("abc") must inherit property "wholeText" with the proper type (1) 
+PASS Text interface: document.createTextNode("abc") must inherit property "assignedSlot" with the proper type (2) 
 PASS CharacterData interface: document.createTextNode("abc") must inherit property "data" with the proper type (0) 
 PASS CharacterData interface: document.createTextNode("abc") must inherit property "length" with the proper type (1) 
 PASS CharacterData interface: document.createTextNode("abc") must inherit property "substringData" with the proper type (2) 
@@ -1013,51 +1037,54 @@
 PASS Node interface: document.createTextNode("abc") must inherit property "nodeType" with the proper type (12) 
 PASS Node interface: document.createTextNode("abc") must inherit property "nodeName" with the proper type (13) 
 PASS Node interface: document.createTextNode("abc") must inherit property "baseURI" with the proper type (14) 
-PASS Node interface: document.createTextNode("abc") must inherit property "ownerDocument" with the proper type (15) 
-PASS Node interface: document.createTextNode("abc") must inherit property "rootNode" with the proper type (16) 
-PASS Node interface: document.createTextNode("abc") must inherit property "parentNode" with the proper type (17) 
-PASS Node interface: document.createTextNode("abc") must inherit property "parentElement" with the proper type (18) 
-PASS Node interface: document.createTextNode("abc") must inherit property "hasChildNodes" with the proper type (19) 
-PASS Node interface: document.createTextNode("abc") must inherit property "childNodes" with the proper type (20) 
-PASS Node interface: document.createTextNode("abc") must inherit property "firstChild" with the proper type (21) 
-PASS Node interface: document.createTextNode("abc") must inherit property "lastChild" with the proper type (22) 
-PASS Node interface: document.createTextNode("abc") must inherit property "previousSibling" with the proper type (23) 
-PASS Node interface: document.createTextNode("abc") must inherit property "nextSibling" with the proper type (24) 
-PASS Node interface: document.createTextNode("abc") must inherit property "nodeValue" with the proper type (25) 
-PASS Node interface: document.createTextNode("abc") must inherit property "textContent" with the proper type (26) 
-PASS Node interface: document.createTextNode("abc") must inherit property "normalize" with the proper type (27) 
-PASS Node interface: document.createTextNode("abc") must inherit property "cloneNode" with the proper type (28) 
+PASS Node interface: document.createTextNode("abc") must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: document.createTextNode("abc") must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: document.createTextNode("abc") must inherit property "rootNode" with the proper type (17) 
+PASS Node interface: document.createTextNode("abc") must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: document.createTextNode("abc") must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: document.createTextNode("abc") must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: document.createTextNode("abc") must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: document.createTextNode("abc") must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: document.createTextNode("abc") must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: document.createTextNode("abc") must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: document.createTextNode("abc") must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: document.createTextNode("abc") must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: document.createTextNode("abc") must inherit property "textContent" with the proper type (27) 
+PASS Node interface: document.createTextNode("abc") must inherit property "normalize" with the proper type (28) 
+PASS Node interface: document.createTextNode("abc") must inherit property "cloneNode" with the proper type (29) 
 PASS Node interface: calling cloneNode(boolean) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "isEqualNode" with the proper type (29) 
+PASS Node interface: document.createTextNode("abc") must inherit property "isEqualNode" with the proper type (30) 
 PASS Node interface: calling isEqualNode(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) 
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) 
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) 
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) 
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) 
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) 
-PASS Node interface: document.createTextNode("abc") must inherit property "compareDocumentPosition" with the proper type (36) 
+PASS Node interface: document.createTextNode("abc") must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: document.createTextNode("abc") must inherit property "compareDocumentPosition" with the proper type (38) 
 PASS Node interface: calling compareDocumentPosition(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "contains" with the proper type (37) 
+PASS Node interface: document.createTextNode("abc") must inherit property "contains" with the proper type (39) 
 PASS Node interface: calling contains(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "lookupPrefix" with the proper type (38) 
+PASS Node interface: document.createTextNode("abc") must inherit property "lookupPrefix" with the proper type (40) 
 PASS Node interface: calling lookupPrefix(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "lookupNamespaceURI" with the proper type (39) 
+PASS Node interface: document.createTextNode("abc") must inherit property "lookupNamespaceURI" with the proper type (41) 
 PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "isDefaultNamespace" with the proper type (40) 
+PASS Node interface: document.createTextNode("abc") must inherit property "isDefaultNamespace" with the proper type (42) 
 PASS Node interface: calling isDefaultNamespace(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "insertBefore" with the proper type (41) 
+PASS Node interface: document.createTextNode("abc") must inherit property "insertBefore" with the proper type (43) 
 PASS Node interface: calling insertBefore(Node,Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "appendChild" with the proper type (42) 
+PASS Node interface: document.createTextNode("abc") must inherit property "appendChild" with the proper type (44) 
 PASS Node interface: calling appendChild(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "replaceChild" with the proper type (43) 
+PASS Node interface: document.createTextNode("abc") must inherit property "replaceChild" with the proper type (45) 
 PASS Node interface: calling replaceChild(Node,Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createTextNode("abc") must inherit property "removeChild" with the proper type (44) 
+PASS Node interface: document.createTextNode("abc") must inherit property "removeChild" with the proper type (46) 
 PASS Node interface: calling removeChild(Node) on document.createTextNode("abc") with too few arguments must throw TypeError 
 PASS EventTarget interface: document.createTextNode("abc") must inherit property "addEventListener" with the proper type (0) 
-PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError 
 PASS EventTarget interface: document.createTextNode("abc") must inherit property "removeEventListener" with the proper type (1) 
-PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.createTextNode("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError 
 PASS EventTarget interface: document.createTextNode("abc") must inherit property "dispatchEvent" with the proper type (2) 
 PASS EventTarget interface: calling dispatchEvent(Event) on document.createTextNode("abc") with too few arguments must throw TypeError 
 PASS ProcessingInstruction interface: existence and properties of interface object 
@@ -1104,52 +1131,55 @@
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "NOTATION_NODE" with the proper type (11) 
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeType" with the proper type (12) 
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeName" with the proper type (13) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "baseURI" with the proper type (14) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ownerDocument" with the proper type (15) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "rootNode" with the proper type (16) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentNode" with the proper type (17) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentElement" with the proper type (18) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "hasChildNodes" with the proper type (19) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "childNodes" with the proper type (20) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "firstChild" with the proper type (21) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lastChild" with the proper type (22) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "previousSibling" with the proper type (23) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nextSibling" with the proper type (24) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeValue" with the proper type (25) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "textContent" with the proper type (26) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "normalize" with the proper type (27) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "cloneNode" with the proper type (28) 
+FAIL Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "baseURI" with the proper type (14) assert_equals: expected "string" but got "object"
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "rootNode" with the proper type (17) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "textContent" with the proper type (27) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "normalize" with the proper type (28) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "cloneNode" with the proper type (29) 
 PASS Node interface: calling cloneNode(boolean) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isEqualNode" with the proper type (29) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isEqualNode" with the proper type (30) 
 PASS Node interface: calling isEqualNode(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "compareDocumentPosition" with the proper type (36) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "compareDocumentPosition" with the proper type (38) 
 PASS Node interface: calling compareDocumentPosition(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "contains" with the proper type (37) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "contains" with the proper type (39) 
 PASS Node interface: calling contains(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupPrefix" with the proper type (38) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupPrefix" with the proper type (40) 
 PASS Node interface: calling lookupPrefix(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupNamespaceURI" with the proper type (39) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupNamespaceURI" with the proper type (41) 
 PASS Node interface: calling lookupNamespaceURI(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isDefaultNamespace" with the proper type (40) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isDefaultNamespace" with the proper type (42) 
 PASS Node interface: calling isDefaultNamespace(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "insertBefore" with the proper type (41) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "insertBefore" with the proper type (43) 
 PASS Node interface: calling insertBefore(Node,Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "appendChild" with the proper type (42) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "appendChild" with the proper type (44) 
 PASS Node interface: calling appendChild(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceChild" with the proper type (43) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceChild" with the proper type (45) 
 PASS Node interface: calling replaceChild(Node,Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "removeChild" with the proper type (44) 
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "removeChild" with the proper type (46) 
 PASS Node interface: calling removeChild(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
 PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "addEventListener" with the proper type (0) 
-PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
 PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "removeEventListener" with the proper type (1) 
-PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
 PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "dispatchEvent" with the proper type (2) 
 PASS EventTarget interface: calling dispatchEvent(Event) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
 PASS Comment interface: existence and properties of interface object 
@@ -1195,51 +1225,54 @@
 PASS Node interface: document.createComment("abc") must inherit property "nodeType" with the proper type (12) 
 PASS Node interface: document.createComment("abc") must inherit property "nodeName" with the proper type (13) 
 PASS Node interface: document.createComment("abc") must inherit property "baseURI" with the proper type (14) 
-PASS Node interface: document.createComment("abc") must inherit property "ownerDocument" with the proper type (15) 
-PASS Node interface: document.createComment("abc") must inherit property "rootNode" with the proper type (16) 
-PASS Node interface: document.createComment("abc") must inherit property "parentNode" with the proper type (17) 
-PASS Node interface: document.createComment("abc") must inherit property "parentElement" with the proper type (18) 
-PASS Node interface: document.createComment("abc") must inherit property "hasChildNodes" with the proper type (19) 
-PASS Node interface: document.createComment("abc") must inherit property "childNodes" with the proper type (20) 
-PASS Node interface: document.createComment("abc") must inherit property "firstChild" with the proper type (21) 
-PASS Node interface: document.createComment("abc") must inherit property "lastChild" with the proper type (22) 
-PASS Node interface: document.createComment("abc") must inherit property "previousSibling" with the proper type (23) 
-PASS Node interface: document.createComment("abc") must inherit property "nextSibling" with the proper type (24) 
-PASS Node interface: document.createComment("abc") must inherit property "nodeValue" with the proper type (25) 
-PASS Node interface: document.createComment("abc") must inherit property "textContent" with the proper type (26) 
-PASS Node interface: document.createComment("abc") must inherit property "normalize" with the proper type (27) 
-PASS Node interface: document.createComment("abc") must inherit property "cloneNode" with the proper type (28) 
+PASS Node interface: document.createComment("abc") must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: document.createComment("abc") must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: document.createComment("abc") must inherit property "rootNode" with the proper type (17) 
+PASS Node interface: document.createComment("abc") must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: document.createComment("abc") must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: document.createComment("abc") must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: document.createComment("abc") must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: document.createComment("abc") must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: document.createComment("abc") must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: document.createComment("abc") must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: document.createComment("abc") must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: document.createComment("abc") must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: document.createComment("abc") must inherit property "textContent" with the proper type (27) 
+PASS Node interface: document.createComment("abc") must inherit property "normalize" with the proper type (28) 
+PASS Node interface: document.createComment("abc") must inherit property "cloneNode" with the proper type (29) 
 PASS Node interface: calling cloneNode(boolean) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "isEqualNode" with the proper type (29) 
+PASS Node interface: document.createComment("abc") must inherit property "isEqualNode" with the proper type (30) 
 PASS Node interface: calling isEqualNode(Node) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (30) 
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (31) 
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (32) 
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (33) 
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (34) 
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (35) 
-PASS Node interface: document.createComment("abc") must inherit property "compareDocumentPosition" with the proper type (36) 
+PASS Node interface: document.createComment("abc") must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: document.createComment("abc") must inherit property "compareDocumentPosition" with the proper type (38) 
 PASS Node interface: calling compareDocumentPosition(Node) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "contains" with the proper type (37) 
+PASS Node interface: document.createComment("abc") must inherit property "contains" with the proper type (39) 
 PASS Node interface: calling contains(Node) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "lookupPrefix" with the proper type (38) 
+PASS Node interface: document.createComment("abc") must inherit property "lookupPrefix" with the proper type (40) 
 PASS Node interface: calling lookupPrefix(DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "lookupNamespaceURI" with the proper type (39) 
+PASS Node interface: document.createComment("abc") must inherit property "lookupNamespaceURI" with the proper type (41) 
 PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "isDefaultNamespace" with the proper type (40) 
+PASS Node interface: document.createComment("abc") must inherit property "isDefaultNamespace" with the proper type (42) 
 PASS Node interface: calling isDefaultNamespace(DOMString) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "insertBefore" with the proper type (41) 
+PASS Node interface: document.createComment("abc") must inherit property "insertBefore" with the proper type (43) 
 PASS Node interface: calling insertBefore(Node,Node) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "appendChild" with the proper type (42) 
+PASS Node interface: document.createComment("abc") must inherit property "appendChild" with the proper type (44) 
 PASS Node interface: calling appendChild(Node) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "replaceChild" with the proper type (43) 
+PASS Node interface: document.createComment("abc") must inherit property "replaceChild" with the proper type (45) 
 PASS Node interface: calling replaceChild(Node,Node) on document.createComment("abc") with too few arguments must throw TypeError 
-PASS Node interface: document.createComment("abc") must inherit property "removeChild" with the proper type (44) 
+PASS Node interface: document.createComment("abc") must inherit property "removeChild" with the proper type (46) 
 PASS Node interface: calling removeChild(Node) on document.createComment("abc") with too few arguments must throw TypeError 
 PASS EventTarget interface: document.createComment("abc") must inherit property "addEventListener" with the proper type (0) 
-PASS EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError 
 PASS EventTarget interface: document.createComment("abc") must inherit property "removeEventListener" with the proper type (1) 
-PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.createComment("abc") with too few arguments must throw TypeError 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError 
 PASS EventTarget interface: document.createComment("abc") must inherit property "dispatchEvent" with the proper type (2) 
 PASS EventTarget interface: calling dispatchEvent(Event) on document.createComment("abc") with too few arguments must throw TypeError 
 PASS Range interface: existence and properties of interface object 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces.html
index f649717d..2ecd604 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/interfaces.html
@@ -42,6 +42,7 @@
   boolean cancelable = false;
 };
 
+
 [Constructor(DOMString type, optional CustomEventInit eventInitDict)/*,
  Exposed=(Window,Worker)*/]
 interface CustomEvent : Event {
@@ -54,10 +55,11 @@
   any detail = null;
 };
 
+
 //[Exposed=(Window,Worker)]
 interface EventTarget {
-  void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
-  void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+  void addEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options);
+  void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options);
   boolean dispatchEvent(Event event);
 };
 
@@ -65,25 +67,40 @@
   void handleEvent(Event event);
 };
 
-[NoInterfaceObject]
+dictionary EventListenerOptions {
+  boolean capture;
+  boolean passive;
+};
+
+
+[NoInterfaceObject,
+ Exposed=Window]
 interface NonElementParentNode {
   Element? getElementById(DOMString elementId);
 };
 Document implements NonElementParentNode;
 DocumentFragment implements NonElementParentNode;
 
-[NoInterfaceObject]
+
+[NoInterfaceObject,
+ Exposed=Window]
+interface DocumentOrShadowRoot {
+};
+Document implements DocumentOrShadowRoot;
+ShadowRoot implements DocumentOrShadowRoot;
+
+
+[NoInterfaceObject,
+ Exposed=Window]
 interface ParentNode {
   [SameObject] readonly attribute HTMLCollection children;
   readonly attribute Element? firstElementChild;
   readonly attribute Element? lastElementChild;
   readonly attribute unsigned long childElementCount;
 
-  [Unscopeable] void prepend((Node or DOMString)... nodes);
-  [Unscopeable] void append((Node or DOMString)... nodes);
+  [Unscopable] void prepend((Node or DOMString)... nodes);
+  [Unscopable] void append((Node or DOMString)... nodes);
 
-  [Unscopeable] Element? query(DOMString relativeSelectors);
-  [NewObject, Unscopeable] Elements queryAll(DOMString relativeSelectors);
   Element? querySelector(DOMString selectors);
   [NewObject] NodeList querySelectorAll(DOMString selectors);
 };
@@ -91,7 +108,9 @@
 DocumentFragment implements ParentNode;
 Element implements ParentNode;
 
-[NoInterfaceObject]
+
+[NoInterfaceObject,
+ Exposed=Window]
 interface NonDocumentTypeChildNode {
   readonly attribute Element? previousElementSibling;
   readonly attribute Element? nextElementSibling;
@@ -99,37 +118,45 @@
 Element implements NonDocumentTypeChildNode;
 CharacterData implements NonDocumentTypeChildNode;
 
-[NoInterfaceObject]
+
+[NoInterfaceObject,
+ Exposed=Window]
 interface ChildNode {
-  [Unscopeable] void before((Node or DOMString)... nodes);
-  [Unscopeable] void after((Node or DOMString)... nodes);
-  [Unscopeable] void replaceWith((Node or DOMString)... nodes);
-  [Unscopeable] void remove();
+  [Unscopable] void before((Node or DOMString)... nodes);
+  [Unscopable] void after((Node or DOMString)... nodes);
+  [Unscopable] void replaceWith((Node or DOMString)... nodes);
+  [Unscopable] void remove();
 };
 DocumentType implements ChildNode;
 Element implements ChildNode;
 CharacterData implements ChildNode;
 
-// XXX unrecognized tokens "class", "extends"
-// https://www.w3.org/Bugs/Public/show_bug.cgi?id=20020
-// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23225
-//class Elements extends Array {
-//  Element? query(DOMString relativeSelectors);
-//  Elements queryAll(DOMString relativeSelectors);
-//};
 
+[NoInterfaceObject,
+ Exposed=Window]
+interface Slotable {
+  readonly attribute HTMLSlotElement? assignedSlot;
+};
+Element implements Slotable;
+Text implements Slotable;
+
+
+[Exposed=Window]
 interface NodeList {
   getter Node? item(unsigned long index);
   readonly attribute unsigned long length;
 //  iterable<Node>;
 };
 
+
+[Exposed=Window, LegacyUnenumerableNamedProperties]
 interface HTMLCollection {
   readonly attribute unsigned long length;
   getter Element? item(unsigned long index);
   getter Element? namedItem(DOMString name);
 };
 
+
 [Constructor(MutationCallback callback)]
 interface MutationObserver {
   void observe(Node target, MutationObserverInit options);
@@ -149,9 +176,11 @@
   sequence<DOMString> attributeFilter;
 };
 
+
+[Exposed=Window]
 interface MutationRecord {
   readonly attribute DOMString type;
-  readonly attribute Node target;
+  [SameObject] readonly attribute Node target;
   [SameObject] readonly attribute NodeList addedNodes;
   [SameObject] readonly attribute NodeList removedNodes;
   readonly attribute Node? previousSibling;
@@ -161,6 +190,8 @@
   readonly attribute DOMString? oldValue;
 };
 
+
+[Exposed=Window]
 interface Node : EventTarget {
   const unsigned short ELEMENT_NODE = 1;
   const unsigned short ATTRIBUTE_NODE = 2; // historical
@@ -177,8 +208,9 @@
   readonly attribute unsigned short nodeType;
   readonly attribute DOMString nodeName;
 
-  readonly attribute DOMString? baseURI;
+  readonly attribute DOMString baseURI;
 
+  readonly attribute boolean isConnected;
   readonly attribute Document? ownerDocument;
   readonly attribute Node rootNode;
   readonly attribute Node? parentNode;
@@ -195,7 +227,8 @@
   void normalize();
 
   [NewObject] Node cloneNode(optional boolean deep = false);
-  boolean isEqualNode(Node? node);
+  boolean isEqualNode(Node? otherNode);
+  boolean isSameNode(Node? otherNode); // historical alias of ===
 
   const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
   const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
@@ -216,7 +249,9 @@
   Node removeChild(Node child);
 };
 
-[Constructor]
+
+[Constructor,
+ Exposed=Window]
 interface Document : Node {
   [SameObject] readonly attribute DOMImplementation implementation;
   readonly attribute DOMString URL;
@@ -224,18 +259,18 @@
   readonly attribute DOMString origin;
   readonly attribute DOMString compatMode;
   readonly attribute DOMString characterSet;
-  readonly attribute DOMString charset; // legacy alias of .characterSet
-  readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
+  readonly attribute DOMString charset; // historical alias of .characterSet
+  readonly attribute DOMString inputEncoding; // historical alias of .characterSet
   readonly attribute DOMString contentType;
 
   readonly attribute DocumentType? doctype;
   readonly attribute Element? documentElement;
-  HTMLCollection getElementsByTagName(DOMString localName);
+  HTMLCollection getElementsByTagName(DOMString qualifiedName);
   HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
   HTMLCollection getElementsByClassName(DOMString classNames);
 
-  [NewObject] Element createElement(DOMString localName);
-  [NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName);
+  [NewObject] Element createElement(DOMString localName, optional ElementCreationOptions options);
+  [NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName, optional ElementCreationOptions options);
   [NewObject] DocumentFragment createDocumentFragment();
   [NewObject] Text createTextNode(DOMString data);
   [NewObject] Comment createComment(DOMString data);
@@ -245,7 +280,7 @@
   Node adoptNode(Node node);
 
   [NewObject] Attr createAttribute(DOMString localName);
-  [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString name);
+  [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString qualifiedName);
 
   [NewObject] Event createEvent(DOMString interface);
 
@@ -256,8 +291,15 @@
   [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
 };
 
+[Exposed=Window]
 interface XMLDocument : Document {};
 
+dictionary ElementCreationOptions {
+  DOMString is;
+};
+
+
+[Exposed=Window]
 interface DOMImplementation {
   [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
   [NewObject] XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
@@ -266,16 +308,31 @@
   boolean hasFeature(); // useless; always returns true
 };
 
-[Constructor]
-interface DocumentFragment : Node {
-};
 
+[Exposed=Window]
 interface DocumentType : Node {
   readonly attribute DOMString name;
   readonly attribute DOMString publicId;
   readonly attribute DOMString systemId;
 };
 
+
+[Constructor,
+ Exposed=Window]
+interface DocumentFragment : Node {
+};
+
+
+[Exposed=Window]
+interface ShadowRoot : DocumentFragment {
+  readonly attribute ShadowRootMode mode;
+  readonly attribute Element host;
+};
+
+enum ShadowRootMode { "open", "closed" };
+
+
+[Exposed=Window]
 interface Element : Node {
   readonly attribute DOMString? namespaceURI;
   readonly attribute DOMString? prefix;
@@ -285,58 +342,76 @@
            attribute DOMString id;
            attribute DOMString className;
   [SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
+           attribute DOMString slot;
 
   boolean hasAttributes();
   [SameObject] readonly attribute NamedNodeMap attributes;
   sequence<DOMString> getAttributeNames();
-  DOMString? getAttribute(DOMString name);
+  DOMString? getAttribute(DOMString qualifiedName);
   DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
-  void setAttribute(DOMString name, DOMString value);
-  void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
-  void removeAttribute(DOMString name);
+  void setAttribute(DOMString qualifiedName, DOMString value);
+  void setAttributeNS(DOMString? namespace, DOMString qualifiedName, DOMString value);
+  void removeAttribute(DOMString qualifiedName);
   void removeAttributeNS(DOMString? namespace, DOMString localName);
-  boolean hasAttribute(DOMString name);
+  boolean hasAttribute(DOMString qualifiedName);
   boolean hasAttributeNS(DOMString? namespace, DOMString localName);
 
-  Attr? getAttributeNode(DOMString name);
+  Attr? getAttributeNode(DOMString qualifiedName);
   Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
   Attr? setAttributeNode(Attr attr);
   Attr? setAttributeNodeNS(Attr attr);
   Attr removeAttributeNode(Attr attr);
 
+  ShadowRoot attachShadow(ShadowRootInit init);
+  readonly attribute ShadowRoot? shadowRoot;
+
   Element? closest(DOMString selectors);
   boolean matches(DOMString selectors);
+  boolean webkitMatchesSelector(DOMString selectors); // historical alias of .matches
 
-  HTMLCollection getElementsByTagName(DOMString localName);
+  HTMLCollection getElementsByTagName(DOMString qualifiedName);
   HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
   HTMLCollection getElementsByClassName(DOMString classNames);
+
+  Element? insertAdjacentElement(DOMString where, Element element); // historical
+  void insertAdjacentText(DOMString where, DOMString data); // historical
 };
 
+dictionary ShadowRootInit {
+//  required ShadowRootMode mode;
+};
+
+
+[Exposed=Window, LegacyUnenumerableNamedProperties]
 interface NamedNodeMap {
   readonly attribute unsigned long length;
   getter Attr? item(unsigned long index);
-  getter Attr? getNamedItem(DOMString name);
+  getter Attr? getNamedItem(DOMString qualifiedName);
   Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
   Attr? setNamedItem(Attr attr);
   Attr? setNamedItemNS(Attr attr);
-  Attr removeNamedItem(DOMString name);
+  Attr removeNamedItem(DOMString qualifiedName);
   Attr removeNamedItemNS(DOMString? namespace, DOMString localName);
 };
 
+
+[Exposed=Window]
 interface Attr {
   readonly attribute DOMString? namespaceURI;
   readonly attribute DOMString? prefix;
   readonly attribute DOMString localName;
   readonly attribute DOMString name;
+  readonly attribute DOMString nodeName; // historical alias of .name
            attribute DOMString value;
-           attribute DOMString nodeValue; // legacy alias of .value
-           attribute DOMString textContent; // legacy alias of .value
+  [TreatNullAs=EmptyString] attribute DOMString nodeValue; // historical alias of .value
+  [TreatNullAs=EmptyString] attribute DOMString textContent; // historical alias of .value
 
   readonly attribute Element? ownerElement;
 
   readonly attribute boolean specified; // useless; always returns true
 };
 
+[Exposed=Window]
 interface CharacterData : Node {
   [TreatNullAs=EmptyString] attribute DOMString data;
   readonly attribute unsigned long length;
@@ -347,21 +422,27 @@
   void replaceData(unsigned long offset, unsigned long count, DOMString data);
 };
 
-[Constructor(optional DOMString data = "")]
+
+[Constructor(optional DOMString data = ""),
+ Exposed=Window]
 interface Text : CharacterData {
   [NewObject] Text splitText(unsigned long offset);
   readonly attribute DOMString wholeText;
 };
 
+[Exposed=Window]
 interface ProcessingInstruction : CharacterData {
   readonly attribute DOMString target;
 };
 
-[Constructor(optional DOMString data = "")]
+[Constructor(optional DOMString data = ""),
+ Exposed=Window]
 interface Comment : CharacterData {
 };
 
-[Constructor]
+
+[Constructor,
+ Exposed=Window]
 interface Range {
   readonly attribute Node startContainer;
   readonly attribute unsigned long startOffset;
@@ -403,6 +484,8 @@
   stringifier;
 };
 
+
+[Exposed=Window]
 interface NodeIterator {
   [SameObject] readonly attribute Node root;
   readonly attribute Node referenceNode;
@@ -416,6 +499,8 @@
   void detach();
 };
 
+
+[Exposed=Window]
 interface TreeWalker {
   [SameObject] readonly attribute Node root;
   readonly attribute unsigned long whatToShow;
@@ -431,6 +516,7 @@
   Node? nextNode();
 };
 
+[Exposed=Window]
 callback interface NodeFilter {
   // Constants for acceptNode()
   const unsigned short FILTER_ACCEPT = 1;
@@ -455,6 +541,7 @@
   unsigned short acceptNode(Node node);
 };
 
+
 interface DOMTokenList {
   readonly attribute unsigned long length;
   getter DOMString? item(unsigned long index);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js
index cc2b736..3d20606 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js
@@ -127,17 +127,19 @@
   test(function() {
     var t = element.appendChild(document.createElementNS("test", "te:st"))
     this.add_cleanup(function() {element.removeChild(t)})
-    assert_array_equals(context.getElementsByTagName("st"), [t])
+    assert_array_equals(context.getElementsByTagName("st"), [])
     assert_array_equals(context.getElementsByTagName("ST"), [])
+    assert_array_equals(context.getElementsByTagName("te:st"), [t])
+    assert_array_equals(context.getElementsByTagName("te:ST"), [])
   }, "Element in non-HTML namespace, prefix, lowercase name")
 
   test(function() {
     var t = element.appendChild(document.createElementNS("test", "te:ST"))
     this.add_cleanup(function() {element.removeChild(t)})
-    assert_array_equals(context.getElementsByTagName("ST"), [t])
     assert_array_equals(context.getElementsByTagName("st"), [])
+    assert_array_equals(context.getElementsByTagName("ST"), [])
     assert_array_equals(context.getElementsByTagName("te:st"), [])
-    assert_array_equals(context.getElementsByTagName("te:ST"), [])
+    assert_array_equals(context.getElementsByTagName("te:ST"), [t])
   }, "Element in non-HTML namespace, prefix, uppercase name")
 
   test(function() {
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent-expected.txt
index 4028007..366eae5 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent-expected.txt
@@ -74,207 +74,227 @@
 PASS Should throw NOT_SUPPORTED_ERR for unrecognized arguments 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AnimationEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AnimationPlayerEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationPlayerEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationPlayerEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ApplicationCacheErrorEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ApplicationCacheErrorEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ApplicationCacheErrorEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AudioProcessingEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AudioProcessingEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AudioProcessingEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AutocompleteErrorEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AutocompleteErrorEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AutocompleteErrorEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "BeforeInstallPromptEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BeforeInstallPromptEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BeforeInstallPromptEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "BeforeUnloadEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BeforeUnloadEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BeforeUnloadEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "BlobEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BlobEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BlobEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ClipboardEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ClipboardEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ClipboardEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "CloseEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CloseEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CloseEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "CommandEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CommandEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "CompositionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CompositionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CompositionEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "DataContainerEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DataContainerEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "DeviceLightEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DeviceLightEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DeviceLightEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "DeviceMotionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DeviceMotionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DeviceMotionEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "DeviceOrientationEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DeviceOrientationEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DeviceOrientationEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "DragEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DragEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DragEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ErrorEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ErrorEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ErrorEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ExtendableEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ExtendableEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ExtendableEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ExtendableMessageEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ExtendableMessageEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ExtendableMessageEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "FetchEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FetchEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FetchEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "FocusEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FocusEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FocusEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "FontFaceSetLoadEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FontFaceSetLoadEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FontFaceSetLoadEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "GamepadEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "GamepadEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "GamepadEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "GeofencingEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "GeofencingEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "GeofencingEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "HashChangeEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "HashChangeEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "HashChangeEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "IDBVersionChangeEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "IDBVersionChangeEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "IDBVersionChangeEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "InstallEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "InstallEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "InstallEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "KeyEvent" 
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "KeyEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "KeyEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MIDIConnectionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MIDIConnectionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MIDIConnectionEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MIDIMessageEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MIDIMessageEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MIDIMessageEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaEncryptedEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaEncryptedEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaEncryptedEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaKeyEvent" 
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaKeyEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaKeyEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaKeyMessageEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaKeyMessageEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaKeyMessageEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaQueryListEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaQueryListEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaQueryListEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaStreamEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaStreamEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaStreamEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaStreamTrackEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaStreamTrackEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaStreamTrackEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MouseScrollEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MouseScrollEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MutationEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-FAIL Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MutationEvent" assert_throws: function "function () {
+FAIL Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MutationEvents" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "NotificationEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "NotificationEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "NotificationEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "NotifyPaintEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "NotifyPaintEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "OfflineAudioCompletionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "OfflineAudioCompletionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "OfflineAudioCompletionEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "OrientationEvent" 
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "OrientationEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "OrientationEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PageTransition" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PageTransitions" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PageTransitionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PageTransitionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PageTransitionEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PointerEvent" 
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PointerEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PointerEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PopStateEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PopStateEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PopStateEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PopUpEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PopUpEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PresentationConnectionAvailableEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PresentationConnectionAvailableEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PresentationConnectionAvailableEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PresentationConnectionCloseEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PresentationConnectionCloseEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PresentationConnectionCloseEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ProgressEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ProgressEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ProgressEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PromiseRejectionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PromiseRejectionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PromiseRejectionEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PushEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PushEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PushEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RTCDTMFToneChangeEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCDTMFToneChangeEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCDTMFToneChangeEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RTCDataChannelEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCDataChannelEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCDataChannelEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RTCIceCandidateEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCIceCandidateEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCIceCandidateEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RelatedEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RelatedEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RelatedEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ResourceProgressEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ResourceProgressEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ResourceProgressEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SVGEvent" 
-FAIL Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SVGEvent" assert_throws: function "function () {
+FAIL Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SVGEvents" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SVGZoomEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-FAIL Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SVGZoomEvent" assert_throws: function "function () {
+FAIL Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SVGZoomEvents" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ScrollAreaEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ScrollAreaEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SecurityPolicyViolationEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SecurityPolicyViolationEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SecurityPolicyViolationEvents" 
 PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ServicePortConnectEvent" 
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ServicePortConnectEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ServicePortConnectEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ServiceWorkerMessageEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ServiceWorkerMessageEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ServiceWorkerMessageEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SimpleGestureEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SimpleGestureEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SpeechRecognitionError" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechRecognitionError" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechRecognitionErrors" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SpeechRecognitionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechRecognitionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechRecognitionEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SpeechSynthesisEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechSynthesisEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechSynthesisEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "StorageEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "StorageEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "StorageEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SyncEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SyncEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SyncEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TextEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TextEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TextEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TimeEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TimeEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TrackEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TrackEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TrackEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TransitionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TransitionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TransitionEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebGLContextEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebGLContextEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebGLContextEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitAnimationEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitAnimationEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitAnimationEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitTransitionEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitTransitionEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitTransitionEvents" 
 FAIL Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WheelEvent" assert_throws: function "function () {
       var evt = document.createEvent(eventI..." did not throw
-PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WheelEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WheelEvents" 
+PASS Should throw NOT_SUPPORTED_ERR for non-legacy event interface "XULCommandEvent" 
+PASS Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "XULCommandEvents" 
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.html
index 20137d8..1d8595c 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-createEvent.html
@@ -39,7 +39,7 @@
   testAlias(alias.toLowerCase(), iface);
   testAlias(alias.toUpperCase(), iface);
 
-  if (!alias.endsWith("s")) {
+  if (alias[alias.length - 1] != "s") {
     var plural = alias + "s";
     if (!(plural in aliases)) {
       test(function () {
@@ -66,11 +66,11 @@
 }, "Should throw NOT_SUPPORTED_ERR for unrecognized arguments");
 
 /*
-The following are event interfaces which do actually exist, but must still
-throw since they're absent from the table in the spec
-for document.createEvent().
-This list is not exhaustive.
-*/
+ * The following are event interfaces which do actually exist, but must still
+ * throw since they're absent from the table in the spec for
+ * document.createEvent().  This list is not exhaustive, but includes all
+ * interfaces that it is known some UA does or did not throw for.
+ */
 var someNonCreateableEvents = [
   "AnimationEvent",
   "AnimationPlayerEvent",
@@ -82,7 +82,9 @@
   "BlobEvent",
   "ClipboardEvent",
   "CloseEvent",
+  "CommandEvent",
   "CompositionEvent",
+  "DataContainerEvent",
   "DeviceLightEvent",
   "DeviceMotionEvent",
   "DeviceOrientationEvent",
@@ -107,13 +109,17 @@
   "MediaQueryListEvent",
   "MediaStreamEvent",
   "MediaStreamTrackEvent",
+  "MouseScrollEvent",
   "MutationEvent",
   "NotificationEvent",
+  "NotifyPaintEvent",
   "OfflineAudioCompletionEvent",
   "OrientationEvent",
+  "PageTransition", // Yes, with no "Event"
   "PageTransitionEvent",
   "PointerEvent",
   "PopStateEvent",
+  "PopUpEvent",
   "PresentationConnectionAvailableEvent",
   "PresentationConnectionCloseEvent",
   "ProgressEvent",
@@ -126,21 +132,25 @@
   "ResourceProgressEvent",
   "SVGEvent",
   "SVGZoomEvent",
+  "ScrollAreaEvent",
   "SecurityPolicyViolationEvent",
   "ServicePortConnectEvent",
   "ServiceWorkerMessageEvent",
+  "SimpleGestureEvent",
   "SpeechRecognitionError",
   "SpeechRecognitionEvent",
   "SpeechSynthesisEvent",
   "StorageEvent",
   "SyncEvent",
   "TextEvent",
+  "TimeEvent",
   "TrackEvent",
   "TransitionEvent",
   "WebGLContextEvent",
   "WebKitAnimationEvent",
   "WebKitTransitionEvent",
-  "WheelEvent"
+  "WheelEvent",
+  "XULCommandEvent",
 ];
 someNonCreateableEvents.forEach(function (eventInterface) {
   test(function () {
@@ -153,6 +163,6 @@
     assert_throws("NOT_SUPPORTED_ERR", function () {
       var evt = document.createEvent(eventInterface + "s");
     });
-  }, 'Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "' + eventInterface + '"');
+  }, 'Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "' + eventInterface + 's"');
 });
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-expected.txt
index 0149f41e..b7d746c9 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-expected.txt
@@ -12,8 +12,8 @@
 PASS HTML element with uppercase tagName never matches in HTML Documents 
 PASS Element in non-HTML namespace, no prefix, lowercase name 
 PASS Element in non-HTML namespace, no prefix, uppercase name 
-PASS Element in non-HTML namespace, prefix, lowercase name 
-PASS Element in non-HTML namespace, prefix, uppercase name 
+FAIL Element in non-HTML namespace, prefix, lowercase name assert_array_equals: lengths differ, expected 0 got 1
+FAIL Element in non-HTML namespace, prefix, uppercase name assert_array_equals: lengths differ, expected 0 got 1
 FAIL Element in HTML namespace, no prefix, non-ascii characters in name assert_equals: expected "aÇ" but got "aç"
 PASS Element in non-HTML namespace, non-ascii characters in name 
 FAIL Element in HTML namespace, prefix, non-ascii characters in name assert_array_equals: All uppercase input lengths differ, expected 1 got 0
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml-expected.txt
new file mode 100644
index 0000000..8a02b79
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+PASS HTML element with uppercase tag name matches in XHTML documents 
+PASS Element in non-HTML namespace, no prefix, lowercase name 
+PASS Element in non-HTML namespace, no prefix, uppercase name 
+FAIL Element in non-HTML namespace, prefix, lowercase name assert_array_equals: lengths differ, expected 0 got 1
+FAIL Element in non-HTML namespace, prefix, uppercase name assert_array_equals: lengths differ, expected 0 got 1
+PASS Element in HTML namespace, no prefix, non-ascii characters in name 
+PASS Element in non-HTML namespace, non-ascii characters in name 
+PASS Element in HTML namespace, prefix, non-ascii characters in name 
+PASS Element in non-HTML namespace, prefix, non-ascii characters in name 
+PASS getElementsByTagName('*') 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml
index bdafb07..a094bd2 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml
@@ -37,17 +37,19 @@
 test(function() {
   var t = document.body.appendChild(document.createElementNS("test", "te:st"))
   this.add_cleanup(function() {document.body.removeChild(t)})
-  assert_array_equals(document.getElementsByTagName("st"), [t])
+  assert_array_equals(document.getElementsByTagName("st"), [])
   assert_array_equals(document.getElementsByTagName("ST"), [])
+  assert_array_equals(document.getElementsByTagName("te:st"), [t])
+  assert_array_equals(document.getElementsByTagName("te:ST"), [])
 }, "Element in non-HTML namespace, prefix, lowercase name")
 
 test(function() {
   var t = document.body.appendChild(document.createElementNS("test", "te:ST"))
   this.add_cleanup(function() {document.body.removeChild(t)})
-  assert_array_equals(document.getElementsByTagName("ST"), [t])
+  assert_array_equals(document.getElementsByTagName("ST"), [])
   assert_array_equals(document.getElementsByTagName("st"), [])
   assert_array_equals(document.getElementsByTagName("te:st"), [])
-  assert_array_equals(document.getElementsByTagName("te:ST"), [])
+  assert_array_equals(document.getElementsByTagName("te:ST"), [t])
 }, "Element in non-HTML namespace, prefix, uppercase name")
 
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist-expected.txt
index d4abfd96..5ae14cc6 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist-expected.txt
@@ -14,12 +14,12 @@
 PASS classList[index] must be undefined for negative index 
 FAIL className should contain initial markup whitespace assert_equals: expected " " but got ""
 PASS classList should contain initial markup whitespace 
-PASS .contains(empty_string) must throw a SYNTAX_ERR 
+FAIL .contains(empty_string) must return false Failed to execute 'contains' on 'DOMTokenList': The token provided must not be empty.
 PASS .add(empty_string) must throw a SYNTAX_ERR 
 PASS .remove(empty_string) must throw a SYNTAX_ERR 
 PASS .toggle(empty_string) must throw a SYNTAX_ERR 
 FAIL .replace with empty_string must throw a SYNTAX_ERR assert_throws: function "function () { elem.classList.replace('', 'foo'); }" threw object "TypeError: elem.classList.replace is not a function" that is not a DOMException SYNTAX_ERR: property "code" is equal to undefined, expected 12
-PASS .contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
+FAIL .contains(string_with_spaces) must return false Failed to execute 'contains' on 'DOMTokenList': The token provided ('a b') contains HTML space characters, which are not valid in tokens.
 PASS .add(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
 PASS .remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
 PASS .toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist.html
index e22422b1..2384c62 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-classlist.html
@@ -66,8 +66,8 @@
   assert_equals( elem.classList.toString(), ' ', 'explicit' );
 }, 'classList should contain initial markup whitespace');
 test(function () {
-  assert_throws( 'SYNTAX_ERR', function () { elem.classList.contains(''); } );
-}, '.contains(empty_string) must throw a SYNTAX_ERR');
+  assert_false( elem.classList.contains('') );
+}, '.contains(empty_string) must return false');
 test(function () {
   assert_throws( 'SYNTAX_ERR', function () { elem.classList.add(''); } );
 }, '.add(empty_string) must throw a SYNTAX_ERR');
@@ -85,8 +85,8 @@
   assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', ''); } );
 }, '.replace with empty_string must throw a SYNTAX_ERR');
 test(function () {
-  assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.contains('a b'); } );
-}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+  assert_false( elem.classList.contains('a b') );
+}, '.contains(string_with_spaces) must return false');
 test(function () {
   assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.add('a b'); } );
 }, '.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-expected.txt
index 68f72da..eb71493 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-getElementsByTagName-expected.txt
@@ -12,8 +12,8 @@
 PASS HTML element with uppercase tagName never matches in HTML Documents 
 PASS Element in non-HTML namespace, no prefix, lowercase name 
 PASS Element in non-HTML namespace, no prefix, uppercase name 
-PASS Element in non-HTML namespace, prefix, lowercase name 
-PASS Element in non-HTML namespace, prefix, uppercase name 
+FAIL Element in non-HTML namespace, prefix, lowercase name assert_array_equals: lengths differ, expected 0 got 1
+FAIL Element in non-HTML namespace, prefix, uppercase name assert_array_equals: lengths differ, expected 0 got 1
 FAIL Element in HTML namespace, no prefix, non-ascii characters in name assert_equals: expected "aÇ" but got "aç"
 PASS Element in non-HTML namespace, non-ascii characters in name 
 FAIL Element in HTML namespace, prefix, non-ascii characters in name assert_array_equals: All uppercase input lengths differ, expected 1 got 0
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentElement-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentElement-expected.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentElement-expected.txt
@@ -0,0 +1 @@
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentElement.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentElement.html
new file mode 100644
index 0000000..37cc054
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentElement.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+
+<div id="target"></div>
+<div id="parent"><span id=target2></span></div>
+<div id="log" style="visibility:visible"></div>
+<span id="test1"></span>
+<span id="test2"></span>
+<span id="test3"></span>
+<span id="test4"></span>
+<script>
+var target = document.getElementById("target");
+var target2 = document.getElementById("target2");
+
+test(function() {
+  assert_throws("SyntaxError", function() {
+    target.insertAdjacentElement("test", document.getElementById("test1"))
+  });
+
+  assert_throws("SyntaxError", function() {
+    target2.insertAdjacentElement("test", document.getElementById("test1"))
+  });
+}, "Inserting to an invalid location should cause a Syntax Error exception")
+
+test(function() {
+  var el = target.insertAdjacentElement("beforebegin", document.getElementById("test1"));
+  assert_equals(target.previousSibling.id, "test1");
+  assert_equals(el.id, "test1");
+
+  el = target2.insertAdjacentElement("beforebegin", document.getElementById("test1"));
+  assert_equals(target2.previousSibling.id, "test1");
+  assert_equals(el.id, "test1");
+}, "Inserted element should be target element's previous sibling for 'beforebegin' case")
+
+test(function() {
+  var el = target.insertAdjacentElement("afterbegin", document.getElementById("test2"));
+  assert_equals(target.firstChild.id, "test2");
+  assert_equals(el.id, "test2");
+
+  el = target2.insertAdjacentElement("afterbegin", document.getElementById("test2"));
+  assert_equals(target2.firstChild.id, "test2");
+  assert_equals(el.id, "test2");
+}, "Inserted element should be target element's first child for 'afterbegin' case")
+
+test(function() {
+  var el = target.insertAdjacentElement("beforeend", document.getElementById("test3"));
+  assert_equals(target.lastChild.id, "test3");
+  assert_equals(el.id, "test3");
+
+  el = target2.insertAdjacentElement("beforeend", document.getElementById("test3"));
+  assert_equals(target2.lastChild.id, "test3");
+  assert_equals(el.id, "test3");
+}, "Inserted element should be target element's last child for 'beforeend' case")
+
+test(function() {
+  var el = target.insertAdjacentElement("afterend", document.getElementById("test4"));
+  assert_equals(target.nextSibling.id, "test4");
+  assert_equals(el.id, "test4");
+
+  el = target2.insertAdjacentElement("afterend", document.getElementById("test4"));
+  assert_equals(target2.nextSibling.id, "test4");
+  assert_equals(el.id, "test4");
+}, "Inserted element should be target element's next sibling for 'afterend' case")
+
+test(function() {
+  var docElement = document.documentElement;
+  docElement.style.visibility="hidden";
+
+  assert_throws("HierarchyRequestError", function() {
+    var el = docElement.insertAdjacentElement("beforebegin", document.getElementById("test1"));
+    assert_equals(el, null);
+  });
+
+  var el = docElement.insertAdjacentElement("afterbegin", document.getElementById("test2"));
+  assert_equals(docElement.firstChild.id, "test2");
+  assert_equals(el.id, "test2");
+
+  el = docElement.insertAdjacentElement("beforeend", document.getElementById("test3"));
+  assert_equals(docElement.lastChild.id, "test3");
+  assert_equals(el.id, "test3");
+
+  assert_throws("HierarchyRequestError", function() {
+    var el = docElement.insertAdjacentElement("afterend", document.getElementById("test4"));
+    assert_equals(el, null);
+  });
+}, "Adding more than one child to document should cause a HierarchyRequestError exception")
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentText-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentText-expected.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentText-expected.txt
@@ -0,0 +1 @@
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentText.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentText.html
new file mode 100644
index 0000000..3711f9b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/Element-insertAdjacentText.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<body style="visibility:hidden">
+<div id="target"></div>
+<div id="parent"><span id=target2></span></div>
+<div id="log" style="visibility:visible"></div>
+</body>
+<script>
+var target = document.getElementById("target");
+var target2 = document.getElementById("target2");
+
+test(function() {
+  assert_throws("SyntaxError", function() {
+    target.insertAdjacentText("test", "text")
+  });
+
+  assert_throws("SyntaxError", function() {
+    target2.insertAdjacentText("test", "test")
+  });
+}, "Inserting to an invalid location should cause a Syntax Error exception")
+
+test(function() {
+  target.insertAdjacentText("beforebegin", "test1");
+  assert_equals(target.previousSibling.nodeValue, "test1");
+
+  target2.insertAdjacentText("beforebegin", "test1");
+  assert_equals(target2.previousSibling.nodeValue, "test1");
+}, "Inserted text node should be target element's previous sibling for 'beforebegin' case")
+
+test(function() {
+  target.insertAdjacentText("afterbegin", "test2");
+  assert_equals(target.firstChild.nodeValue, "test2");
+
+  target2.insertAdjacentText("afterbegin", "test2");
+  assert_equals(target2.firstChild.nodeValue, "test2");
+}, "Inserted text node should be target element's first child for 'afterbegin' case")
+
+test(function() {
+  target.insertAdjacentText("beforeend", "test3");
+  assert_equals(target.lastChild.nodeValue, "test3");
+
+  target2.insertAdjacentText("beforeend", "test3");
+  assert_equals(target2.lastChild.nodeValue, "test3");
+}, "Inserted text node should be target element's last child for 'beforeend' case")
+
+test(function() {
+  target.insertAdjacentText("afterend", "test4");
+  assert_equals(target.nextSibling.nodeValue, "test4");
+
+  target2.insertAdjacentText("afterend", "test4");
+  assert_equals(target.nextSibling.nodeValue, "test4");
+}, "Inserted text node should be target element's next sibling for 'afterend' case")
+
+test(function() {
+  var docElement = document.documentElement;
+  docElement.style.visibility="hidden";
+
+  assert_throws("HierarchyRequestError", function() {
+    docElement.insertAdjacentText("beforebegin", "text1")
+  });
+
+  docElement.insertAdjacentText("afterbegin", "test2");
+  assert_equals(docElement.firstChild.nodeValue, "test2");
+
+  docElement.insertAdjacentText("beforeend", "test3");
+  assert_equals(docElement.lastChild.nodeValue, "test3");
+
+  assert_throws("HierarchyRequestError", function() {
+    docElement.insertAdjacentText("afterend", "test4")
+  });
+}, "Adding more than one child to document should cause a HierarchyRequestError exception")
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case-expected.txt
index 46edb961..e8c8beb0 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case-expected.txt
@@ -2,27 +2,27 @@
 PASS createElement abc 
 PASS setAttribute abc 
 PASS getAttribute abc 
-PASS getElementsByTagName a:abc 
+FAIL getElementsByTagName a:abc assert_array_equals: lengths differ, expected 0 got 3
 PASS getElementsByTagName abc 
 PASS createElement Abc 
 PASS setAttribute Abc 
 PASS getAttribute Abc 
-PASS getElementsByTagName a:Abc 
+FAIL getElementsByTagName a:Abc assert_array_equals: lengths differ, expected 0 got 3
 PASS getElementsByTagName Abc 
 PASS createElement ABC 
 PASS setAttribute ABC 
 PASS getAttribute ABC 
-PASS getElementsByTagName a:ABC 
+FAIL getElementsByTagName a:ABC assert_array_equals: lengths differ, expected 0 got 3
 PASS getElementsByTagName ABC 
 PASS createElement ä 
 PASS setAttribute ä 
 PASS getAttribute ä 
-PASS getElementsByTagName a:ä 
+FAIL getElementsByTagName a:ä assert_array_equals: lengths differ, expected 0 got 3
 PASS getElementsByTagName ä 
 FAIL createElement Ä assert_equals: expected "Ä" but got "ä"
 FAIL setAttribute Ä assert_equals: expected "Ä" but got "ä"
 PASS getAttribute Ä 
-FAIL getElementsByTagName a:Ä assert_array_equals: property 0, expected Element node <Ä></Ä> but got Element node <ä></ä>
+FAIL getElementsByTagName a:Ä assert_array_equals: lengths differ, expected 0 got 3
 FAIL getElementsByTagName Ä assert_array_equals: property 0, expected Element node <Ä></Ä> but got Element node <ä></ä>
 PASS createElementNS http://www.w3.org/1999/xhtml,abc,abc 
 PASS setAttributeNS http://www.w3.org/1999/xhtml,abc,abc 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.js
index fb28b95..8c2da4a 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.js
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/case.js
@@ -73,6 +73,13 @@
                        });
 }
 
+function get_qualified_name(el) {
+  if (el.prefix) {
+    return el.prefix + ":" + el.localName;
+  }
+  return el.localName;
+}
+
 function test_create_element(name) {
   var node = document.createElement(name);
   assert_equals(node.localName, expected_case(name));
@@ -133,9 +140,9 @@
   var expected = Array.prototype.filter.call(container.childNodes,
                                             function(node) {
                                               if (is_html && node.namespaceURI === "http://www.w3.org/1999/xhtml") {
-                                                return node.localName === expected_case(search_string);
+                                                return get_qualified_name(node) === expected_case(search_string);
                                               } else {
-                                                return node.localName === search_string;
+                                                return get_qualified_name(node) === search_string;
                                               }
                                             });
   document.documentElement.appendChild(container);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/remove-unscopable-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/remove-unscopable-expected.txt
new file mode 100644
index 0000000..61329d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/remove-unscopable-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL remove() should be unscopable Cannot read property 'remove' of undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/remove-unscopable.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/remove-unscopable.html
new file mode 100644
index 0000000..a76501d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/dom/nodes/remove-unscopable.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=../../../../resources/testharness.js></script>
+<script src=../../../../resources/testharnessreport.js></script>
+<div id="testDiv" onclick="result1 = remove; result2 = this.remove;"></div>
+<script>
+var remove = "Hello there";
+var result1;
+var result2;
+test(function() {
+  assert_true(Element.prototype[Symbol.unscopables].remove);
+  var div = document.querySelector("#testDiv");
+  div.dispatchEvent(new Event("click"));
+  assert_equals(typeof result1, "string");
+  assert_equals(typeof result2, "function");
+}, "remove() should be unscopable")
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-basics.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-basics.html
index cbf1f3d74..4a7e650 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-basics.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-basics.html
@@ -15,13 +15,11 @@
 }, 'Default inputs');
 
 
-function testEncodeDecodeSample(encoding, string, bytes) {
+function testDecodeSample(encoding, string, bytes) {
   test(function() {
-    var encoded = new TextEncoder(encoding).encode(string);
-    assert_array_equals([].slice.call(encoded), bytes);
     assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string);
     assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string);
-  }, 'Encode/decode round trip: ' + encoding);
+  }, 'Decode sample: ' + encoding);
 }
 
 // z (ASCII U+007A), cent (Latin-1 U+00A2), CJK water (BMP U+6C34),
@@ -29,25 +27,29 @@
 // byte-swapped BOM (non-character U+FFFE)
 var sample = 'z\xA2\u6C34\uD834\uDD1E\uF8FF\uDBFF\uDFFD\uFFFE';
 
-testEncodeDecodeSample(
-  'utf-8',
-  sample,
-  [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xEF, 0xA3, 0xBF, 0xF4, 0x8F, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE]
-);
+test(function() {
+  var encoding = 'utf-8';
+  var string = sample;
+  var bytes = [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xEF, 0xA3, 0xBF, 0xF4, 0x8F, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE];
+  var encoded = new TextEncoder().encode(string);
+  assert_array_equals([].slice.call(encoded), bytes);
+  assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string);
+  assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string);
+}, 'Encode/decode round trip: utf-8');
 
-testEncodeDecodeSample(
+testDecodeSample(
   'utf-16le',
   sample,
   [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF]
 );
 
-testEncodeDecodeSample(
+testDecodeSample(
   'utf-16be',
   sample,
   [0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xF8, 0xFF, 0xDB, 0xFF, 0xDF, 0xFD, 0xFF, 0xFE]
 );
 
-testEncodeDecodeSample(
+testDecodeSample(
   'utf-16',
   sample,
   [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF]
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-invalid-label.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-invalid-label.html
index e90c1fd..5ed71f1e 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-invalid-label.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-invalid-label.html
@@ -24,10 +24,6 @@
 
 tests.forEach(function(input) {
   test(function() {
-    assert_throws(new RangeError(), function() { new TextEncoder(input); });
-  }, 'Invalid label ' + format_value(input) + ' should be rejected by TextEncoder.');
-
-  test(function() {
     assert_throws(new RangeError(), function() { new TextDecoder(input); });
   }, 'Invalid label ' + format_value(input) + ' should be rejected by TextDecoder.');
 });
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-replacement-encodings.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-replacement-encodings.html
index c5cac4a..1063405 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-replacement-encodings.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/api-replacement-encodings.html
@@ -6,7 +6,6 @@
 <script>
 
 test(function() {
-    assert_throws(new RangeError(), function() { new TextEncoder('replacement'); });
     assert_throws(new RangeError(), function() { new TextDecoder('replacement'); });
 }, 'The "replacement" label should not be a known encoding.');
 
@@ -16,7 +15,6 @@
     }).forEach(function(encoding) {
         encoding.labels.forEach(function(label) {
             test(function() {
-                assert_throws(new RangeError(), function() { new TextEncoder(label); });
                 assert_throws(new RangeError(), function() { new TextDecoder(label); });
             }, 'Label for "replacement" should be rejected by API: ' + label);
         });
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/idlharness.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/idlharness.html
index a17638b..7a162bc 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/idlharness.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/idlharness.html
@@ -38,7 +38,7 @@
 
 // 8.2 Interface TextDecoder
 
-[Constructor(optional DOMString utfLabel = "utf-8"),
+[Constructor,
  Exposed=Window,Worker]
 interface TextEncoder {
   readonly attribute DOMString encoding;
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textdecoder-streaming.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textdecoder-streaming.html
index ed0dc7c..5a8a0334 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textdecoder-streaming.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textdecoder-streaming.html
@@ -5,12 +5,23 @@
 <script src="resources/encodings.js"></script>
 <script>
 
-var string = '\\x00123ABCabc\\x80\\xFF\\u0100\\u1000\\uFFFD\\uD800\\uDC00\\uDBFF\\uDFFF';
+var string = '\x00123ABCabc\x80\xFF\u0100\u1000\uFFFD\uD800\uDC00\uDBFF\uDFFF';
+var octets = {
+    'utf-16le': [0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x41,0x00,0x42,0x00,
+                 0x43,0x00,0x61,0x00,0x62,0x00,0x63,0x00,0x80,0x00,0xFF,0x00,
+                 0x00,0x01,0x00,0x10,0xFD,0xFF,0x00,0xD8,0x00,0xDC,0xFF,0xDB,
+                 0xFF,0xDF],
+    'utf-16be': [0x00,0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x41,0x00,0x42,
+                 0x00,0x43,0x00,0x61,0x00,0x62,0x00,0x63,0x00,0x80,0x00,0xFF,
+                 0x01,0x00,0x10,0x00,0xFF,0xFD,0xD8,0x00,0xDC,0x00,0xDB,0xFF,
+                 0xDF,0xFF]
+};
 
 utf_encodings.forEach(function (encoding) {
     for (var len = 1; len <= 5; ++len) {
         test(function() {
-            var encoded = new TextEncoder(encoding).encode(string);
+            var encoded = octets[encoding] ||
+                          new TextEncoder(encoding).encode(string);
 
             var out = '';
             var decoder = new TextDecoder(encoding);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textencoder-constructor-non-utf-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textencoder-constructor-non-utf-expected.txt
new file mode 100644
index 0000000..9960c24
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textencoder-constructor-non-utf-expected.txt
@@ -0,0 +1,82 @@
+This is a testharness.js-based test.
+PASS Encoding argument supported for decode: utf-8 
+PASS Encoding argument not considered for encode: utf-8 
+PASS Encoding argument supported for decode: ibm866 
+FAIL Encoding argument not considered for encode: ibm866 Failed to construct 'TextEncoder': The encoding provided ('ibm866') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-2 
+FAIL Encoding argument not considered for encode: iso-8859-2 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-2') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-3 
+FAIL Encoding argument not considered for encode: iso-8859-3 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-3') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-4 
+FAIL Encoding argument not considered for encode: iso-8859-4 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-4') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-5 
+FAIL Encoding argument not considered for encode: iso-8859-5 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-5') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-6 
+FAIL Encoding argument not considered for encode: iso-8859-6 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-6') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-7 
+FAIL Encoding argument not considered for encode: iso-8859-7 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-7') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-8 
+FAIL Encoding argument not considered for encode: iso-8859-8 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-8') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-8-i 
+FAIL Encoding argument not considered for encode: iso-8859-8-i Failed to construct 'TextEncoder': The encoding provided ('iso-8859-8-i') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-10 
+FAIL Encoding argument not considered for encode: iso-8859-10 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-10') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-13 
+FAIL Encoding argument not considered for encode: iso-8859-13 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-13') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-14 
+FAIL Encoding argument not considered for encode: iso-8859-14 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-14') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-15 
+FAIL Encoding argument not considered for encode: iso-8859-15 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-15') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-8859-16 
+FAIL Encoding argument not considered for encode: iso-8859-16 Failed to construct 'TextEncoder': The encoding provided ('iso-8859-16') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: koi8-r 
+FAIL Encoding argument not considered for encode: koi8-r Failed to construct 'TextEncoder': The encoding provided ('koi8-r') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: koi8-u 
+FAIL Encoding argument not considered for encode: koi8-u Failed to construct 'TextEncoder': The encoding provided ('koi8-u') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: macintosh 
+FAIL Encoding argument not considered for encode: macintosh Failed to construct 'TextEncoder': The encoding provided ('macintosh') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-874 
+FAIL Encoding argument not considered for encode: windows-874 Failed to construct 'TextEncoder': The encoding provided ('windows-874') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1250 
+FAIL Encoding argument not considered for encode: windows-1250 Failed to construct 'TextEncoder': The encoding provided ('windows-1250') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1251 
+FAIL Encoding argument not considered for encode: windows-1251 Failed to construct 'TextEncoder': The encoding provided ('windows-1251') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1252 
+FAIL Encoding argument not considered for encode: windows-1252 Failed to construct 'TextEncoder': The encoding provided ('windows-1252') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1253 
+FAIL Encoding argument not considered for encode: windows-1253 Failed to construct 'TextEncoder': The encoding provided ('windows-1253') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1254 
+FAIL Encoding argument not considered for encode: windows-1254 Failed to construct 'TextEncoder': The encoding provided ('windows-1254') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1255 
+FAIL Encoding argument not considered for encode: windows-1255 Failed to construct 'TextEncoder': The encoding provided ('windows-1255') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1256 
+FAIL Encoding argument not considered for encode: windows-1256 Failed to construct 'TextEncoder': The encoding provided ('windows-1256') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1257 
+FAIL Encoding argument not considered for encode: windows-1257 Failed to construct 'TextEncoder': The encoding provided ('windows-1257') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: windows-1258 
+FAIL Encoding argument not considered for encode: windows-1258 Failed to construct 'TextEncoder': The encoding provided ('windows-1258') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: x-mac-cyrillic 
+FAIL Encoding argument not considered for encode: x-mac-cyrillic Failed to construct 'TextEncoder': The encoding provided ('x-mac-cyrillic') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: gbk 
+FAIL Encoding argument not considered for encode: gbk Failed to construct 'TextEncoder': The encoding provided ('gbk') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: gb18030 
+FAIL Encoding argument not considered for encode: gb18030 Failed to construct 'TextEncoder': The encoding provided ('gb18030') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: big5 
+FAIL Encoding argument not considered for encode: big5 Failed to construct 'TextEncoder': The encoding provided ('big5') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: euc-jp 
+FAIL Encoding argument not considered for encode: euc-jp Failed to construct 'TextEncoder': The encoding provided ('euc-jp') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: iso-2022-jp 
+FAIL Encoding argument not considered for encode: iso-2022-jp Failed to construct 'TextEncoder': The encoding provided ('iso-2022-jp') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: shift_jis 
+FAIL Encoding argument not considered for encode: shift_jis Failed to construct 'TextEncoder': The encoding provided ('shift_jis') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+PASS Encoding argument supported for decode: euc-kr 
+FAIL Encoding argument not considered for encode: euc-kr Failed to construct 'TextEncoder': The encoding provided ('euc-kr') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+FAIL Encoding argument not considered for encode: replacement Failed to construct 'TextEncoder': The encoding label provided ('replacement') is invalid.
+PASS Encoding argument supported for decode: utf-16be 
+FAIL Encoding argument not considered for encode: utf-16be assert_equals: expected "utf-8" but got "utf-16be"
+PASS Encoding argument supported for decode: utf-16le 
+FAIL Encoding argument not considered for encode: utf-16le assert_equals: expected "utf-8" but got "utf-16le"
+PASS Encoding argument supported for decode: x-user-defined 
+FAIL Encoding argument not considered for encode: x-user-defined Failed to construct 'TextEncoder': The encoding provided ('x-user-defined') is not one of 'utf-8', 'utf-16', or 'utf-16be'.
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textencoder-constructor-non-utf.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textencoder-constructor-non-utf.html
index 9b56a54..2080cf6 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textencoder-constructor-non-utf.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/encoding/textencoder-constructor-non-utf.html
@@ -6,20 +6,16 @@
 <script>
 
 encodings_table.forEach(function(section) {
-    section.encodings.filter(function(encoding) {
-        return encoding.name !== 'replacement';
-    }).forEach(function(encoding) {
-        if (utf_encodings.indexOf(encoding.name) !== -1) {
+    section.encodings.forEach(function(encoding) {
+        if (encoding.name !== 'replacement') {
             test(function() {
                 assert_equals(new TextDecoder(encoding.name).encoding, encoding.name);
-                assert_equals(new TextEncoder(encoding.name).encoding, encoding.name);
-            }, 'UTF encodings are supported for encode and decode: ' + encoding.name);
-        } else {
-            test(function() {
-                assert_equals(new TextDecoder(encoding.name).encoding, encoding.name);
-                assert_throws(new RangeError(), function() { new TextEncoder(encoding.name); });
-            }, 'Non-UTF encodings supported only for decode, not encode: ' + encoding.name);
+            }, 'Encoding argument supported for decode: ' + encoding.name);
         }
+
+        test(function() {
+            assert_equals(new TextEncoder(encoding.name).encoding, 'utf-8');
+        }, 'Encoding argument not considered for encode: ' + encoding.name);
     });
 });
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/align-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/align-expected.html
new file mode 100644
index 0000000..9e4283e2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/align-expected.html
@@ -0,0 +1,31 @@
+
+<!doctype html>
+<meta charset=utf-8>
+<style>
+.hr {
+  color: gray;
+  border-style: inset;
+  border-width: 1px;
+  margin: 0.5em auto;
+  width: 100px;
+}
+
+.left {
+  margin-left: 0;
+}
+
+.right {
+  margin-right: 0;
+}
+</style>
+<div class='hr'></div>
+<div class='hr left'></div>
+<div class='hr'></div>
+<div class='hr right'></div>
+<div class='hr'></div>
+
+<div class='hr'></div>
+<div class='hr left'></div>
+<div class='hr'></div>
+<div class='hr right'></div>
+<div class='hr'></div>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/align.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/align.html
new file mode 100644
index 0000000..1657f24
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/align.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<link rel="match" href="align-ref.html">
+<style>
+hr {
+  width: 100px;
+}
+</style>
+
+<hr align=>
+<hr align=left>
+<hr align=center>
+<hr align=right>
+<hr align=foobar>
+
+<script>
+// Test the IDL attribute
+const values = ['', 'left', 'center', 'right', 'foobar'];
+values.forEach(value => {
+  const hr = document.createElement('hr');
+  hr.align = value;
+  document.body.appendChild(hr);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback-expected.html
new file mode 100644
index 0000000..9077591
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback-expected.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Canvas fallback content</title>
+<p>The word "FAIL" should not be visible below this line.
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html
new file mode 100644
index 0000000..142024e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Canvas fallback content</title>
+<link rel=match href=canvas-fallback-ref.html>
+<style>
+#canvas2 {
+  display: inline;
+}
+
+#canvas3 {
+  display: block;
+}
+
+#canvas4 {
+  display: table;
+}
+</style>
+<p>The word "FAIL" should not be visible below this line.
+<p><canvas id=canvas1>FAIL</canvas>
+<p><canvas id=canvas2>FAIL</canvas>
+<p><canvas id=canvas3>FAIL</canvas>
+<p><canvas id=canvas4>FAIL</canvas>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js
index 07c44f0..9b7fca05 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js
@@ -29,8 +29,8 @@
 }
 
 var testContainer = document.querySelector('#testContainer');
-var outerWidth = testContainer.getBoundingClientRect().width;
-var outerHeight = testContainer.getBoundingClientRect().height;
+var testContainerWidth = testContainer.getBoundingClientRect().width;
+var testContainerHeight = testContainer.getBoundingClientRect().height;
 
 SVGSizing.doCombinationTest(
     [["placeholder", [ null ]],
@@ -45,7 +45,8 @@
         var testData = new SVGSizing.TestData(config);
 
         var expectedRect =
-                testData.computeInlineReplacedSize(outerWidth, outerHeight);
+                testData.computeInlineReplacedSize(testContainerWidth,
+                                                   testContainerHeight);
         var svgElement = testData.buildSVGOrPlaceholder();
         var container =
                 testData.buildContainer(svgElement);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/resources/common.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/resources/common.js
index 0f2bfb1e..5d3afd64 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/resources/common.js
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/resources/common.js
@@ -157,10 +157,6 @@
     }
 }
 
-function isVisible(el) {
-    return el.offsetTop != 0;
-}
-
 function isVoidElement(elementName) {
     return HTML5_VOID_ELEMENTS.indexOf(elementName) >= 0;
 }
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-legend-element/legend-form.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-legend-element/legend-form.html
index 0409d53c..fb138bd 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-legend-element/legend-form.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-legend-element/legend-form.html
@@ -13,11 +13,21 @@
   </form>
 </div>
 
+<div style="display:none">
+  <form id="testformWithFieldSet">
+    <fieldset>
+    <legend id="legendWithFieldSet">radio</legend>
+    </fieldset>
+  </form>
+</div>
 <script>
-
+test(function () {
+  var legendEle = document.getElementById("legendWithFieldSet");
+  assert_not_equals(legendEle.form, null);
+  assert_equals(legendEle.form, document.getElementById("testformWithFieldSet"));
+}, "Check if legend.form returns its parent when it's inside a fieldset");
 test(function () {
   var legendEle = document.getElementById("testlegend");
   assert_equals(legendEle.form, null);
 }, "Check if legend.form return null when legend has no fieldset element as its parent");
-
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-expected.html
new file mode 100644
index 0000000..f7747fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-expected.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference of Alternate css</title>
+<link rel="match" href="alternate-css-ref.html">
+<link rel="stylesheet" href="preferred.css" title="preferred">
+<div>foobar</div>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-ref-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-ref-expected.html
new file mode 100644
index 0000000..f7747fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-ref-expected.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference of Alternate css</title>
+<link rel="match" href="alternate-css-ref.html">
+<link rel="stylesheet" href="preferred.css" title="preferred">
+<div>foobar</div>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-ref.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-ref.html
new file mode 100644
index 0000000..f7747fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference of Alternate css</title>
+<link rel="match" href="alternate-css-ref.html">
+<link rel="stylesheet" href="preferred.css" title="preferred">
+<div>foobar</div>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css.html
new file mode 100644
index 0000000..366d6c55
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate-css.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Alternate css</title>
+<link rel="match" href="alternate-css-ref.html">
+<link rel="stylesheet"           href="preferred.css" title="preferred">
+<link rel="alternate stylesheet" href="alternate.css" title="alternate">
+<div>foobar</div>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate.css b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate.css
new file mode 100644
index 0000000..05920c61
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/alternate.css
@@ -0,0 +1,3 @@
+div {
+    background-color: red;
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/preferred.css b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/preferred.css
new file mode 100644
index 0000000..54b95ac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/links/linktypes/preferred.css
@@ -0,0 +1,3 @@
+div {
+    border: 4px solid green;
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-utf8.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-utf8.js
deleted file mode 100644
index eb442c9..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-utf8.js
+++ /dev/null
@@ -1,5 +0,0 @@
-(function() {
-  window.getSomeString = function() {
-    return "śćążź"; //<- these are five Polish letters, similar to scazz. It can be read correctly only with windows 1250 encoding.
-  };
-})();
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-windows1250.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-windows1250.js
deleted file mode 100644
index 4ac83bf..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/external-script-windows1250.js
+++ /dev/null
@@ -1,5 +0,0 @@
-(function() {
-  window.getSomeString = function() {
-    return "œ湿Ÿ"; //<- these are five Polish letters, similar to scazz. It can be read correctly only with windows 1250 encoding.
-  };
-})();
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/serve-with-content-type.py b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/serve-with-content-type.py
deleted file mode 100644
index 7cfe6f4..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/scripting-1/the-script-element/serve-with-content-type.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import os
-
-def main(request, response):
-    directory = os.path.dirname(__file__)
-
-    try:
-        file_name = request.GET.first("fn")
-        content_type = request.GET.first("ct")
-        with open(os.path.join(directory, file_name), "rb") as fh:
-            content = fh.read()
-
-        response.headers.set("Content-Type", content_type)
-        response.content = content
-    except:
-        response.set_error(400, "Not enough parameters or file not found")
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html
index 099feda..c6ba644 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html
@@ -34,10 +34,13 @@
 <input type=checkbox id=checkbox1 checked>
 <input type=checkbox id=checkbox2>
 <input type=checkbox id=checkbox3 default>
+<input type=radio name=radios id=radio1 checked>
+<input type=radio name=radios id=radio2>
+<input type=radio name=radios id=radio3 default>
 <select id=select1>
  <optgroup label="options" id=optgroup1>
-  <option value="option1" id=option1 selected>option1
   <option value="option1" id=option1>option1
+  <option value="option2" id=option2 selected>option2
 </select>
 <dialog id="dialog">
   <input type=submit id=input8>
@@ -53,9 +56,9 @@
 
 
 <script>
-  testSelector(":default", ["button2", "button4", "input3", "input5", "input7", "checkbox1", "option1", "button6", "button8"], "':default' matches <button>s that are their form's default button, <input>s of type submit/image that are their form's default button, checked <input>s and selected <option>s");
+  testSelector(":default", ["button2", "button4", "input3", "input5", "input7", "checkbox1", "radio1", "option2", "button6", "button8"], "':default' matches <button>s that are their form's default button, <input>s of type submit/image that are their form's default button, checked <input>s and selected <option>s");
 
   document.getElementById("button1").type = "submit"; // change the form's default button
-  testSelector(":default", ["button1", "button4", "input3", "input5", "input7", "checkbox1", "option1", "button6", "button8"], "':default' matches dynamically changed form's default buttons");
+  testSelector(":default", ["button1", "button4", "input3", "input5", "input7", "checkbox1", "radio1", "option2", "button6", "button8"], "':default' matches dynamically changed form's default buttons");
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange-expected.txt
new file mode 100644
index 0000000..45098d65
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange-expected.txt
@@ -0,0 +1,10 @@
+CONSOLE WARNING: line 59: The specified value "0" is not a valid email address.
+This is a testharness.js-based test.
+FAIL ':in-range' matches all elements that are candidates for constraint validation, have range limitations, and that are neither suffering from an underflow nor suffering from an overflow assert_array_equals: lengths differ, expected 10 got 16
+PASS ':out-of-range' matches all elements that are candidates for constraint validation, have range limitations, and that are either suffering from an underflow or suffering from an overflow 
+FAIL ':in-range' update number1's value < min assert_array_equals: lengths differ, expected 9 got 15
+PASS ':out-of-range' update number1's value < min 
+FAIL ':in-range' update number3's min < value assert_array_equals: lengths differ, expected 10 got 16
+PASS ':out-of-range' update number3's min < value 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html
index 1f5b6da5..fc900b53 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html
@@ -1,8 +1,10 @@
 <!DOCTYPE html>
 <meta charset=utf-8>
 <title>Selector: pseudo-classes (:in-range, :out-of-range)</title>
-<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
-<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id="link1">
+<link rel="author" title="Chris Rebert" href="http://chrisrebert.com" id="link2">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#selector-in-range" id="link3">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#selector-out-of-range" id="link4">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
 <script src="utils.js"></script>
@@ -11,17 +13,72 @@
 <input type=number value=0 min=0 max=10 id=number2 disabled>
 <input type=number value=0 min=1 max=10 id=number3>
 <input type=number value=11 min=0 max=10 id=number4>
+<input type=number value=0 min=0 max=10 id=number5 readonly>
+
+<input type="date" min="2005-10-10" max="2020-10-10" value="2010-10-10" id="datein">
+<input type="date" min="2010-10-10" max="2020-10-10" value="2005-10-10" id="dateunder">
+<input type="date" min="2010-10-10" max="2020-10-10" value="2030-10-10" id="dateover">
+
+<input type="time" min="01:00:00" max="05:00:00" value="02:00:00" id="timein">
+<input type="time" min="02:00:00" max="05:00:00" value="01:00:00" id="timeunder">
+<input type="time" min="02:00:00" max="05:00:00" value="07:00:00" id="timeover">
+
+<input type="week" min="2016-W05" max="2016-W10" value="2016-W07" id="weekin">
+<input type="week" min="2016-W05" max="2016-W10" value="2016-W02" id="weekunder">
+<input type="week" min="2016-W05" max="2016-W10" value="2016-W26" id="weekover">
+
+<input type="month" min="2000-04" max="2000-09" value="2000-06" id="monthin">
+<input type="month" min="2000-04" max="2000-09" value="2000-02" id="monthunder">
+<input type="month" min="2000-04" max="2000-09" value="2000-11" id="monthover">
+
+<input type="datetime-local" min="2008-03-12T23:59:59" max="2015-02-13T23:59:59" value="2012-11-28T23:59:59" id="datetimelocalin">
+<input type="datetime-local" min="2008-03-12T23:59:59" max="2015-02-13T23:59:59" value="2008-03-01T23:59:59" id="datetimelocalunder">
+<input type="datetime-local" min="2008-03-12T23:59:59" max="2015-02-13T23:59:59" value="2016-01-01T23:59:59" id="datetimelocalover">
+
+<!--  None of the following have range limitations since they have neither min nor max attributes  -->
+<input type="number" value="0" id="numbernolimit">
+<input type="date" value="2010-10-10" id="datenolimit">
+<input type="time" value="02:00:00" id="timenolimit">
+<input type="week" value="2016-W07" id="weeknolimit">
+<input type="month" value="2000-06" id="monthnolimit">
+<input type="datetime-local" value="2012-11-28T23:59:59" id="datetimelocalnolimit">
+
+<!--  range inputs have default minimum of 0 and default maximum of 100  -->
+<input type="range" value="50" id="range0">
+
+<!--  range input's value gets immediately clamped to the nearest boundary point  -->
+<input type="range" min="2" max="7" value="5" id="range1">
+<input type="range" min="2" max="7" value="1" id="range2">
+<input type="range" min="2" max="7" value="9" id="range3">
+
+<!--  None of the following input types can have range limitations  -->
+<input min="1" value="0" type="text">
+<input min="1" value="0" type="search">
+<input min="1" value="0" type="url">
+<input min="1" value="0" type="tel">
+<input min="1" value="0" type="email">
+<input min="1" value="0" type="password">
+<input min="1" value="#000000" type="color">
+<input min="1" value="0" type="checkbox">
+<input min="1" value="0" type="radio">
+<input min="1" value="0" type="file">
+<input min="1" value="0" type="submit">
+<input min="1" value="0" type="image">
+<!--  The following types are also barred from constraint validation  -->
+<input min="1" value="0" type="hidden">
+<input min="1" value="0" type="button">
+<input min="1" value="0" type="reset">
 
 <script>
-  testSelector(":in-range", ["number1"], "':in-range' matches all elements that are candidates for constraint validation, have range limitations, and that are neither suffering from an underflow nor suffering from an overflow");
+  testSelector(":in-range", ["number1", "datein", "timein", "weekin", "monthin", "datetimelocalin", "range0", "range1", "range2", "range3"], "':in-range' matches all elements that are candidates for constraint validation, have range limitations, and that are neither suffering from an underflow nor suffering from an overflow");
 
-  testSelector(":out-of-range", ["number3", "number4"], "':out-of-range' matches all elements that are candidates for constraint validation, have range limitations, and that are either suffering from an underflow or suffering from an overflow");
+  testSelector(":out-of-range", ["number3", "number4", "dateunder", "dateover", "timeunder", "timeover", "weekunder", "weekover", "monthunder", "monthover", "datetimelocalunder", "datetimelocalover"], "':out-of-range' matches all elements that are candidates for constraint validation, have range limitations, and that are either suffering from an underflow or suffering from an overflow");
 
   document.getElementById("number1").value = -10;
-  testSelector(":in-range", [], "':in-range' update number1's value < min");
-  testSelector(":out-of-range", ["number1", "number3", "number4"], "':out-of-range' update number1's value < min");
+  testSelector(":in-range", ["datein", "timein", "weekin", "monthin", "datetimelocalin", "range0", "range1", "range2", "range3"], "':in-range' update number1's value < min");
+  testSelector(":out-of-range", ["number1", "number3", "number4", "dateunder", "dateover", "timeunder", "timeover", "weekunder", "weekover", "monthunder", "monthover", "datetimelocalunder", "datetimelocalover"], "':out-of-range' update number1's value < min");
 
   document.getElementById("number3").min = 0;
-  testSelector(":in-range", ["number3"], "':in-range' update number3's min < value");
-  testSelector(":out-of-range", ["number1", "number4"], "':out-of-range' update number3's min < value");
+  testSelector(":in-range", ["number3", "datein", "timein", "weekin", "monthin", "datetimelocalin", "range0", "range1", "range2", "range3"], "':in-range' update number3's min < value");
+  testSelector(":out-of-range", ["number1", "number4", "dateunder", "dateover", "timeunder", "timeover", "weekunder", "weekover", "monthunder", "monthover", "datetimelocalunder", "datetimelocalover"], "':out-of-range' update number3's min < value");
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/resources/shadow-dom-utils.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/resources/shadow-dom-utils.js
new file mode 100644
index 0000000..07db343
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/resources/shadow-dom-utils.js
@@ -0,0 +1,154 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+"use strict";
+
+// custom element is also allowed.
+var ATTACHSHADOW_SAFELISTED_ELEMENTS = [
+    'article',
+    'aside',
+    'blockquote',
+    'body',
+    'div',
+    'footer',
+    'h1',
+    'h2',
+    'h3',
+    'h4',
+    'h5',
+    'h6',
+    'header',
+    'nav',
+    'p',
+    'section',
+    'span'
+];
+
+var HTML5_ELEMENT_NAMES = [
+    'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio',
+    'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button',
+    'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'command',
+    'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt',
+    'em', 'embed',
+    'fieldset', 'figcaption', 'figure', 'footer', 'form',
+    'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr',
+    'html',
+    'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen',
+    'label', 'legend', 'li', 'link',
+    'map', 'mark', 'menu', 'meta', 'meter',
+    'nav', 'noscript',
+    'object', 'ol', 'optgroup', 'option', 'output',
+    'p', 'param', 'pre', 'progress',
+    'q',
+    'rp', 'rt', 'ruby',
+    's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span',
+    'strong', 'style', 'sub',
+    'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time',
+    'title', 'tr', 'track',
+    'u', 'ul',
+    'var', 'video',
+    'wbr'
+];
+
+function unit(f) {
+    return function () {
+        var ctx = newContext();
+        try {
+            f(ctx);
+        } finally {
+            cleanContext(ctx);
+        }
+    }
+}
+
+function step_unit(f, ctx, t) {
+    return function () {
+        var done = false;
+        try {
+            f();
+            done = true;
+        } finally {
+            if (done) {
+                t.done();
+            }
+            cleanContext(ctx);
+        }
+    }
+}
+
+function assert_nodelist_contents_equal_noorder(actual, expected, message) {
+    assert_equals(actual.length, expected.length, message);
+    var used = [];
+    for (var i = 0; i < expected.length; i++) {
+        used.push(false);
+    }
+    for (i = 0; i < expected.length; i++) {
+        var found = false;
+        for (var j = 0; j < actual.length; j++) {
+            if (used[j] == false && expected[i] == actual[j]) {
+                used[j] = true;
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            assert_unreached(message + ". Fail reason:  element not found: " + expected[i]);
+        }
+    }
+}
+
+//Example taken from http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+function createTestMediaPlayer(d) {
+    d.body.innerHTML = '' +
+    '<div id="player">' +
+        '<input type="checkbox" id="outside-control">' +
+        '<div id="player-shadow-host">' +
+        '</div>' +
+    '</div>';
+
+    var playerShadowRoot = d.querySelector('#player-shadow-host').attachShadow({mode: 'open'});
+    playerShadowRoot.innerHTML = '' +
+        '<div id="controls">' +
+            '<button class="play-button">PLAY</button>' +
+            '<div tabindex="0" id="timeline">' +
+                '<div id="timeline-shadow-host">' +
+                '</div>' +
+            '</div>' +
+            '<div class="volume-slider-container" id="volume-slider-container">' +
+                '<div tabindex="0" class="volume-slider" id="volume-slider">' +
+                    '<div id="volume-shadow-host">' +
+                    '</div>' +
+                '</div>' +
+            '</div>' +
+        '</div>';
+
+    var timeLineShadowRoot = playerShadowRoot.querySelector('#timeline-shadow-host').attachShadow({mode: 'open'});
+    timeLineShadowRoot.innerHTML =  '<div class="slider-thumb" id="timeline-slider-thumb"></div>';
+
+    var volumeShadowRoot = playerShadowRoot.querySelector('#volume-shadow-host').attachShadow({mode: 'open'});
+    volumeShadowRoot.innerHTML = '<div class="slider-thumb" id="volume-slider-thumb"></div>';
+
+    return {
+        'playerShadowRoot': playerShadowRoot,
+        'timeLineShadowRoot': timeLineShadowRoot,
+        'volumeShadowRoot': volumeShadowRoot
+        };
+}
+
+//FIXME This call of initKeyboardEvent works for WebKit-only.
+//See https://bugs.webkit.org/show_bug.cgi?id=16735
+// and https://bugs.webkit.org/show_bug.cgi?id=13368. Add check for browser here
+function fireKeyboardEvent(doc, element, key) {
+    var event = doc.createEvent('KeyboardEvent');
+    event.initKeyboardEvent("keydown", true, true, doc.defaultView, key, 0, false, false, false, false);
+    element.dispatchEvent(event);
+}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html
deleted file mode 100644
index 055bc3fa..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_02_01_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-attributes">
-<meta name="assert" content="Extensions to Element Interface: pseudo of type DOMString attribute. Test getter when there is a custom pseudo-element associated with this element">
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(function () {
-
-	var d = newHTMLDocument();
-
-    var widget = d.createElement('div');
-    d.body.appendChild(widget);
-
-    var s = widget.createShadowRoot();
-
-    var thumb = d.createElement('span');
-    thumb.innerHTML = 'This is a pseudo-element';
-    thumb.pseudo = 'x-thumb';
-    s.appendChild(thumb);
-
-    var style = d.createElement('style');
-    style.innerHTML = '' +
-    	'div::x-thumb {' +
-    	'font-size: 30px;' +
-    	'}';
-    d.body.appendChild(style);
-
-    assert_true(thumb.pseudo != null, 'attribute \'pseudo\' must not be null');
-
-    assert_equals(thumb.pseudo, 'x-thumb', 'attribute \'pseudo\' must return ' +
-    		'the current custom pseudo-element value')
-
-}, 'A_10_02_01_01_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html
deleted file mode 100644
index d1be9d6..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_02_01_05</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-attributes">
-<meta name="assert" content="Extensions to Element Interface: shadowRoot of type ShadowRoot">
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(function () {
-
-	var d = newHTMLDocument();
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-    //old tree
-    var s1 = host.createShadowRoot();
-    //young tree
-    var s2 = host.createShadowRoot();
-
-    assert_equals(host.shadowRoot, s2, 'attribute shadowRoot must return the youngest tree that has ' +
-        	'the context object as its shadow host');
-
-
-}, 'A_10_02_01_05_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html
index a07c9ec..321803a 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html
@@ -16,14 +16,14 @@
 <meta name="assert" content="Extensions to Element Interface: shadowRoot of type ShadowRoot">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(function () {
 
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var host = d.createElement('div');
     d.body.appendChild(host);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html
deleted file mode 100644
index 6668880e..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: HTML elements can host shadow trees</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
-<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#partial-element-methods">
-<meta name="assert" content="All HTML elements must be able to host shadow trees.">
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-// These elements does not support creating shadow root.
-// instead, NotSupportedError should be thrown.
-// http://w3c.github.io/webcomponents/spec/shadow/#widl-Element-createShadowRoot-ShadowRoot-ShadowRootInit-shadowRootInitDict
-var BLACK_LISTED_ELEMENTS = [
-    "button",
-    "details",
-    "input",
-    "marquee",
-    "meter",
-    "progress",
-    "select",
-    "textarea",
-    "keygen"
-];
-
-function testElement(elementName) {
-    var doc = document.implementation.createHTMLDocument('Test');
-    var element = doc.createElement(elementName);
-    doc.body.appendChild(element);
-
-    var shadowRoot = element.createShadowRoot();
-    assert_equals(shadowRoot.ownerDocument, doc);
-}
-
-var testParameters = HTML5_ELEMENT_NAMES.filter(function(name) {
-    return BLACK_LISTED_ELEMENTS.indexOf(name) == -1;
-}).map(function (name) {
-    return [
-        'Checks whether an element "' + name + '" can create a shadow root.',
-        name
-    ];
-});
-generate_tests(testElement, testParameters);
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html
deleted file mode 100644
index 814ef80..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html
+++ /dev/null
@@ -1,104 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: Non-element node cannot be a shadow host</title>
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
-<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#partial-element-methods">
-<meta name="assert" content="Nodes, that are not elements, are not allowed to become shadow hosts.">
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
-
-function createTextNode() {
-    var doc = document.implementation.createHTMLDocument('Test Document');
-    var node = doc.createTextNode('Text Node');
-    doc.body.appendChild(node);
-    return node;
-}
-
-function createCommentNode() {
-    var doc = document.implementation.createHTMLDocument('Test Document');
-    var node = doc.createComment('Comment Node');
-    doc.body.appendChild(node);
-    return node;
-}
-
-function createCDATASectionNode() {
-    var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
-    var node = doc.createCDATASection('CDATA Section Node');
-    doc.documentElement.appendChild(node);
-    return node;
-}
-
-function createAttributeNode() {
-    var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
-    var node = doc.createAttribute('attribute-node');
-    doc.documentElement.setAttributeNode(node);
-    return node;
-}
-
-function createDocumentFragmentNode() {
-    var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
-    var node = doc.createDocumentFragment();
-    doc.documentElement.appendChild(node);
-    return node;
-}
-
-function createProcessingInstructionNode() {
-    var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
-    var node = doc.createProcessingInstruction('processing-instruction-node', '');
-    doc.documentElement.appendChild(node);
-    return node;
-}
-
-function createDocumentNode() {
-    return document.implementation.createDocument(XHTML_NAMESPACE, 'html');
-}
-
-var factories = [
-    ['a text node', createTextNode],
-    ['a comment node', createCommentNode],
-    ['a CDATA section node', createCDATASectionNode],
-    ['an attribute node', createAttributeNode],
-    ['a document fragment node', createDocumentFragmentNode],
-    ['a processing instruction node', createProcessingInstructionNode],
-    ['a document node', createDocumentNode]
-];
-
-// Non-element nodes should not have createShadowRoot() method.
-var noCreateShadowRootTestParameters = factories.map(
-    function (nameAndFactory) {
-        var name = nameAndFactory[0];
-        var factory = nameAndFactory[1];
-        return [
-            'Checks whether ' + name + ' does not have createShadowRoot() ' +
-                'method.',
-            factory
-        ];
-    });
-
-function testNoCreateShadowRoot(factory) {
-    var node = factory();
-    assert_equals(node.createShadowRoot, undefined);
-}
-
-generate_tests(testNoCreateShadowRoot, noCreateShadowRootTestParameters);
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html
index 2e4bf78..fc45880 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html
@@ -13,25 +13,25 @@
 <title>Shadow DOM Test: A_10_02_02_01</title>
 <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
 <link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-methods">
-<meta name="assert" content="Extensions to Element Interface: createShadowRoot method creates new instance of Shadow root object">
+<meta name="assert" content="Extensions to Element Interface: attachShadow method creates new instance of Shadow root object">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(function () {
 
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var host = d.createElement('div');
     d.body.appendChild(host);
 
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
-    assert_true(s instanceof ShadowRoot, 'createShadowRoot() method should create new instance ' +
-    		'of ShadowRoot object');
+    assert_true(s instanceof ShadowRoot, 'attachShadow() method should create new instance ' +
+            'of ShadowRoot object');
 
 }, 'A_10_02_02_01_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html
index 447770e..c1913f3 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html
@@ -13,17 +13,18 @@
 <title>Shadow DOM Test: A_10_02_02_02</title>
 <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
 <link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-methods">
-<meta name="assert" content="Extensions to Element Interface: createShadowRoot method">
+<meta name="assert" content="Extensions to Element Interface: attachShadow method">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
     var host = d.createElement('div');
     d.body.appendChild(host);
@@ -32,11 +33,11 @@
     span.innerHTML = 'Some text';
     host.appendChild(span);
 
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     // span should become invisible as shadow root content
-    assert_equals(span.offsetTop, 0, 'createShadowRoot() method should establish ' +
-    		'the context object as the shadow host of the ShadowRoot object');
+    assert_equals(span.offsetTop, 0, 'attachShadow() method should establish ' +
+            'the context object as the shadow host of the ShadowRoot object');
 
 }), 'A_10_02_02_02_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html
deleted file mode 100644
index 8c4abc0..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_02_02_03</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-methods">
-<meta name="assert" content="Extensions to Element Interface: createShadowRoot method">
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-    var span = d.createElement('span');
-    span.setAttribute('id', 'sp0');
-    span.innerHTML = 'Some text';
-    host.appendChild(span);
-
-    //old tree
-    var s1 = host.createShadowRoot();
-    s1.innerHTML = '<span id="sp1">Span 1</span>';
-    //young tree
-    var s2 = host.createShadowRoot();
-    s2.innerHTML = '<span id="sp2">Span 2</span>';
-
-    // span should become invisible as shadow root content
-    assert_equals(span.offsetTop, 0, 'Point 1:createShadowRoot() method should add ' +
-    		'the ShadowRoot object at the top of the tree stack of its host');
-    assert_equals(s1.querySelector('#sp1').offsetTop, 0, 'Point 2:createShadowRoot() method should add ' +
-		'the ShadowRoot object at the top of the tree stack of its host');
-    assert_true(s2.querySelector('#sp2').offsetTop > 0, 'Point 3:createShadowRoot() method should add ' +
-		'the ShadowRoot object at the top of the tree stack of its host');
-
-
-}), 'A_10_02_02_03_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html
index dd241a87..b850ecd 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html
@@ -13,35 +13,36 @@
 <title>Shadow DOM Test - event path</title>
 <link rel="author" title="Kazuhito Hokamura" href="mailto:k.hokamura@gmail.com">
 <link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event">
-<meta name="assert" content="Extensions to Event Interface: event.path cross the shadow boundary">
+<meta name="assert" content="Extensions to Event Interface: event.deepPath() cross the shadow boundary">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
-var t = async_test('event.path cross the shadow boundary');
+var t = async_test('event.deepPath() cross the shadow boundary');
 
 t.step(unit(function(ctx) {
     var doc = newRenderedHTMLDocument(ctx);
     var host = doc.createElement('div');
 
-    var shadowRoot = host.createShadowRoot();
+    var shadowRoot = host.attachShadow({mode: 'open'});
     var child = doc.createElement('div');
 
     doc.body.appendChild(host);
     shadowRoot.appendChild(child);
 
     child.addEventListener('click', t.step_func(function(e) {
-        assert_equals(e.path.length, 7, 'path.length');
-        assert_equals(e.path[0], child, 'path[0] should be child');
-        assert_equals(e.path[1], shadowRoot, 'path[1] should be shadowRoot');
-        assert_equals(e.path[2], host, 'path[2] should be host');
-        assert_equals(e.path[3], doc.body, 'path[3] should be body');
-        assert_equals(e.path[4], doc.documentElement, 'path[4] should be html');
-        assert_equals(e.path[5], doc, 'path[5] should be document');
-        assert_equals(e.path[6], ctx.iframes[0].contentWindow, 'path[6] should be window');
+        assert_equals(e.deepPath().length, 7, 'deepPath().length');
+        assert_equals(e.deepPath()[0], child, 'deepPath()[0] should be child');
+        assert_equals(e.deepPath()[1], shadowRoot, 'deepPath()[1] should be shadowRoot');
+        assert_equals(e.deepPath()[2], host, 'deepPath()[2] should be host');
+        assert_equals(e.deepPath()[3], doc.body, 'deepPath()[3] should be body');
+        assert_equals(e.deepPath()[4], doc.documentElement, 'deepPath()[4] should be html');
+        assert_equals(e.deepPath()[5], doc, 'deepPath()[5] should be document');
+        assert_equals(e.deepPath()[6], ctx.iframes[0].contentWindow, 'deepPath()[6] should be window');
 
         t.done();
     }));
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html
deleted file mode 100644
index f124bba..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test - event path</title>
-<link rel="author" title="Kazuhito Hokamura" href="mailto:k.hokamura@gmail.com">
-<link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event">
-<meta name="assert" content="Extensions to Event Interface: event.path is readonly">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var t = async_test('event.path is readonly');
-
-t.step(unit(function(ctx) {
-    var doc = newRenderedHTMLDocument(ctx);
-    var div = doc.createElement('div');
-    doc.body.appendChild(div);
-
-    div.addEventListener('click', t.step_func(function(e) {
-        var obj = {};
-        e.path = obj;
-        assert_not_equals(e.path, obj);
-
-        t.done();
-    }));
-
-    var event = doc.createEvent('HTMLEvents');
-    event.initEvent('click', true, false);
-    div.dispatchEvent(event);
-}));
-</script>
-</body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html
index ba5310ea..23c9aa80 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html
@@ -17,18 +17,19 @@
 <meta name="assert" content="ShadowRoot Object: confirm activeElement return null">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
     assert_equals(s.activeElement, null, 'activeElement attribute of the ShadowRoot must return null if there\'s no focused element');
 
@@ -37,16 +38,16 @@
 
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp = d.createElement('input');
-	d.body.appendChild(inp);
+    var inp = d.createElement('input');
+    d.body.appendChild(inp);
 
-	inp.focus();
+    inp.focus();
 
     assert_equals(s.activeElement, null, 'activeElement attribute of the ShadowRoot must return null if there\'s no focused element in the shadow tree');
 
@@ -55,19 +56,19 @@
 
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp = d.createElement('input');
-	d.body.appendChild(inp);
+    var inp = d.createElement('input');
+    d.body.appendChild(inp);
 
-	var inp2 = d.createElement('input');
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    s.appendChild(inp2);
 
-	inp.focus();
+    inp.focus();
 
     assert_equals(s.activeElement, null, 'activeElement attribute of the ShadowRoot must return null if there\'s no focused element in the shadow tree');
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html
index 8fc8449b..4e8e936 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html
@@ -16,32 +16,33 @@
 <meta name="assert" content="ShadowRoot Object: readonly attribute Element? activeElement; actual value">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	host.setAttribute('id', 'shRoot');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    host.setAttribute('id', 'shRoot');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp = d.createElement('input');
-	inp.setAttribute('type', 'text');
-	inp.setAttribute('id', 'inpId');
-	inp.setAttribute('value', 'Some text');
-	s.appendChild(inp);
+    var inp = d.createElement('input');
+    inp.setAttribute('type', 'text');
+    inp.setAttribute('id', 'inpId');
+    inp.setAttribute('value', 'Some text');
+    s.appendChild(inp);
 
-	inp.focus();
+    inp.focus();
 
     assert_true(s.activeElement != null, 'Point 1: activeElement attribute of the ShadowRoot ' +
-    		'must return the currently focused element in the shadow tree');
+            'must return the currently focused element in the shadow tree');
     assert_equals(s.activeElement.tagName, 'INPUT', 'Point 2: activeElement attribute of the ShadowRoot ' +
-    		'must return the currently focused element in the shadow tree');
+            'must return the currently focused element in the shadow tree');
 
 }), 'A_10_01_01_03_01_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html
index 0d91cec..1f001e4 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html
@@ -16,25 +16,26 @@
 <meta name="assert" content="ShadowRoot Object: innerHTML of type DOMString; Test getter">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var span = d.createElement('span');
-	span.innerHTML = 'Some text';
-	s.appendChild(span);
+    var span = d.createElement('span');
+    span.innerHTML = 'Some text';
+    s.appendChild(span);
 
     assert_equals(s.innerHTML.toLowerCase(), '<span>some text</span>',
-    		'Wrong value of ShadowRoot innerHTML attribute');
+            'Wrong value of ShadowRoot innerHTML attribute');
 
 }), 'A_10_01_01_04_01_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html
index e9d7205..76519d66 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html
@@ -16,58 +16,59 @@
 <meta name="assert" content="ShadowRoot Object: innerHTML of type DOMString; Test setter">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var span = d.createElement('span');
-	span.innerHTML = 'Some text';
-	s.appendChild(span);
+    var span = d.createElement('span');
+    span.innerHTML = 'Some text';
+    s.appendChild(span);
 
-	s.innerHTML = '<input type="text"><div>new text</div>';
+    s.innerHTML = '<input type="text"><div>new text</div>';
 
     assert_equals(s.innerHTML.toLowerCase(), '<input type="text"><div>new text</div>',
-    		'Wrong value of ShadowRoot innerHTML attribute');
+            'Wrong value of ShadowRoot innerHTML attribute');
 
 }), 'A_10_01_01_04_02_T01_01');
 
 
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var span = d.createElement('span');
-	span.setAttribute('id', 'spanId');
-	span.innerHTML = 'Some text';
-	s.appendChild(span);
+    var span = d.createElement('span');
+    span.setAttribute('id', 'spanId');
+    span.innerHTML = 'Some text';
+    s.appendChild(span);
 
-	s.innerHTML = '<input type="text" id="inputId"><div id="divId">new text</div>';
+    s.innerHTML = '<input type="text" id="inputId"><div id="divId">new text</div>';
 
     assert_equals(s.querySelector('#spanId'), null, 'Point 1:innerHTML attribute must replace all content of ' +
-    		'the ShadowRoot object');
+            'the ShadowRoot object');
 
     assert_true(s.querySelector('#inputId') != null, 'Point 2:innerHTML attribute must replace all content of ' +
-    	'the ShadowRoot object');
+        'the ShadowRoot object');
     assert_equals(s.querySelector('#inputId').getAttribute('id'), 'inputId',
-    		'Point 3:innerHTML attribute must replace all content of the ShadowRoot object');
+            'Point 3:innerHTML attribute must replace all content of the ShadowRoot object');
 
     assert_true(s.querySelector('#divId') != null, 'Point 3:innerHTML attribute must replace all content of ' +
-		'the ShadowRoot object');
-	assert_equals(s.querySelector('#divId').getAttribute('id'), 'divId',
-		'Point 4:innerHTML attribute must replace all content of the ShadowRoot object');
+        'the ShadowRoot object');
+    assert_equals(s.querySelector('#divId').getAttribute('id'), 'divId',
+        'Point 4:innerHTML attribute must replace all content of the ShadowRoot object');
 }), 'A_10_01_01_04_02_T01_02');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html
index 6555f38f..ab49dc7 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html
@@ -16,20 +16,21 @@
 <meta name="assert" content="ShadowRoot Object: styleSheets of type StyleSheetList, readonly">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	assert_true(s.styleSheets != null, 'ShadowRoot styleSheets attribute shouldn\'t be null');
+    assert_true(s.styleSheets != null, 'ShadowRoot styleSheets attribute shouldn\'t be null');
     assert_equals(s.styleSheets.length, 0, 'attribute must return the shadow root style sheets only');
 
 }), 'A_10_01_01_05_01_T01');
@@ -37,16 +38,16 @@
 
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var style = d.createElement('style');
-	s.appendChild(style);
+    var style = d.createElement('style');
+    s.appendChild(style);
 
-	assert_true(s.styleSheets != null, 'ShadowRoot styleSheets attribute shouldn\'t be null');
+    assert_true(s.styleSheets != null, 'ShadowRoot styleSheets attribute shouldn\'t be null');
     assert_equals(s.styleSheets.length, 1, 'attribute must return the shadow root style sheets');
 
 }), 'A_10_01_01_05_01_T02');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html
index 7733a2f..1ac0699 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html
@@ -16,21 +16,22 @@
 <meta name="assert" content="ShadowRoot Object: The nodeType attribute of a ShadowRoot instance must return DOCUMENT_FRAGMENT_NODE">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
     assert_equals(s.nodeType, 11, 'The nodeType attribute of a ShadowRoot ' +
-    		'instance must return DOCUMENT_FRAGMENT_NODE');
+            'instance must return DOCUMENT_FRAGMENT_NODE');
 
 }), 'A_10_01_01_06_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html
index 3c33d72..11666c2 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html
@@ -16,21 +16,22 @@
 <meta name="assert" content="ShadowRoot Object: The nodeName attribute of a ShadowRoot instance must return "#document-fragment".">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
     assert_equals(s.nodeName, '#document-fragment', 'The nodeName attribute of a ShadowRoot instance ' +
-    		'must return "#document-fragment".');
+            'must return "#document-fragment".');
 
 }), 'A_10_01_01_07_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html
deleted file mode 100644
index 5d3af34..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: ShadowRoot olderShadowRoot</title>
-<link rel="author" title="Kenji Baheux" href="mailto:kenjibaheux@google.com">
-<link rel="author" title="Kyohei Tsukuda" href="tsukuda.kyouhei@gmail.com">
-<link rel="help" href="http://w3c.github.io/webcomponents/spec/shadow/#widl-ShadowRoot-olderShadowRoot">
-<meta name="assert" content="The ShadowRoot element: olderShadowRoot attribute">
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-
-	// Shadow root and older Shadow root to play with
-	var oldRoot = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML = '' +
-		'<span id="spandex">This is a shadow root content</span>' +
-		'<content><span id="contentId">This is the content fallback</span></content>';
-	oldRoot.appendChild(div);
-	var youngRoot = host.createShadowRoot();
-
-	assert_equals(oldRoot.olderShadowRoot, null, 'If the context object is the oldest shadow root, return null');
-	assert_equals(youngRoot.olderShadowRoot, oldRoot, 'Return the older shadow root relative to the context object');
-
-}), 'ShadowRoot.olderShadowRoot_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html
index c34f5d1..a6a2ade 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html
@@ -16,28 +16,28 @@
 <meta name="assert" content="ShadowRoot Object: HTMLElement getElementById(DOMString elementId) method">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(function () {
 
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var el = d.createElement('div');
     d.body.appendChild(el);
 
-    var s = el.createShadowRoot();
+    var s = el.attachShadow({mode: 'open'});
 
     var child = d.createElement('span');
     child.setAttribute('id', 'span_id');
     s.appendChild(child);
 
     assert_true(s.getElementById('span_id') != null, 'Point 1: ShadowRoot getElementById() ' +
-    		'method should return child element');
+            'method should return child element');
     assert_equals(s.getElementById('span_id').getAttribute('id'), 'span_id', 'Point 2: ' +
-    		'ShadowRoot getElementById() method should return child element');
+            'ShadowRoot getElementById() method should return child element');
 
 }, 'A_10_01_02_01_T01');
 
@@ -45,15 +45,15 @@
 
 test(function () {
 
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var el = d.createElement('div');
     d.body.appendChild(el);
 
-    var s = el.createShadowRoot();
+    var s = el.attachShadow({mode: 'open'});
 
     assert_true(s.getElementById('span_id') == null, ' ShadowRoot getElementById() ' +
-    		'method should return null if matching element not found');
+            'method should return null if matching element not found');
 
 }, 'A_10_01_02_01_T02');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html
index 96804b4..1f116809 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html
@@ -16,33 +16,34 @@
 <meta name="assert" content="ShadowRoot Object: Selection? getSelection() method">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var span = d.createElement('span');
-	span.innerHTML = 'Some text';
-	s.appendChild(span);
+    var span = d.createElement('span');
+    span.innerHTML = 'Some text';
+    s.appendChild(span);
 
-	var range = d.createRange();
-	range.setStart(span.firstChild, 0);
-	range.setEnd(span.firstChild, 3);
+    var range = d.createRange();
+    range.setStart(span.firstChild, 0);
+    range.setEnd(span.firstChild, 3);
 
-	var selection = s.getSelection();
+    var selection = s.getSelection();
     selection.removeAllRanges();
     selection.addRange(range);
 
     var sl = s.getSelection();
     assert_equals(sl.toString(), 'Som', 'The getSelection() method of the shadow root object must return ' +
-    		'the current selection in this shadow tree');
+            'the current selection in this shadow tree');
 
 }), 'A_10_01_02_04_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html
index 1eb5b1ae..1892f0d1 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html
@@ -16,7 +16,7 @@
 <meta name="assert" content="ShadowRoot Object: Element? elementFromPoint(float x, float y) method">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -29,10 +29,10 @@
     d.body.appendChild(el);
 
     try {
-    	el.elementFromPoint(1, 1);
-    	assert_true(false, 'TypeMismatchError should be thrown');
+        el.elementFromPoint(1, 1);
+        assert_true(false, 'TypeMismatchError should be thrown');
     } catch(e) {
-    	assert_true(e instanceof TypeError, 'Wrong error type');
+        assert_true(e instanceof TypeError, 'Wrong error type');
     }
 
 }, 'A_10_01_02_06_01_T01');
@@ -44,7 +44,7 @@
 
     var el = d.createElement('div');
 
-    var s = el.createShadowRoot();
+    var s = el.attachShadow({mode: 'open'});
     d.body.appendChild(el);
 
     if (typeof(s) == 'undefined' || typeof (s.elementFromPoint(1, 1)) != 'object') {
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html
index e5e0acc..5f764d5 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html
@@ -16,45 +16,45 @@
 <meta name="assert" content="ShadowRoot Object: Element? elementFromPoint(float x, float y) method">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(function () {
 
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var el = d.createElement('div');
     d.body.appendChild(el);
 
-    var s = el.createShadowRoot();
+    var s = el.attachShadow({mode: 'open'});
 
     var span = d.createElement('span');
     span.innerHTML = 'Some text';
     s.appendChild(span);
 
     assert_equals(s.elementFromPoint(-1, 1), null, 'If x argument of elementFromPoint(x, y) is less ' +
-    		'than zero then method shold return null');
+            'than zero then method shold return null');
 
 }, 'A_10_01_02_06_02_T01');
 
 
 test(function () {
 
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var el = d.createElement('div');
     d.body.appendChild(el);
 
-    var s = el.createShadowRoot();
+    var s = el.attachShadow({mode: 'open'});
 
     var span = d.createElement('span');
     span.innerHTML = 'Some text';
     s.appendChild(span);
 
     assert_equals(s.elementFromPoint(1, -1), null, 'If y argument of elementFromPoint(x, y) is less ' +
-    		'than zero then method shold return null');
+            'than zero then method shold return null');
 
 }, 'A_10_01_02_06_02_T02');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html
index ff6d771..ff83012 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html
@@ -12,29 +12,30 @@
 <head>
 <title>Shadow DOM Test: A_10_01_02_09</title>
 <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
-<meta name="assert" content="ShadowRoot Object: Invoking the cloneNode() method on a ShadowRoot instance must always throw a DATA_CLONE_ERR exception.">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-node-clonenode">
+<meta name="assert" content="If context object is a shadow root, throw a NotSupportedError exception.">
 <script src="../../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../../resources/testharnessreport.js"></script>
-<script src="../../../testcommon.js"></script>
+<script src="../../../../../html/resources/common.js"></script>
+<script src="../../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
-
-	try {
-		s.cloneNode();
-		assert_true(false, 'Invoking the cloneNode() method on a ShadowRoot instance must always ' +
-    	'throw a DATA_CLONE_ERR exception.');
-	} catch (e) {
-		assert_equals(e.code, 25, 'Wrong exceprion type');
-	}
+    try {
+        s.cloneNode();
+        assert_true(false, 'Invoking the cloneNode() method on a ShadowRoot instance must always ' +
+        'throw a NotSupportedError (code 9) exception.');
+    } catch (e) {
+        assert_equals(e.code, 9, 'Wrong exception type');
+        assert_equals(e.name, 'NotSupportedError', 'Wrong exception name');
+    }
 }), 'A_10_01_02_09_T01');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html
deleted file mode 100644
index 2f5d628..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-001.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_04_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
-<meta name="assert" content="The content HTML element: fallback content">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content select=".clazz"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
-
-}), 'A_10_04_01_T01');
-
-
-
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content select=".shadow"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_equals(s.querySelector('#spandex').offsetTop, 0, 'Fallback content should not be rendered');
-
-}), 'A_10_04_01_T02');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html
deleted file mode 100644
index 0671a9a..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-002.html
+++ /dev/null
@@ -1,97 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_04_02</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
-<meta name="assert" content="The content HTML element: select attribute">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content select=".shadow"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_equals(s.querySelector('#spandex').offsetTop, 0, 'Fallback content should not be rendered');
-
-    assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 1: Element should not be rendered');
-    assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 2: Element should not be rendered');
-    assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 3: Element should not be rendered');
-
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 11: Element should be rendered');
-    assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 12: Element should be rendered');
-    assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 13: Element should be rendered');
-
-}), 'A_10_04_02_T01_01');
-
-
-
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content select=".shadow, #li4"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_equals(s.querySelector('#spandex').offsetTop, 0, 'Fallback content should not be rendered');
-
-    assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 1: Element should not be rendered');
-    assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 2: Element should not be rendered');
-
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 11: Element should be rendered');
-    assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 12: Element should be rendered');
-    assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 13: Element should be rendered');
-    assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 14: Element should be rendered');
-
-}), 'A_10_04_02_T01_02');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html
deleted file mode 100644
index b45d1e3..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-003.html
+++ /dev/null
@@ -1,129 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_04_03</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
-<meta name="assert" content="The content HTML element: invalid select attribute">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content select="&@()"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
-
-    assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Element should not be rendered');
-    assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Element should not be rendered');
-    assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Element should not be rendered');
-    assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Element should not be rendered');
-    assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Element should not be rendered');
-    assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 6: Element should not be rendered');
-
-}), 'A_10_04_03_T01');
-
-
-test(unit(function (ctx) {
-
-var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content select=".shadow, &@()"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
-
-    assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Element should not be rendered');
-    assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Element should not be rendered');
-    assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Element should not be rendered');
-    assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Element should not be rendered');
-    assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Element should not be rendered');
-    assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 6: Element should not be rendered');
-
-}), 'A_10_04_03_T02');
-
-
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content select=".shadow, &@(), #li4"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
-
-    assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Element should not be rendered');
-    assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Element should not be rendered');
-    assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Element should not be rendered');
-    assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Element should not be rendered');
-    assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Element should not be rendered');
-    assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 6: Element should not be rendered');
-
-}), 'A_10_04_03_T03');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html
deleted file mode 100644
index 8717c2c..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-005.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_04_05</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
-<meta name="assert" content="The content HTML element: reset-style-inheritance attribute">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul id="shHost">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-
-    var defHeight1 = d.querySelector('#li1').offsetHeight;
-    var defHeight2 = d.querySelector('#li2').offsetHeight;
-    var defHeight3 = d.querySelector('#li3').offsetHeight;
-    var defHeight4 = d.querySelector('#li4').offsetHeight;
-    var defHeight5 = d.querySelector('#li5').offsetHeight;
-    var defHeight6 = d.querySelector('#li6').offsetHeight;
-
-    assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
-    assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
-    assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
-    assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
-    assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
-    assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
-
-    var host = d.querySelector('#shHost');
-
-    d.body.setAttribute('style', 'font-size: 30px');
-
-    var height1 = d.querySelector('#li1').offsetHeight;
-    var height2 = d.querySelector('#li2').offsetHeight;
-    var height3 = d.querySelector('#li3').offsetHeight;
-    var height4 = d.querySelector('#li4').offsetHeight;
-    var height5 = d.querySelector('#li5').offsetHeight;
-    var height6 = d.querySelector('#li6').offsetHeight;
-
-
-    assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
-    assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
-    assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
-    assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
-    assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
-    assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
-
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML ='<ul><content select=".shadow"></content></ul>';
-    s.appendChild(div);
-
-    assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 21: Inherited ' +
-        'element style should be reset');
-    assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 22: Inherited ' +
-        'element style should be reset');
-    assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 23: Inherited ' +
-        'element style should be reset');
-
-    assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
-    assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
-    assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
-
-}), 'A_10_04_05_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html
deleted file mode 100644
index 50ccbcf..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-content-html-element/test-006.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_04_06</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
-<meta name="assert" content="The content HTML element: getDistributedNodes method">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content id="contentId" select=".clazz"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_equals(s.querySelector('#contentId').getDistributedNodes().length, 1,
-            'Fallback content should show up as distributed nodes');
-
-    assert_equals(s.querySelector('#contentId').getDistributedNodes()[0].id, 'spandex',
-            'Fallback content should show up as distributed nodes');
-
-}), 'A_10_04_06_T01');
-
-
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-        '<ul class="cls">' +
-            '<li id="li1" class="shadow">1</li>' +
-            '<li id="li2" class="shadow2">2</li>' +
-            '<li id="li3" class="shadow">3</li>' +
-            '<li id="li4">4</li>' +
-            '<li id="li5" class="shadow">5</li>' +
-            '<li id="li6" class="shadow2">6</li>' +
-        '</ul>';
-
-    var host = d.querySelector('.cls');
-    //Shadow root to play with
-    var s = host.createShadowRoot();
-
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-        '<ul><content id="contentId" select=".shadow"><span id="spandex">This is fallback content</span></content></ul>';
-    s.appendChild(div);
-
-    assert_equals(s.querySelector('#contentId').getDistributedNodes().length, 3,
-            'Wrond distributed nodes collection size');
-
-    assert_equals(s.querySelector('#contentId').getDistributedNodes()[0].getAttribute('id'), 'li1',
-            'Point 1: wrong element in distributed nodes collection');
-    assert_equals(s.querySelector('#contentId').getDistributedNodes()[1].getAttribute('id'), 'li3',
-        'Point 2: wrong element in distributed nodes collection');
-    assert_equals(s.querySelector('#contentId').getDistributedNodes()[2].getAttribute('id'), 'li5',
-        'Point 3: wrong element in distributed nodes collection');
-
-
-}), 'A_10_04_06_T02');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html
deleted file mode 100644
index 8942722d..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-001.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_05_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-element">
-<meta name="assert" content="The shadow HTML element: fallback content">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-
-	//Shadow root to play with
-	var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML = '' +
-		'<span id="spandex">This is a shadow root content</span>' +
-		'<shadow><span id="shadowId">This is a shadow fallback content</span></shadow>';
-	s.appendChild(div);
-
-	assert_true(s.querySelector('#shadowId').offsetTop == 0, 'Shadow fallback content should not be rendered in this case');
-
-}), 'A_10_05_01_T01');
-
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-
-	//Shadow root to play with
-	var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML = '' +
-		'<span id="spandex">This is a shadow root content</span>' +
-		'<content><span id="contentId">This is a content fallback</span></content>';
-	s.appendChild(div);
-
-	assert_true(s.querySelector('#contentId').offsetTop > 0, 'Fallback content should be rendered');
-
-}), 'A_10_05_01_T02');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html
deleted file mode 100644
index e5a96eb..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-002.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_05_02</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-element">
-<meta name="assert" content="The shadow HTML element: shadow insertion point">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-
-	//old tree
-	var s1 = host.createShadowRoot();
-	s1.innerHTML = '<span id="sp1">This is an old tree</span>';
-	//young tree
-	var s2 = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML = '' +
-		'<span id="spandex">This is a shadow root content</span>' +
-		'<shadow><span id="shadowId">This is a shadow fallback content</span></shadow>';
-	s2.appendChild(div);
-
-	assert_equals(s2.querySelector('#shadowId').offsetTop, 0, 'Fallback content should not be rendered');
-	assert_true(s1.querySelector('#sp1').offsetTop > 0, 'Old tree should be rendered');
-	assert_true(s2.querySelector('#spandex').offsetTop > 0, 'Element should be rendered');
-
-}), 'A_10_05_02_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html
deleted file mode 100644
index 010b13f..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/elements-and-dom-objects/the-shadow-html-element/test-004.html
+++ /dev/null
@@ -1,106 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_10_05_04</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-element">
-<meta name="assert" content="The shadow HTML element: no reset-style-inheritance attribute">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-// test no reset-style-inheritance
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-    	'<ul id="shHost">' +
-    		'<li id="li1" class="shadow">1</li>' +
-    		'<li id="li2" class="shadow2">2</li>' +
-    		'<li id="li3" class="shadow">3</li>' +
-    		'<li id="li4">4</li>' +
-    		'<li id="li5" class="shadow">5</li>' +
-    		'<li id="li6" class="shadow2">6</li>' +
-    	'</ul>';
-
-
-	var defHeight1 = d.querySelector('#li1').offsetHeight;
-	var defHeight2 = d.querySelector('#li2').offsetHeight;
-	var defHeight3 = d.querySelector('#li3').offsetHeight;
-	var defHeight4 = d.querySelector('#li4').offsetHeight;
-	var defHeight5 = d.querySelector('#li5').offsetHeight;
-	var defHeight6 = d.querySelector('#li6').offsetHeight;
-
-	assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
-	assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
-	assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
-	assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
-	assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
-	assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
-
-    var host = d.querySelector('#shHost');
-
-    d.body.setAttribute('style', 'font-size: 30px');
-
-	var height1 = d.querySelector('#li1').offsetHeight;
-	var height2 = d.querySelector('#li2').offsetHeight;
-	var height3 = d.querySelector('#li3').offsetHeight;
-	var height4 = d.querySelector('#li4').offsetHeight;
-	var height5 = d.querySelector('#li5').offsetHeight;
-	var height6 = d.querySelector('#li6').offsetHeight;
-
-
-	assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
-	assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
-	assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
-	assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
-	assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
-	assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
-
-	//Shadow root to play with
-    var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML ='<ul><content select=".shadow"></content></ul>';
-	s.appendChild(div);
-
-	assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 21: Element height should not be changed');
-	assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 22: Element height should not be changed');
-	assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 23: Element height should not be changed');
-
-	assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
-
-	//Young tree
-	var s2 = host.createShadowRoot();
-
-	var div2 = d.createElement('div');
-	div2.innerHTML = '<shadow></shadow>';
-	s2.appendChild(div2);
-
-	//styles should be reset
-	assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 31: Inherited ' +
-			'element style should not be reset');
-	assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 32: Inherited ' +
-			'element style should not be reset');
-	assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 33: Inherited ' +
-			'element style should not be reset');
-
-}), 'A_10_05_04_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html
index 732cae8..9b6806a 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-001.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Event Dispatch: At the time of event dispatch:The Event target and currentTarget attributes must return the relative target for the node on which event listeners are invoked">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -36,13 +37,13 @@
 
     //For #volume-slider-thumb relative target #volume-slider-thumb
     roots.volumeShadowRoot.querySelector('#volume-slider-thumb').addEventListener('click',
-	    A_05_05_01_T01.step_func(function(event) {
-	    	invoked = true;
-	    	assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
-	    			'Point 1: Wrong target');
-	    	assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-thumb',
-	    			'Point 1: Wrong currentTarget');
-	    }), false);
+        A_05_05_01_T01.step_func(function(event) {
+            invoked = true;
+            assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
+                    'Point 1: Wrong target');
+            assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-thumb',
+                    'Point 1: Wrong currentTarget');
+        }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ('click', true, false);
@@ -69,13 +70,13 @@
 
     //For #volume-shadow-root relative target #volume-slider-thumb
     roots.volumeShadowRoot.addEventListener('click',
-    		A_05_05_01_T02.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
-		    			'Wrong target');
-		    	assert_true(event.currentTarget == roots.volumeShadowRoot,
-		    			'Wrong currentTarget');
-	    }), false);
+            A_05_05_01_T02.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
+                        'Wrong target');
+                assert_true(event.currentTarget == roots.volumeShadowRoot,
+                        'Wrong currentTarget');
+        }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ('click', true, false);
@@ -102,19 +103,19 @@
 
     //For #volume-slider relative target #volume-shadow-host
     roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click',
-    		A_05_05_01_T03.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-		    			'Wrong target');
-		    	assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider',
-		    			'Wrong currentTarget');
-	    }), false);
+            A_05_05_01_T03.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                        'Wrong target');
+                assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider',
+                        'Wrong currentTarget');
+        }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ('click', true, false);
     roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
 
-   	assert_true(invoked, 'Event listener was not invoked');
+    assert_true(invoked, 'Event listener was not invoked');
 
     A_05_05_01_T03.done();
 }));
@@ -136,21 +137,21 @@
 
     //For #volume-slider-container relative target #volume-shadow-host
     roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click',
-    		A_05_05_01_T04.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-		    			'Wrong target');
-		    	assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-container',
-		    			'Wrong currentTarget');
-	    }), false);
+            A_05_05_01_T04.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                        'Wrong target');
+                assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-container',
+                        'Wrong currentTarget');
+        }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ('click', true, false);
     roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
 
-   	assert_true(invoked, 'Event listener was not invoked');
+    assert_true(invoked, 'Event listener was not invoked');
 
-   	A_05_05_01_T04.done();
+    A_05_05_01_T04.done();
 }));
 
 
@@ -169,21 +170,21 @@
 
     //For #controls relative target #volume-shadow-host
     roots.playerShadowRoot.querySelector('#controls').addEventListener('click',
-    		A_05_05_01_T05.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-		    			'Wrong target');
-		    	assert_equals(event.currentTarget.getAttribute('id'), 'controls',
-		    			'Wrong currentTarget');
-	    }), false);
+            A_05_05_01_T05.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                        'Wrong target');
+                assert_equals(event.currentTarget.getAttribute('id'), 'controls',
+                        'Wrong currentTarget');
+        }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ('click', true, false);
     roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
 
-   	assert_true(invoked, 'Event listener was not invoked');
+    assert_true(invoked, 'Event listener was not invoked');
 
-   	A_05_05_01_T05.done();
+    A_05_05_01_T05.done();
 }));
 
 
@@ -202,21 +203,21 @@
 
     //For #player-shadow-host relative target #player-shadow-host
     d.querySelector('#player-shadow-host').addEventListener('click',
-    		A_05_05_01_T06.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
-		    			'Wrong target');
-		    	assert_equals(event.currentTarget.getAttribute('id'), 'player-shadow-host',
-		    			'Wrong currentTarget');
-	    }), false);
+            A_05_05_01_T06.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
+                        'Wrong target');
+                assert_equals(event.currentTarget.getAttribute('id'), 'player-shadow-host',
+                        'Wrong currentTarget');
+        }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ('click', true, false);
     roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
 
-   	assert_true(invoked, 'Event listener was not invoked');
+    assert_true(invoked, 'Event listener was not invoked');
 
-   	A_05_05_01_T06.done();
+    A_05_05_01_T06.done();
 }));
 
 
@@ -236,21 +237,21 @@
 
     //For #player relative target #player-shadow-host
     d.querySelector('#player').addEventListener('click',
-    		A_05_05_01_T07.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
-		    			'Wrong target');
-		    	assert_equals(event.currentTarget.getAttribute('id'), 'player',
-		    			'Wrong currentTarget');
-	    }), false);
+            A_05_05_01_T07.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
+                        'Wrong target');
+                assert_equals(event.currentTarget.getAttribute('id'), 'player',
+                        'Wrong currentTarget');
+        }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ('click', true, false);
     roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
 
-   	assert_true(invoked, 'Event listener was not invoked');
+    assert_true(invoked, 'Event listener was not invoked');
 
-   	A_05_05_01_T07.done();
+    A_05_05_01_T07.done();
 }));
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html
index 3e2a82d..8792988 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-002.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Event Dispatch: The MouseEvent relatedTarget attribute must return the adjusted related target">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -36,11 +37,11 @@
 
     //For #volume-shadow-root adjusted related target #volume-shadow-root
     roots.volumeShadowRoot.addEventListener('mouseover',
-    		A_05_05_02_T01.step_func(function(event) {
-	    	invoked = true;
-	    	assert_true(event.relatedTarget === roots.volumeShadowRoot,
-	    			'Wrong relatedTarget');
-	    }), false);
+            A_05_05_02_T01.step_func(function(event) {
+            invoked = true;
+            assert_true(event.relatedTarget === roots.volumeShadowRoot,
+                    'Wrong relatedTarget');
+        }), false);
 
 
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html
index c69ee74a..ea4a5ca 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-dispatch/test-003.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Event Path Trimming: In cases where both relatedTarget and target of a trusted event are part of the same shadow tree, the conforming UAs must stop events at the shadow root to avoid the appearance of spurious mouseover and mouseout events firing from the same node.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -32,7 +33,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
     s.id = 'shadow';
 
     var input1 = d.createElement('input');
@@ -44,20 +45,20 @@
     s.appendChild(input2);
 
     input1.addEventListener('focusin', A_05_05_03_T01.step_func(function(event) {
-        assert_equals(event.deepPath.length, 7);
-        assert_equals(event.deepPath[0].id, 'input1');
-        assert_equals(event.deepPath[1].id, 'shadow');
-        assert_equals(event.deepPath[2].id, 'host');
-        assert_equals(event.deepPath[3].tagName, 'BODY');
-        assert_equals(event.deepPath[4].tagName, 'HTML');
-        assert_equals(event.deepPath[5], d);
-        assert_equals(event.deepPath[6], ctx.iframes[0].contentWindow);
+        assert_equals(event.deepPath().length, 7);
+        assert_equals(event.deepPath()[0].id, 'input1');
+        assert_equals(event.deepPath()[1].id, 'shadow');
+        assert_equals(event.deepPath()[2].id, 'host');
+        assert_equals(event.deepPath()[3].tagName, 'BODY');
+        assert_equals(event.deepPath()[4].tagName, 'HTML');
+        assert_equals(event.deepPath()[5], d);
+        assert_equals(event.deepPath()[6], ctx.iframes[0].contentWindow);
     }), false);
 
     input2.addEventListener('focusin', A_05_05_03_T01.step_func(function(event) {
-        assert_equals(event.deepPath.length, 2);
-        assert_equals(event.deepPath[0].id, 'input2');
-        assert_equals(event.deepPath[1].id, 'shadow');
+        assert_equals(event.deepPath().length, 2);
+        assert_equals(event.deepPath()[0].id, 'input2');
+        assert_equals(event.deepPath()[1].id, 'shadow');
         A_05_05_03_T01.done();
     }), false);
 
@@ -69,7 +70,7 @@
     // In this case, original relatedTarget is #input1, and original target
     // is #input2.
     // It should be viewed outside the shadow as "target == relatedTarget"
-    // after event retargeting, therefore, event.deepPath above the shadow
+    // after event retargeting, therefore, event.deepPath() above the shadow
     // host will be trimmed.
     // Expected event path for #input2:
     // <input>, #shadow-root
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html
index b97ad45..20366973 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-001.html
@@ -16,7 +16,7 @@
 <meta name="assert" content="Event Retargeting:test that event.target is retargeted when event crosses shadow boundary and vice versa">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -31,23 +31,23 @@
     iframe.onload = A_05_01_01_T1.step_func(function () {
 
     try {
-    	var d = iframe.contentDocument;
-    	var div = d.createElement('div');
-    	d.body.appendChild(div);
+        var d = iframe.contentDocument;
+        var div = d.createElement('div');
+        d.body.appendChild(div);
 
-    	var s = div.createShadowRoot();
+        var s = div.attachShadow({mode: 'open'});
 
-    	var div2 = d.createElement('div');
-    	s.appendChild(div2);
+        var div2 = d.createElement('div');
+        s.appendChild(div2);
 
-    	var inp = d.createElement('input');
-    	inp.setAttribute('type', 'text');
-    	inp.setAttribute('id', 'inpid');
-    	div2.appendChild(inp);
+        var inp = d.createElement('input');
+        inp.setAttribute('type', 'text');
+        inp.setAttribute('id', 'inpid');
+        div2.appendChild(inp);
 
-    	div2.addEventListener('click', A_05_01_01_T1.step_func(function (event) {
+        div2.addEventListener('click', A_05_01_01_T1.step_func(function (event) {
             assert_equals(event.target.tagName, 'INPUT', 'Information about target of the event that ' +
-            		'doesn\'t cross the shadow boundaries should not be adjusted');
+                    'doesn\'t cross the shadow boundaries should not be adjusted');
         }), false);
 
         var event = d.createEvent('HTMLEvents');
@@ -72,24 +72,24 @@
     iframe.onload = A_05_01_01_T2.step_func(function () {
 
     try {
-    	var d = iframe.contentDocument;
+        var d = iframe.contentDocument;
 
-    	var div = d.createElement('div');
-    	d.body.appendChild(div);
+        var div = d.createElement('div');
+        d.body.appendChild(div);
 
-    	var s = div.createShadowRoot();
+        var s = div.attachShadow({mode: 'open'});
 
-    	var div2 = d.createElement('div');
-    	s.appendChild(div2);
+        var div2 = d.createElement('div');
+        s.appendChild(div2);
 
-    	var inp = d.createElement('input');
-    	inp.setAttribute('type', 'text');
-    	inp.setAttribute('id', 'inpid');
-    	div2.appendChild(inp);
+        var inp = d.createElement('input');
+        inp.setAttribute('type', 'text');
+        inp.setAttribute('id', 'inpid');
+        div2.appendChild(inp);
 
-    	div.addEventListener('click', A_05_01_01_T2.step_func(function (event) {
+        div.addEventListener('click', A_05_01_01_T2.step_func(function (event) {
             assert_equals(event.target.tagName, 'DIV', 'Information about event target crossing ' +
-            		'the shadow boundaries should be adjusted');
+                    'the shadow boundaries should be adjusted');
         }), false);
 
         var event = d.createEvent('HTMLEvents');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-002.html
deleted file mode 100644
index b63fde3..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-002.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_05_01_02</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-retargeting">
-<meta name="assert" content="Event Retargeting:Event retargeting for document nodes distributed among insertion points">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_05_01_02_T1 = async_test('A_05_01_02_T1');
-
-A_05_01_02_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_05_01_02_T1.step_func(function () {
-
-    try {
-    	var d = iframe.contentDocument;
-
-        var ul = d.querySelector('ul.stories');
-        var s = ul.createShadowRoot();
-
-        //make shadow subtree
-        var div = document.createElement('div');
-        div.innerHTML = '<ul id="ip_wrapper"><content select=".shadow"></content></ul>';
-        s.appendChild(div);
-
-    	d.body.addEventListener('click', A_05_01_02_T1.step_func(function (event) {
-            assert_equals(event.target.tagName, 'LI', 'Incorrect target');
-        }), false);
-
-        var event = d.createEvent('HTMLEvents');
-        event.initEvent ("click", true, false);
-        d.querySelector('#li3').dispatchEvent(event);
-    } finally {
-        iframe.parentNode.removeChild(iframe);
-    }
-    A_05_01_02_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html
index 90150b2..61e8ab5 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-003.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Event Retargeting:Event retargeting for fallback content">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -24,36 +25,36 @@
 var A_05_01_03_T01 = async_test('A_05_01_03_T01');
 
 A_05_01_03_T01.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
     d.body.innerHTML = '' +
-	'<div id="main">' +
-		'<div id="shadow-root">' +
-			'<span>1</span>' +
-			'<span>2</span>' +
-			'<span>3</span>' +
-	    '</div>' +
-	'</div>';
+    '<div id="main">' +
+        '<div id="shadow-root">' +
+            '<span>1</span>' +
+            '<span>2</span>' +
+            '<span>3</span>' +
+        '</div>' +
+    '</div>';
 
     var ul = d.querySelector('#shadow-root');
-    var s = ul.createShadowRoot();
+    var s = ul.attachShadow({mode: 'open'});
 
     //make shadow subtree
     var div = document.createElement('div');
-    div.innerHTML = '<content select=".shadow"><span id="flbk">Fallback item</span></content>';
+    div.innerHTML = '<slot name="shadow"><span id="flbk">Fallback item</span></slot>';
     s.appendChild(div);
 
-	d.body.addEventListener('click', A_05_01_03_T01.step_func(function (event) {
+    d.body.addEventListener('click', A_05_01_03_T01.step_func(function (event) {
         assert_equals(event.target.getAttribute('id'), 'shadow-root', 'Information about ' +
-        		'event target crossing the shadow boundaries should be adjusted for the fallback ' +
-        		'content');
+                'event target crossing the shadow boundaries should be adjusted for the fallback ' +
+                'content');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
     event.initEvent ("click", true, false);
     s.querySelector('#flbk').dispatchEvent(event);
 
-	A_05_01_03_T01.done();
+    A_05_01_03_T01.done();
 }));
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html
index 32853e9..e172e3d45 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/event-retargeting/test-004.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Event Retargeting:Retargeting algorithm">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -24,18 +25,18 @@
 var A_05_01_04_T01 = async_test('A_05_01_04_T01');
 
 A_05_01_04_T01.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
     //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
     //For #volume-slider-thumb relative target is #volume-slider-thumb
     roots.volumeShadowRoot.querySelector('#volume-slider-thumb').addEventListener('click',
-    	A_05_01_04_T01.step_func(function (event) {
-    		invoked = true;
-	        assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
-        		'Wrong related target');
+        A_05_01_04_T01.step_func(function (event) {
+            invoked = true;
+            assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
+                'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -44,7 +45,7 @@
 
     assert_true(invoked, 'Event listener was not invoked');
 
-	A_05_01_04_T01.done();
+    A_05_01_04_T01.done();
 }));
 
 
@@ -52,8 +53,8 @@
 var A_05_01_04_T02 = async_test('A_05_01_04_T02');
 
 A_05_01_04_T02.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -61,10 +62,10 @@
 
     //For #volume-shadow-host relative target is #volume-shadow-host
     roots.playerShadowRoot.querySelector('#volume-shadow-host').addEventListener('click',
-    	A_05_01_04_T02.step_func(function (event) {
-    		invoked = true;
-	        assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-        		'Wrong related target');
+        A_05_01_04_T02.step_func(function (event) {
+            invoked = true;
+            assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -82,8 +83,8 @@
 var A_05_01_04_T03 = async_test('A_05_01_04_T03');
 
 A_05_01_04_T03.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -91,10 +92,10 @@
 
     //For #volume-slider relative target is #volume-shadow-host
     roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click',
-    		A_05_01_04_T03.step_func(function (event) {
-    			invoked = true;
-	        assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-        		'Wrong related target');
+            A_05_01_04_T03.step_func(function (event) {
+                invoked = true;
+            assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -110,8 +111,8 @@
 var A_05_01_04_T04 = async_test('A_05_01_04_T04');
 
 A_05_01_04_T04.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -119,10 +120,10 @@
 
     //For #volume-slider-container relative target is #volume-shadow-host
     roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click',
-    		A_05_01_04_T04.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-	        		'Wrong related target');
+            A_05_01_04_T04.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -138,8 +139,8 @@
 var A_05_01_04_T05 = async_test('A_05_01_04_T05');
 
 A_05_01_04_T05.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -147,10 +148,10 @@
 
     //For #controls relative target is #volume-shadow-host
     roots.playerShadowRoot.querySelector('#controls').addEventListener('click',
-    		A_05_01_04_T05.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-	        		'Wrong related target');
+            A_05_01_04_T05.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -166,8 +167,8 @@
 var A_05_01_04_T06 = async_test('A_05_01_04_T06');
 
 A_05_01_04_T06.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -175,10 +176,10 @@
 
     //For #player-shadow-host relative target is #player-shadow-host
     roots.playerShadowRoot.addEventListener('click',
-    		A_05_01_04_T06.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
-	        		'Wrong related target');
+            A_05_01_04_T06.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-shadow-host',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -195,8 +196,8 @@
 var A_05_01_04_T07 = async_test('A_05_01_04_T07');
 
 A_05_01_04_T07.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -204,10 +205,10 @@
 
     //For #player relative target is #player-shadow-host
     d.querySelector('#player').addEventListener('click',
-    		A_05_01_04_T07.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
-	        		'Wrong related target');
+            A_05_01_04_T07.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -223,8 +224,8 @@
 var A_05_01_04_T08 = async_test('A_05_01_04_T08');
 
 A_05_01_04_T08.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -232,10 +233,10 @@
 
     //For #volume-slider relative target is #volume-slider
     roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click',
-    		A_05_01_04_T08.step_func(function (event) {
-    			invoked = true;
-	        assert_equals(event.target.getAttribute('id'), 'volume-slider',
-        		'Wrong related target');
+            A_05_01_04_T08.step_func(function (event) {
+                invoked = true;
+            assert_equals(event.target.getAttribute('id'), 'volume-slider',
+                'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -251,8 +252,8 @@
 var A_05_01_04_T09 = async_test('A_05_01_04_T09');
 
 A_05_01_04_T09.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -260,10 +261,10 @@
 
     //For #volume-slider-container relative target is #volume-slider
     roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click',
-    		A_05_01_04_T09.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'volume-slider',
-	        		'Wrong related target');
+            A_05_01_04_T09.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-slider',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -279,8 +280,8 @@
 var A_05_01_04_T10 = async_test('A_05_01_04_T10');
 
 A_05_01_04_T10.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -288,10 +289,10 @@
 
     //For #controls relative target is #volume-slider
     roots.playerShadowRoot.querySelector('#controls').addEventListener('click',
-    		A_05_01_04_T10.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'volume-slider',
-	        		'Wrong related target');
+            A_05_01_04_T10.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-slider',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -307,8 +308,8 @@
 var A_05_01_04_T11 = async_test('A_05_01_04_T11');
 
 A_05_01_04_T11.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -316,10 +317,10 @@
 
     //For #player-shadow-root relative target is #volume-slider
     roots.playerShadowRoot.addEventListener('click',
-    		A_05_01_04_T11.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'volume-slider',
-	        		'Wrong related target');
+            A_05_01_04_T11.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-slider',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
@@ -336,8 +337,8 @@
 var A_05_01_04_T12 = async_test('A_05_01_04_T12');
 
 A_05_01_04_T12.step(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-	var invoked = false;
+    var d = newRenderedHTMLDocument(ctx);
+    var invoked = false;
     roots = createTestMediaPlayer(d);
 
     //expected result of what relative target should be see
@@ -345,10 +346,10 @@
 
     //For #player relative target is #player-shadow-host
     d.querySelector('#player').addEventListener('click',
-    		A_05_01_04_T12.step_func(function (event) {
-    			invoked = true;
-		        assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
-	        		'Wrong related target');
+            A_05_01_04_T12.step_func(function (event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'player-shadow-host',
+                    'Wrong related target');
     }), false);
 
     var event = d.createEvent('HTMLEvents');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html
index af29e0a0..4ba00c6 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-001.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html
index ead61905..1fdeaa3 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-002.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html
index ee4bcf3..cd603fa 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-003.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html
index 28ac700..df2a4513 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-004.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html
index f4e9c241..f6266c8 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-005.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html
index 7e14e60..bff6361 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-006.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html
index ee83903..4d76232 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-007.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html
index 0585f8e3..9c78269 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-008.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html
index 41c75fd..4ad2957 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/events-created-by-users-do-not-stop/test-009.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="The following events must not be stopped at the nearest shadow boundary if created by users: abort, error, select, change, load, reset, resize, scroll, selectstart">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html
index 44cc04c..096ff668 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-001.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Retargeting focus events:The focus, DOMFocusIn, blur, and DOMFocusOut events must be treated in the same way as events with a relatedTarget, where the corresponding node that is losing focus as a result of target gaining focus or the node that is gaining focus, and thus causing the blurring of target acts as the related target">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -37,7 +38,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
@@ -50,11 +51,11 @@
     d.body.appendChild(inp2);
 
     s.addEventListener('DOMFocusOut', A_05_03_01_T01.step_func(function(event) {
-    	assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: Wrong target');
+        assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: Wrong target');
     }), false);
 
     d.body.addEventListener('DOMFocusOut', A_05_03_01_T01.step_func(function(event) {
-    	assert_equals(event.target.getAttribute('id'), 'host', 'Inside shadow tree: Wrong target');
+        assert_equals(event.target.getAttribute('id'), 'host', 'Inside shadow tree: Wrong target');
     }), false);
 
     inp1.focus();
@@ -77,7 +78,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
@@ -92,11 +93,11 @@
     inp2.focus();
 
     s.addEventListener('DOMFocusIn', A_05_03_01_T02.step_func(function(event) {
-    	assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+        assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
     }), false);
 
     d.body.addEventListener('DOMFocusIn', A_05_03_01_T02.step_func(function(event) {
-    	assert_equals(event.target.getAttribute('id'), 'host', 'Outside shadow tree: Wrong target');
+        assert_equals(event.target.getAttribute('id'), 'host', 'Outside shadow tree: Wrong target');
     }), false);
 
     inp1.focus();
@@ -120,7 +121,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var inp1 = d.createElement('input');
     inp1.setAttribute('id', 'inp1');
@@ -135,7 +136,7 @@
     inp1.focus();
 
     d.body.addEventListener('DOMFocusIn', A_05_03_01_T03.step_func(function(event) {
-    	assert_true(false, 'Event should be stopped at Shadow boundary');
+        assert_true(false, 'Event should be stopped at Shadow boundary');
     }), false);
 
     inp2.focus();
@@ -152,35 +153,35 @@
 
 A_05_03_01_T04.step(unit(function (ctx) {
 
-	 var d = newRenderedHTMLDocument(ctx);
+     var d = newRenderedHTMLDocument(ctx);
 
-	 var host = d.createElement('div');
-	 host.setAttribute('style', 'height:50%; width:100%');
-	 host.setAttribute('id', 'host');
-	 d.body.appendChild(host);
+     var host = d.createElement('div');
+     host.setAttribute('style', 'height:50%; width:100%');
+     host.setAttribute('id', 'host');
+     d.body.appendChild(host);
 
-	 //Shadow root to play with
-	 var s = host.createShadowRoot();
+     //Shadow root to play with
+     var s = host.attachShadow({mode: 'open'});
 
-	 var inp1 = d.createElement('input');
-	 inp1.setAttribute('id', 'inp1');
-	 inp1.setAttribute('type', 'checkbox');
-	 s.appendChild(inp1);
+     var inp1 = d.createElement('input');
+     inp1.setAttribute('id', 'inp1');
+     inp1.setAttribute('type', 'checkbox');
+     s.appendChild(inp1);
 
-	 var inp2 = d.createElement('input');
-	 inp2.setAttribute('id', 'inp2');
-	 inp2.setAttribute('type', 'checkbox');
-	 s.appendChild(inp2);
+     var inp2 = d.createElement('input');
+     inp2.setAttribute('id', 'inp2');
+     inp2.setAttribute('type', 'checkbox');
+     s.appendChild(inp2);
 
-	 inp1.focus();
+     inp1.focus();
 
-	 d.body.addEventListener('DOMFocusOut', A_05_03_01_T04.step_func(function(event) {
-	 	assert_true(false, 'Event should be stopped at Shadow boundary');
-	 }), false);
+     d.body.addEventListener('DOMFocusOut', A_05_03_01_T04.step_func(function(event) {
+        assert_true(false, 'Event should be stopped at Shadow boundary');
+     }), false);
 
-	 inp2.focus();
+     inp2.focus();
 
-	 A_05_03_01_T04.done();
+     A_05_03_01_T04.done();
 }));
 
 
@@ -192,63 +193,63 @@
 
 A_05_03_01_T05.step(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	host.setAttribute('id', 'host');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    host.setAttribute('id', 'host');
+    d.body.appendChild(host);
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('id', 'inp1');
-	inp1.setAttribute('type', 'checkbox');
-	inp1.setAttribute('class', 'clazz1');
-	host.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('id', 'inp1');
+    inp1.setAttribute('type', 'checkbox');
+    inp1.setAttribute('slot', 'slot1');
+    host.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('id', 'inp2');
-	inp2.setAttribute('type', 'checkbox');
-	inp2.setAttribute('class', 'clazz2');
-	host.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('id', 'inp2');
+    inp2.setAttribute('type', 'checkbox');
+    inp2.setAttribute('slot', 'slot2');
+    host.appendChild(inp2);
 
-	var inp3 = d.createElement('input');
-	inp3.setAttribute('id', 'inp3');
-	inp3.setAttribute('type', 'checkbox');
-	inp3.setAttribute('class', 'clazz1');
-	host.appendChild(inp3);
+    var inp3 = d.createElement('input');
+    inp3.setAttribute('id', 'inp3');
+    inp3.setAttribute('type', 'checkbox');
+    inp3.setAttribute('slot', 'slot1');
+    host.appendChild(inp3);
 
 
-	//Shadow root to play with
-	var s = host.createShadowRoot();
+    //Shadow root to play with
+    var s = host.attachShadow({mode: 'open'});
 
-	var shadowDiv = document.createElement('div');
-	shadowDiv.innerHTML = '<content select=".clazz1"></content>';
-	s.appendChild(shadowDiv);
+    var shadowDiv = document.createElement('div');
+    shadowDiv.innerHTML = '<slot name="slot1"></slot>';
+    s.appendChild(shadowDiv);
 
-	//element outside the shadow tree
-	var inp4 = d.createElement('input');
-	inp4.setAttribute('id', 'inp4');
-	inp4.setAttribute('type', 'checkbox');
-	inp4.setAttribute('class', 'clazz1');
-	d.body.appendChild(inp4);
+    //element outside the shadow tree
+    var inp4 = d.createElement('input');
+    inp4.setAttribute('id', 'inp4');
+    inp4.setAttribute('type', 'checkbox');
+    inp4.setAttribute('slot', 'slot1');
+    d.body.appendChild(inp4);
 
-	inp1.focus();
+    inp1.focus();
 
-	s.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) {
-		assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' +
-				'Event for nodes, distributed ' +
-				'agains insertion points shouldn\'t be retargeted');
-	}), false);
+    s.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) {
+        assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' +
+                'Event for nodes, distributed ' +
+                'agains insertion points shouldn\'t be retargeted');
+    }), false);
 
 
-	d.body.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) {
-		assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' +
-				'Event for nodes, distributed ' +
-				'agains insertion points shouldn\'t be retargeted');
-	}), false);
+    d.body.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) {
+        assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' +
+                'Event for nodes, distributed ' +
+                'agains insertion points shouldn\'t be retargeted');
+    }), false);
 
-	inp4.focus();
+    inp4.focus();
 
-	A_05_03_01_T05.done();
+    A_05_03_01_T05.done();
 }));
 
 
@@ -258,63 +259,63 @@
 
 A_05_03_01_T06.step(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	host.setAttribute('id', 'host');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    host.setAttribute('id', 'host');
+    d.body.appendChild(host);
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('id', 'inp1');
-	inp1.setAttribute('type', 'checkbox');
-	inp1.setAttribute('class', 'clazz1');
-	host.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('id', 'inp1');
+    inp1.setAttribute('type', 'checkbox');
+    inp1.setAttribute('slot', 'slot1');
+    host.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('id', 'inp2');
-	inp2.setAttribute('type', 'checkbox');
-	inp2.setAttribute('class', 'clazz2');
-	host.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('id', 'inp2');
+    inp2.setAttribute('type', 'checkbox');
+    inp2.setAttribute('slot', 'slot2');
+    host.appendChild(inp2);
 
-	var inp3 = d.createElement('input');
-	inp3.setAttribute('id', 'inp3');
-	inp3.setAttribute('type', 'checkbox');
-	inp3.setAttribute('class', 'clazz1');
-	host.appendChild(inp3);
+    var inp3 = d.createElement('input');
+    inp3.setAttribute('id', 'inp3');
+    inp3.setAttribute('type', 'checkbox');
+    inp3.setAttribute('slot', 'slot1');
+    host.appendChild(inp3);
 
 
-	//Shadow root to play with
-	var s = host.createShadowRoot();
+    //Shadow root to play with
+    var s = host.attachShadow({mode: 'open'});
 
-	var shadowDiv = document.createElement('div');
-	shadowDiv.innerHTML = '<content select=".clazz1"></content>';
-	s.appendChild(shadowDiv);
+    var shadowDiv = document.createElement('div');
+    shadowDiv.innerHTML = '<slot name="slot1"></slot>';
+    s.appendChild(shadowDiv);
 
-	//element outside the shadow tree
-	var inp4 = d.createElement('input');
-	inp4.setAttribute('id', 'inp4');
-	inp4.setAttribute('type', 'checkbox');
-	inp4.setAttribute('class', 'clazz1');
-	d.body.appendChild(inp4);
+    //element outside the shadow tree
+    var inp4 = d.createElement('input');
+    inp4.setAttribute('id', 'inp4');
+    inp4.setAttribute('type', 'checkbox');
+    inp4.setAttribute('slot', 'slot1');
+    d.body.appendChild(inp4);
 
-	inp4.focus();
+    inp4.focus();
 
-	s.addEventListener('DOMFocusIn', A_05_03_01_T06.step_func(function(event) {
-		assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' +
-				'Event for nodes, distributed ' +
-				'agains insertion points shouldn\'t be retargeted');
-	}), false);
+    s.addEventListener('DOMFocusIn', A_05_03_01_T06.step_func(function(event) {
+        assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' +
+                'Event for nodes, distributed ' +
+                'agains insertion points shouldn\'t be retargeted');
+    }), false);
 
 
-	d.body.addEventListener('DOMFocusIn', A_05_03_01_T05.step_func(function(event) {
-		assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' +
-				'Event for nodes, distributed ' +
-				'agains insertion points shouldn\'t be retargeted');
-	}), false);
+    d.body.addEventListener('DOMFocusIn', A_05_03_01_T05.step_func(function(event) {
+        assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' +
+                'Event for nodes, distributed ' +
+                'agains insertion points shouldn\'t be retargeted');
+    }), false);
 
-	inp1.focus();
+    inp1.focus();
 
-	A_05_03_01_T06.done();
+    A_05_03_01_T06.done();
 }));
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html
index 0682394..385d774 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Retargeting focus events:The blur event must be treated in the same way as events with a relatedTarget, where the node that is gaining focus causing the blurring of target acts as the related target">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -40,11 +41,11 @@
 
     //For #volume-slider relative target is #volume-slider
     roots.playerShadowRoot.querySelector('.volume-slider').addEventListener('blur',
-    		A_05_03_02_T01.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'volume-slider',
-		    			'Wrong target');
-	    }), false);
+            A_05_03_02_T01.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-slider',
+                        'Wrong target');
+        }), false);
 
     // move focus out of shadow tree. blur should be fired
     d.querySelector('#outside-control').focus();
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html
index 438ef6cf..52c9540c 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Retargeting focus events:The focus event must be treated in the same way as events with a relatedTarget, where the corresponding node that is losing focus as a result of target gaining focus or the node that is gaining focus">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -40,11 +41,11 @@
 
     //For #volume-slider relative target is #volume-slider
     roots.playerShadowRoot.querySelector('.volume-slider').addEventListener('focus',
-    		A_05_03_03_T01.step_func(function(event) {
-    			invoked = true;
-		    	assert_equals(event.target.getAttribute('id'), 'volume-slider',
-		    			'Wrong target');
-	    }), false);
+            A_05_03_03_T01.step_func(function(event) {
+                invoked = true;
+                assert_equals(event.target.getAttribute('id'), 'volume-slider',
+                        'Wrong target');
+        }), false);
 
     roots.playerShadowRoot.querySelector('.volume-slider').focus();
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html
index 421c16b..641f251 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-001.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Retargeting relatedTarget:Event retargeting is a process of computing relative targets for each ancestor of the node at which the event is dispatched. A relative target is a DOM node that most accurately represents the target of a dispatched event at a given ancestor while maintaining the upper boundary encapsulation.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var div1 = d.createElement('div');
     div1.setAttribute('style', 'height:40px; width:100%');
@@ -46,11 +47,11 @@
     s.appendChild(div2);
 
     s.addEventListener('mouseover', A_05_02_01_T01.step_func(function(event) {
-    	assert_equals(event.relatedTarget.getAttribute('id'), 'div1', 'Wrong relatedTarget');
+        assert_equals(event.relatedTarget.getAttribute('id'), 'div1', 'Wrong relatedTarget');
     }), false);
 
     d.body.addEventListener('mouseover', A_05_02_01_T01.step_func(function(event) {
-    	assert_true(false, 'Event must be stopped at Shadow boundary');
+        assert_true(false, 'Event must be stopped at Shadow boundary');
     }), false);
 
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html
index c612142..0fdd621 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-002.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Retargeting relatedTarget:For a given node, the relatedTarget must be changed to its ancestor (or self) that is in the same shadow tree as the node">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,7 +34,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var div1 = d.createElement('div');
     div1.setAttribute('style', 'height:100%; width:100%');
@@ -46,7 +47,7 @@
     d.body.appendChild(div2);
 
     d.body.addEventListener('mouseover', A_05_02_02_T01.step_func(function(event) {
-    	assert_equals(event.relatedTarget.getAttribute('id'), 'host', 'Wrong related target');
+        assert_equals(event.relatedTarget.getAttribute('id'), 'host', 'Wrong related target');
     }), false);
 
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html
index 10fb3e3..7aa1a01 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/retargeting-relatedtarget/test-003.html
@@ -12,11 +12,12 @@
 <head>
 <title>Shadow DOM Test: A_05_02_03</title>
 <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-201305214#retargeting-related-target">
-<meta name="assert" content="Retargeting relatedTarget:Event listeners must not be invoked on a node for which the target and relatedTarget are the same.">
+<link rel="help" href="https://w3c.github.io/webcomponents/spec/shadow/#event-relatedtarget-retargeting">
+<meta name="assert" content="The value of the Event object's relatedTarget attribute must be the result of the retargeting algorithm with the event's currentTarget and relatedTarget as input. The result is called a relative related target.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -33,27 +34,19 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var div1 = d.createElement('div');
     div1.setAttribute('style', 'height:100%; width:100%');
     div1.setAttribute('id', 'div1');
     s.appendChild(div1);
 
-    var div2 = d.createElement('div');
-    div2.setAttribute('style', 'height:100%; width:100%');
-    div2.setAttribute('id', 'div2');
-    s.appendChild(div2);
-
-    s.addEventListener('mouseover', A_05_02_03_T01.step_func(function(event) {
-    	assert_true(false, 'Event listeners shouldn\'t be invoked if target and relatedTarget are the same');
+    host.addEventListener('mouseover', A_05_02_03_T01.step_func(function(event) {
+        assert_unreached('Event listeners shouldn\'t be invoked if relative target and relative related target are the same');
     }), false);
 
-
-    var evt = document.createEvent("MouseEvents");
-    evt.initMouseEvent("mouseover", true, false, window,
-      0, 10, 10, 10, 10, false, false, false, false, 0, div1);
-
+    var evt = new MouseEvent("mouseover",
+                             { relatedTarget: div1, relatedTargetScoped: true });
     div1.dispatchEvent(evt);
 
     A_05_02_03_T01.done();
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/test-001.html
index 3746a698..d86c72a 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/events/test-001.html
@@ -16,7 +16,7 @@
 <meta name="assert" content="Events:The mutation event types must never be dispatched in a shadow DOM subtree.">
 <script src="../../../../../resources/testharness.js"></script>
 <script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -31,34 +31,34 @@
     iframe.onload = A_05_00_01_T1.step_func(function () {
 
     try {
-    	var d = iframe.contentDocument;
+        var d = iframe.contentDocument;
 
-    	var div = d.createElement('div');
-    	d.body.appendChild(div);
+        var div = d.createElement('div');
+        d.body.appendChild(div);
 
-    	var s = div.createShadowRoot();
+        var s = div.attachShadow({mode: 'open'});
 
-    	var div2 = d.createElement('div');
-    	s.appendChild(div2);
+        var div2 = d.createElement('div');
+        s.appendChild(div2);
 
-    	var inp = d.createElement('input');
-    	inp.setAttribute('type', 'text');
-    	inp.setAttribute('id', 'inpid');
-    	div2.appendChild(inp);
+        var inp = d.createElement('input');
+        inp.setAttribute('type', 'text');
+        inp.setAttribute('id', 'inpid');
+        div2.appendChild(inp);
 
-    	div2.addEventListener('DOMAttrModified', A_05_00_01_T1.step_func(function (event) {
+        div2.addEventListener('DOMAttrModified', A_05_00_01_T1.step_func(function (event) {
             assert_true(false, 'The mutation event types must never be dispatched in a shadow DOM subtree');
         }), false);
-    	/*
-		var attr = inp.getAttributeNode ("value");
+        /*
+        var attr = inp.getAttributeNode ("value");
         var event = d.createEvent('MutationEvent');
         event.initMutationEvent ("DOMAttrModified", true, true, attr, null, 'new value', "value", MutationEvent.MODIFICATION);
         inp.dispatchEvent(event);
-        	*/
-    	inp.value = 'new value';
-    	inp.setAttribute ("newAttr" , "firstValue");
-    	inp.setAttribute ("newAttr" , "secondValue");
-    	inp.removeAttribute ("newAttr");
+            */
+        inp.value = 'new value';
+        inp.setAttribute ("newAttr" , "firstValue");
+        inp.setAttribute ("newAttr" , "secondValue");
+        inp.removeAttribute ("newAttr");
     } finally {
         iframe.parentNode.removeChild(iframe);
     }
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html
deleted file mode 100644
index 3d71be4..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-001.html
+++ /dev/null
@@ -1,231 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_09_00_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
-<meta name="assert" content="HTML Elements and Their Shadow Trees: If the element can have fallback content, UA should allow the shadow tree to contain at least one insertion point.">
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-//test iframe
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('iframe');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'Iframe should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T01');
-
-
-//test object
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('object');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'object should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T02');
-
-
-//test video
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('video');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'video should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T03');
-
-
-//test audio
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('audio');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'audio should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T04');
-
-
-//test canvas
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('canvas');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'canvas should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T05');
-
-
-//test map
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-    var img = d.createElement('img');
-    img.setAttribute('usemap', '#theMap');
-    img.setAttribute('width', '20px');
-    img.setAttribute('height', '20px');
-    d.body.appendChild(img);
-
-
-	// create element
-    var el = d.createElement('map');
-    el.setAttribute('name', 'theMap');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-		'<span id="shadow">This is a node that should be distributed</span>' +
-		'<span id="flbk">This is a fallback content</span>';
-
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'map should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T06');
-
-
-//test textarea
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('textarea');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'textarea should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T07');
-
-
-//test progress
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('progress');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'progress should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T08');
-
-
-//test meter
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('meter');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'meter should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_01_T09');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html
deleted file mode 100644
index 6b6b9770..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-002.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_09_00_02</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
-<meta name="assert" content="HTML Elements and Their Shadow Trees: Elements that have no fallback content should allow the shadow tree to contain no insertion points or an insertion point that matches nothing">
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-//test img
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('img');
-    d.body.appendChild(el);
-
-    var s = el.createShadowRoot();
-
-    s.innerHTML = '<content id="cont" select="#shadow"></content>';
-
-    assert_true(s.querySelector('#cont') != null, 'img should allow one insertion point ' +
-    		'that matches nothing');
-
-}), 'A_09_00_02_T01');
-
-
-//test embed
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('embed');
-    d.body.appendChild(el);
-
-    var s = el.createShadowRoot();
-
-    s.innerHTML = '<content id="cont" select="#shadow"></content>';
-
-    assert_true(s.querySelector('#cont') != null, 'embed should allow one insertion point ' +
-    		'that matches nothing');
-
-}), 'A_09_00_02_T02');
-
-
-//test embed
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('input');
-    d.body.appendChild(el);
-
-    var s = el.createShadowRoot();
-
-    s.innerHTML = '<content id="cont" select="#shadow"></content>';
-
-    assert_true(s.querySelector('#cont') != null, 'input should allow one insertion point ' +
-    		'that matches nothing');
-
-}), 'A_09_00_02_T03');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html
deleted file mode 100644
index 9d23020f..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-003.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_09_00_03</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
-<meta name="assert" content="HTML Elements and Their Shadow Trees: Check that fieldset can contain at least two insertion points with matching criteria 'legend:first-of-type' and 'universal selector'">
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-//test universal selector
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('fieldset');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'fieldset should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_03_T01');
-
-
-
-//test legend:first-of-type
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('fieldset');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<legend>'
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'</legend>' +
-    	'<span id="flbk">Unlucky content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="legend:first-of-type"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, 'fieldset should allow insertion point ' +
-    		'with legend:first-of-type matching criteria');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_03_T02');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html
deleted file mode 100644
index 325ce1a..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-and-their-shadow-trees/test-004.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_09_00_04</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
-<meta name="assert" content="HTML Elements and Their Shadow Trees: Check that details can contain at least two insertion points with matching criteria 'summary:first-of-type' and 'universal selector'">
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-//test universal selector
-test(unit(function (ctx) {
-
-	var d = newRenderedHTMLDocument(ctx);
-
-	// create element
-    var el = d.createElement('details');
-    el.setAttribute('open', 'open');
-    d.body.appendChild(el);
-
-    el.innerHTML = '' +
-    	'<span id="shadow">This is a node that should be distributed</span>' +
-    	'<span id="flbk">This is a fallback content</span>';
-
-    var s = el.createShadowRoot();
-    s.innerHTML = '<content select="#shadow"></content>';
-
-    assert_true(d.querySelector('#shadow').offsetTop > 0, '\'details\' should allow at least one insertion point');
-    assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
-
-}), 'A_09_00_04_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html
index 895ab7b..22dd26f 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-001.html
@@ -16,14 +16,14 @@
 <meta name="assert" content="HTML Elements in shadow trees: Form elements and form-associated elements in shadow tree are not accessible using document DOM object's tree accessors">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 //test form-associated elements
 test(function () {
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var form = d.createElement('form');
     form.setAttribute('id', 'form_id');
@@ -31,7 +31,7 @@
 
     var div = d.createElement('div');
     d.body.appendChild(div);
-    var s = div.createShadowRoot();
+    var s = div.attachShadow({mode: 'open'});
 
 
     HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
@@ -42,21 +42,21 @@
         s.appendChild(el);
 
         assert_equals(d.querySelector('#' + tagName + '_id'), null, 'Form-associated element ' + tagName +
-        	' in shadow tree must not be accessible using owner\'s document tree accessors');
+            ' in shadow tree must not be accessible using owner\'s document tree accessors');
     });
 }, 'A_08_02_01_T01');
 
 
 //test form elements
 test(function () {
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var form = d.createElement('form');
     d.body.appendChild(form);
 
     var div = d.createElement('div');
     form.appendChild(div);
-    s = div.createShadowRoot();
+    s = div.attachShadow({mode: 'open'});
 
     HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
 
@@ -65,7 +65,7 @@
         s.appendChild(el);
 
         assert_equals(d.querySelector('#' + tagName + '_id'), null, 'Form element ' + tagName +
-        	' in shadow tree must not be accessible using owner\'s document tree accessors');
+            ' in shadow tree must not be accessible using owner\'s document tree accessors');
     });
 }, 'A_08_02_01_T02');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html
index b6be18b..e833308 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html
@@ -16,14 +16,14 @@
 <meta name="assert" content="HTML Elements in shadow trees: Form elements and form-associated elements in shadow tree must be accessible using shadow tree accessors">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 //test form-associated elements
 test(function () {
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var form = d.createElement('form');
     form.setAttribute('id', 'form_id');
@@ -31,7 +31,7 @@
 
     var div = d.createElement('div');
     d.body.appendChild(div);
-    var s = div.createShadowRoot();
+    var s = div.attachShadow({mode: 'open'});
 
 
     HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
@@ -42,23 +42,23 @@
         s.appendChild(el);
 
         assert_true(s.querySelector('#' + tagName + '_id') != null, 'Form-associated element ' + tagName +
-        		' in shadow tree must be accessible shadow tree accessors');
+                ' in shadow tree must be accessible shadow tree accessors');
         assert_equals(s.querySelector('#' + tagName + '_id').getAttribute('id'), tagName + '_id',
-        	'Form-associated element ' + tagName + ' in shadow tree must be accessible shadow tree accessors');
+            'Form-associated element ' + tagName + ' in shadow tree must be accessible shadow tree accessors');
     });
 }, 'A_08_02_02_T01');
 
 
 //test form elements
 test(function () {
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     var form = d.createElement('form');
     d.body.appendChild(form);
 
     var div = d.createElement('div');
     form.appendChild(div);
-    var s = div.createShadowRoot();
+    var s = div.attachShadow({mode: 'open'});
 
     HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
 
@@ -67,16 +67,16 @@
         s.appendChild(el);
 
         assert_true(s.querySelector('#' + tagName + '_id') != null, 'Form-associated element ' + tagName +
-		' in shadow tree must be accessible shadow tree accessors');
+        ' in shadow tree must be accessible shadow tree accessors');
         assert_equals(s.querySelector('#' + tagName + '_id').getAttribute('id'), tagName + '_id',
-        	'Form element ' + tagName +	' in shadow tree must be accessible shadow tree accessors');
+            'Form element ' + tagName + ' in shadow tree must be accessible shadow tree accessors');
     });
 }, 'A_08_02_02_T02');
 
 
 //test distributed form elements
 test(function () {
-	var d = newHTMLDocument();
+    var d = newHTMLDocument();
 
     HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
 
@@ -88,13 +88,14 @@
 
         var el = d.createElement(tagName);
         el.setAttribute('id', tagName + '_id');
+        el.setAttribute('slot', tagName + '_slot');
         div.appendChild(el);
 
-        var s = div.createShadowRoot();
-    	s.innerHTML = '<content select="' + tagName + '"></content>';
+        var s = div.attachShadow({mode: 'open'});
+        s.innerHTML = '<slot name="' + tagName + '_slot"></slot>';
 
         assert_true(s.querySelector('#' + tagName + '_id') == null, 'Distributed form-associated element ' + tagName +
-		' in shadow tree must not be accessible shadow tree accessors');
+        ' in shadow tree must not be accessible shadow tree accessors');
     });
 }, 'A_08_02_02_T03');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html
index bc24838..2d437d2a 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html
@@ -12,47 +12,47 @@
 <head>
 <title>Shadow DOM Test: A_08_02_03</title>
 <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#inert-html-elements">
-<meta name="assert" content="HTML Elements in shadow trees: form should submit elements in shadow tree">
+<link rel="help" href="https://w3c.github.io/webcomponents/spec/shadow/#inertness-of-html-elements-in-a-shadow-tree">
+<meta name="assert" content="HTML Elements in shadow trees: form should not submit elements in shadow tree">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 var A_08_02_03_T01 = async_test('A_08_02_03_T01', { timeout: 5000 });
 
-A_08_02_03_T01.checkIframeContent = A_08_02_03_T01.step_func(function () {
-	//remember value to check before cleaning the context (it'll destroy the iframe)
-	var valueToCheck = A_08_02_03_T01.iframe.contentWindow.document.URL;
-	cleanContext(A_08_02_03_T01.ctx);
+var checkIframeContent = A_08_02_03_T01.step_func(function () {
+    // remember value to check before cleaning the context (it'll destroy the iframe)
+    var valueToCheck = A_08_02_03_T01.iframe.contentWindow.document.URL;
+    cleanContext(A_08_02_03_T01.ctx);
 
-	assert_true(valueToCheck.indexOf('inp1=value1') > 0,
-		'html form should submit all of its fields');
+    assert_true(valueToCheck.indexOf('inp1=value1') > 0,
+        'html form should submit all of its fields');
 
-	// Expected behavior is not quite clear. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=20320
-	assert_true(valueToCheck.indexOf('inp2=value2') > 0,
-		'html form should submit all of its fields including the shadow ones');
+    // Form data crossing shadow boundary should not be submitted.
+    // https://github.com/w3c/webcomponents/issues/65
+    assert_equals(valueToCheck.indexOf('inp2=value2'), -1,
+        'html form should not submit fields in the shadow tree');
 
-	A_08_02_03_T01.done();
+    A_08_02_03_T01.done();
 });
 
 
 A_08_02_03_T01.step(function () {
 
-	A_08_02_03_T01.ctx = newContext();
+    A_08_02_03_T01.ctx = newContext();
     var d = newRenderedHTMLDocument(A_08_02_03_T01.ctx);
 
     //create iframe
     var iframe = document.createElement('iframe');
+    A_08_02_03_T01.iframe = iframe;
 
     iframe.src = '../../resources/blank.html';
     iframe.setAttribute('name', 'targetIframe');
     d.body.appendChild(iframe);
 
-    A_08_02_03_T01.iframe = iframe;
-
     // create form
     var form = d.createElement('form');
     form.setAttribute('target', 'targetIframe');
@@ -60,11 +60,10 @@
     form.setAttribute('action', '../../resources/blank.html');
     d.body.appendChild(form);
 
-    //create Shadow root
+    // create shadow root
     var root = d.createElement('div');
     form.appendChild(root);
-    var s = root.createShadowRoot();
-
+    var s = root.attachShadow({mode: 'open'});
 
     var input1 = d.createElement('input');
     input1.setAttribute('type', 'text');
@@ -78,11 +77,11 @@
     input2.setAttribute('value', 'value2');
     s.appendChild(input2);
 
-    //submit the form
+    // submit the form
     form.submit();
 
     // set timeout to give the iframe time to load content
-    setTimeout('A_08_02_03_T01.checkIframeContent()', 2000);
+    setTimeout(checkIframeContent, 2000);
 });
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html
index 40df773..a087afc 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-001.html
@@ -16,7 +16,7 @@
 <meta name="assert" content="HTML Elements in shadow trees: base element must behave as inert, or not part of the document tree">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -24,20 +24,20 @@
 var A_08_01_01_T01 = async_test('A_08_01_01_T01', { timeout: 5000 });
 
 A_08_01_01_T01.checkIframeContent = A_08_01_01_T01.step_func(function () {
-	//remember value to check before cleaning the context (it'll destroy the iframe)
-	var valueToCheck = A_08_01_01_T01.iframe.contentWindow;
-	cleanContext(A_08_01_01_T01.ctx);
+    //remember value to check before cleaning the context (it'll destroy the iframe)
+    var valueToCheck = A_08_01_01_T01.iframe.contentWindow;
+    cleanContext(A_08_01_01_T01.ctx);
 
-	assert_equals(valueToCheck, null,
-		'base html element ih a shadow tree must beahve like inert one');
+    assert_equals(valueToCheck, null,
+        'base html element ih a shadow tree must beahve like inert one');
 
-	A_08_01_01_T01.done();
+    A_08_01_01_T01.done();
 });
 
 
 A_08_01_01_T01.step(function () {
 
-	A_08_01_01_T01.ctx = newContext();
+    A_08_01_01_T01.ctx = newContext();
     var d = newRenderedHTMLDocument(A_08_01_01_T01.ctx);
 
     //create iframe
@@ -58,7 +58,7 @@
     //create Shadow root
     var root = d.createElement('div');
     d.body.appendChild(root);
-    var s = root.createShadowRoot();
+    var s = root.attachShadow({mode: 'open'});
 
     // create base element, set iframe as a target
     var base = d.createElement('base');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html
index 6637bdbf..9f2609c 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/html-elements-in-shadow-trees/inert-html-elements/test-002.html
@@ -16,26 +16,27 @@
 <meta name="assert" content="HTML Elements in shadow trees: link element must behave as inert not as part of the document tree">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var link = d.createElement('link');
-	link.setAttribute('rel', 'stylesheet');
+    var link = d.createElement('link');
+    link.setAttribute('rel', 'stylesheet');
 
-	//create Shadow root
-	var root = d.createElement('div');
-	d.body.appendChild(root);
-	var s = root.createShadowRoot();
+    //create Shadow root
+    var root = d.createElement('div');
+    d.body.appendChild(root);
+    var s = root.attachShadow({mode: 'open'});
 
-	s.appendChild(link);
+    s.appendChild(link);
 
-	assert_equals(d.styleSheets.length, 0, 'link element must behave as inert not as part of the document tree');
+    assert_equals(d.styleSheets.length, 0, 'link element must behave as inert not as part of the document tree');
 
 
 }), 'A_08_01_02_T01');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/resources/bobs_page.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/resources/bobs_page.html
index c5b04eb1..92dfb0d3 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/resources/bobs_page.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/resources/bobs_page.html
@@ -2,34 +2,34 @@
 <head>
 </head>
 <body>
-	<ul class='stories'>
-	    <li id='li1'><a href='#1'>Link1</a></li>
-	    <li id='li2' title="li2"><a href='#2'>Link 2</a></li>
-	    <li id='li3' class='shadow'><a href='#3'>Link 3 Shadow</a></li>
-	    <li id='li4' class='shadow2'><a href='#4'>Link 4 Shadow 2</a></li>
-	    <li id='li5'><a id="a5" class="shadow" href='#5'>Link 5</a></li>
-		<li id='li6' class='shadow'><a href='#5'>Link 6 Shadow</a></li>
-	</ul>
-	<div id="divid" class='breaking'>
-		<span id='spandex'>Some text</span>
-		<ul id="ul2">
-		    <li id='li11'>Item 11</li>
-		    <li id='li12'>Item 12</li>
-		    <li id='li13' class='shadow'>Item 13 Shadow</li>
-		    <li id='li14' class='shadow2'>Item 14 Shadow 2</li>
-		    <li id='li15'>Item 15</li>
-			<li id='li16' class='shadow'>Item 16 Shadow</li>
-		</ul>
-	</div>
-	<div id="links-wrapper">
-		<a href='#10' id='link10'>Link 10</a>
-		<a href='#11' id='link11'>Link 11</a>
-	</div>
-	<div id="inputs-wrapper">
-		<input type='text' id='inp1' disabled/>
-		<input type='text' id='inp2'/>
-		<input type='checkbox' id='chb1' checked>
-		<input type='checkbox' id='chb2'>
-	</div>
+    <ul class='stories'>
+        <li id='li1'><a href='#1'>Link1</a></li>
+        <li id='li2' title="li2"><a href='#2'>Link 2</a></li>
+        <li id='li3' class='shadow'><a href='#3'>Link 3 Shadow</a></li>
+        <li id='li4' class='shadow2'><a href='#4'>Link 4 Shadow 2</a></li>
+        <li id='li5'><a id="a5" class="shadow" href='#5'>Link 5</a></li>
+        <li id='li6' class='shadow'><a href='#5'>Link 6 Shadow</a></li>
+    </ul>
+    <div id="divid" class='breaking'>
+        <span id='spandex'>Some text</span>
+        <ul id="ul2">
+            <li id='li11'>Item 11</li>
+            <li id='li12'>Item 12</li>
+            <li id='li13' class='shadow'>Item 13 Shadow</li>
+            <li id='li14' class='shadow2'>Item 14 Shadow 2</li>
+            <li id='li15'>Item 15</li>
+            <li id='li16' class='shadow'>Item 16 Shadow</li>
+        </ul>
+    </div>
+    <div id="links-wrapper">
+        <a href='#10' id='link10'>Link 10</a>
+        <a href='#11' id='link11'>Link 11</a>
+    </div>
+    <div id="inputs-wrapper">
+        <input type='text' id='inp1' disabled/>
+        <input type='text' id='inp2'/>
+        <input type='checkbox' id='chb1' checked>
+        <input type='checkbox' id='chb2'>
+    </div>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/composition/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/composition/test-001.html
deleted file mode 100644
index 5ffd1a0..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/composition/test-001.html
+++ /dev/null
@@ -1,163 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_07_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#multiple-shadow-subtrees">
-<meta name="assert" content="Composition:Composition algorithm">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-    var d = newRenderedHTMLDocument(ctx);
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-    	'<ul id="host">' +
-    		'<li id="li1" class="shadow">' +
-    			'<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
-    			'<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
-    			'<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
-    		'</li>' +
-    		'<li id="li2">' +
-    			'<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
-    		'</li>' +
-    		'<li id="li3" class="shadow">' +
-    			'<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
-    		'</li>' +
-    		'<li id="li4" class="shadow2">' +
-    			'<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
-    		'</li>' +
-    		'<li id="li5" class="shadow2">' +
-    			'<a id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
-    		'</li>' +
-    	'</ul>';
-
-    d.body.appendChild(div);
-
-    //make nested shadow tree to check the reprojection
-    var li1 = d.querySelector('#li1');
-    var s = li1.createShadowRoot();
-    var shadowLI1 = document.createElement('li');
-    shadowLI1.innerHTML = '<content select=".cl1"></content>';
-    s.appendChild(shadowLI1);
-
-    //Shadow root to play with
-    var ul = d.querySelector('#host');
-
-    //make an old shadow tree
-    var s2 = ul.createShadowRoot();
-    var div2 = d.createElement('div');
-    div2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
-    s2.appendChild(div2);
-
-    // At this point visible: li4 and li5
-    assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 1: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 2: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 3: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 4: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 5: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the nested tree
-	assert_equals(d.querySelector('#a11').offsetTop, 0,
-	    'Point 6: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a13').offsetTop, 0,
-		'Point 7: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 8: Aleady distributed nodes should behave like a shadow host child nodes');
-
-
-
-    //make a young shadow tree
-    var s3 = ul.createShadowRoot();
-    var div3 = d.createElement('div');
-    div3.innerHTML = '<ul><content select=".shadow"></content></ul>';
-    s3.appendChild(div3);
-
-    //At this point: li1 and li3 visible, others not
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 21: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 22: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 23: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 24: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 25: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (a11 and a13 visible, a12 not)
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 26: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 27: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 28: Aleady distributed nodes should behave like a shadow host child nodes');
-
-	var shadow = d.createElement('shadow');
-	s3.appendChild(shadow);
-
-    //At this point: li1, li3, li4 and li5 visible li2 not
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 31: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 32: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 33: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 34: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 35: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (a11 and a13 visible, a12 not)
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 36: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 37: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 38: Aleady distributed nodes should behave like a shadow host child nodes');
-
-	var shadow2 = d.createElement('shadow');
-	s3.appendChild(shadow2);
-
-	// Nothing should be changed
-    //At this point: li1, li3, li4 and li5 visible li2 not
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 41: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 42: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 43: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 44: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 45: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (a11 and a13 visible, a12 not)
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 46: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 47: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 48: Aleady distributed nodes should behave like a shadow host child nodes');
-}), 'A_04_07_01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html
deleted file mode 100644
index a5c5bc1c..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-001.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_04_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Tetsuharu OHZEKI" href="mailto:saneyuki.snyk@gmail.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#distributed-pseudo-element">
-<meta name="assert" content="Matching Children, Distributed To Insertion Points">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_04_01_T1 = async_test('A_04_04_01_T01');
-
-A_04_04_01_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_04_01_T1.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-
-            //make shadow tree
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-            var subdiv1 = d.createElement('div');
-            subdiv1.innerHTML = '<ul><content select="li"></content></ul>';
-            s.appendChild(subdiv1);
-
-            var shadowStyle = d.createElement('style');
-            shadowStyle.innerHTML = '*::content .shadow { display:none; }';
-            s.appendChild(shadowStyle);
-
-            //The order of DOM elements should be the following:
-            //li3, li6 - invisible. Other elements visible
-            var li3 = d.querySelector('#li3');
-            var li6 = d.querySelector('#li6');
-            assert_equals(window.getComputedStyle(li3).display, "none",
-              'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(window.getComputedStyle(li6).display, "none",
-              'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
-
-            var li1 = d.querySelector('#li1');
-            var li2 = d.querySelector('#li2');
-            var li4 = d.querySelector('#li4');
-            var li5 = d.querySelector('#li5');
-            assert_not_equals(window.getComputedStyle(li1).display, "none",
-              'Point 3: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
-            assert_not_equals(window.getComputedStyle(li2).display, "none",
-              'Point 4: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
-            assert_not_equals(window.getComputedStyle(li4).display, "none",
-              'Point 5: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
-            assert_not_equals(window.getComputedStyle(li5).display, "none",
-              'Point 6: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_04_01_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html
deleted file mode 100644
index 9d70672..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/content-pseudo-element/test-002.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_04_01</title>
-<link rel="author" title="Tetsuharu OHZEKI" href="mailto:saneyuki.snyk@gmail.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#distributed-pseudo-element">
-<meta name="assert" content="::content pseudo-element, Relative Selector">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_04_01_T2 = async_test('A_04_04_01_T02');
-
-A_04_04_01_T2.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_04_01_T2.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-
-            //make shadow tree
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-            var subdiv1 = d.createElement('div');
-            subdiv1.innerHTML = '<ul><content select="li"></content></ul>';
-            s.appendChild(subdiv1);
-
-            var shadowStyle = d.createElement('style');
-            shadowStyle.innerHTML = '*::content > .shadow { display:none; }';
-            s.appendChild(shadowStyle);
-
-            //The order of DOM elements should be the following:
-            //li3, li6 - invisible. Other elements visible
-            var li3 = d.querySelector('#li3');
-            var li6 = d.querySelector('#li6');
-            assert_equals(window.getComputedStyle(li3).display, "none",
-              'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(window.getComputedStyle(li6).display, "none",
-              'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
-
-            var a5 = d.querySelector('#a5');
-            assert_not_equals(window.getComputedStyle(a5).display, "none",
-              'Point 3: ::content pseudo-element with relative selector should be a valid insertion point matching criteria, element should be visible');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_04_01_T2.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html
deleted file mode 100644
index 5fff7dc..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/custom-pseudo-elements/test-001.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_10_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#custom-pseudo-elements">
-<meta name="assert" content="Custom Pseudo-Elements: test valid pseudo-element">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-// Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103973
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    var style = d.createElement('style');
-    style.innerHTML = 'span {' +
-    	'font-size: 10px;' +
-    	'}';
-    d.head.appendChild(style);
-
-    var widget = d.createElement('div');
-    d.body.appendChild(widget);
-
-    var s = widget.createShadowRoot();
-
-    var thumb = d.createElement('span');
-    thumb.innerHTML = 'This is a pseudo-element';
-    //FIXME test works if prefixed version of API used.
-    //In other words works if webkitPseudo property is used
-    //thumb.webkitPseudo = 'x-thumb';
-    thumb.pseudo = 'x-thumb';
-    s.appendChild(thumb);
-
-    var height = thumb.offsetHeight;
-
-    assert_true(height > 0, 'Element should be rendered');
-
-    style = d.createElement('style');
-    style.innerHTML = 'div::x-thumb {' +
-    	'font-size: 30px;' +
-    	'}';
-    d.body.appendChild(style);
-
-    assert_true(thumb.offsetHeight > height, 'Pseudo-element style should be applied');
-
-}), 'A_04_10_01_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-expected.html
deleted file mode 100644
index 4380e39..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: Distribution: Unordered list (Reference)</title>
-<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
-</head>
-<body>
-<p>
-You should see an unordered list below, consisting of ten elements
-each of which contains a capital letter ranging from "A" to "J",
-in alphabetical order.
-</p>
-<ul>
-<li>A</li>
-<li>B</li>
-<li>C</li>
-<li>D</li>
-<li>E</li>
-<li>F</li>
-<li>G</li>
-<li>H</li>
-<li>I</li>
-<li>J</li>
-</ul>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html
deleted file mode 100644
index 25a4c4a..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-001.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: Distribution: Unordered list</title>
-<link rel="match" href="distribution-001-ref.html">
-<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
-<meta name="assert" content="Lower-boundary Encapsulation: Each insertion point participates in distribution by providing a matching criteria for the child nodes. The matching criteria determines whether a given node could be distributed to a given insertion point.">
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<p>
-You should see an unordered list below, consisting of ten elements
-each of which contains a capital letter ranging from "A" to "J",
-in alphabetical order.
-</p>
-<ul id="list">
-<li>H</li>
-<li class="first">B</li>
-<li class="second">E</li>
-<li>I</li>
-<li class="first">C</li>
-</ul>
-<script>
-var shadowRoot = document.getElementById('list').createShadowRoot();
-shadowRoot.innerHTML =
-    '<li>A</li>' +
-    '<content select=".first"></content>' +
-    '<li>D</li>' +
-    '<content select=".second"></content>' +
-    '<li>F</li>' +
-    '<content select="img"></content>' +
-    '<li>G</li>' +
-    '<content></content>' +
-    '<li>J</li>';
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-expected.html
deleted file mode 100644
index 94fcb66..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002-expected.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: Distribution: Ordered list (Reference)</title>
-<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
-<style>
-ol {
-    list-style-type: decimal;
-}
-</style>
-</head>
-<body>
-<p>
-You should see an ordered list below, consisting of ten elements numbered
-from 1 through 10, and each line should contain a capital letter ranging from
-"A" to "J", in alphabetical order.
-</p>
-<ol>
-<li>A</li>
-<li>B</li>
-<li>C</li>
-<li>D</li>
-<li>E</li>
-<li>F</li>
-<li>G</li>
-<li>H</li>
-<li>I</li>
-<li>J</li>
-</ol>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html
deleted file mode 100644
index 91b6337..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-002.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: Distribution: Ordered list</title>
-<link rel="match" href="distribution-002-ref.html">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
-<meta name="assert" content="Lower-boundary Encapsulation: Each insertion point participates in distribution by providing a matching criteria for the child nodes. The matching criteria determines whether a given node could be distributed to a given insertion point.">
-<script src="../../testcommon.js"></script>
-<style>
-ol {
-    list-style-type: decimal;
-}
-</style>
-</head>
-<body>
-<p>
-You should see an ordered list below, consisting of ten elements numbered
-from 1 through 10, and each line should contain a capital letter ranging from
-"A" to "J", in alphabetical order.
-</p>
-<ol id="list">
-<li>H</li>
-<li class="first">B</li>
-<li class="second">E</li>
-<li>I</li>
-<li class="first">C</li>
-</ol>
-<script>
-var shadowRoot = document.getElementById('list').createShadowRoot();
-shadowRoot.innerHTML =
-    '<li>A</li>' +
-    '<content select=".first"></content>' +
-    '<li>D</li>' +
-    '<content select=".second"></content>' +
-    '<li>F</li>' +
-    '<content select="img"></content>' +
-    '<li>G</li>' +
-    '<content></content>' +
-    '<li>J</li>';
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html
deleted file mode 100644
index de0a6f2..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/distribution-003.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: Invariants after distribution</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
-<meta name="assert" content="Lower-boundary encapsulation: The distribution does not affect the state of the document tree or shadow trees">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var distributionTest = async_test(
-    'Distribution should not affect the state of the document trees and ' +
-    'the shadow trees.');
-
-distributionTest.step(function () {
-    var shadowHost = document.createElement('ul');
-    shadowHost.innerHTML =
-        '<li class="first">host 1</li>' +
-        '<li class="second">host 2</li>';
-    shadowHost.style.visibility = 'hidden';
-    document.body.appendChild(shadowHost);
-    var host1 = shadowHost.querySelector('.first');
-    var host2 = shadowHost.querySelector('.second');
-
-    var shadowRoot = shadowHost.createShadowRoot();
-    shadowRoot.innerHTML =
-        '<li class="first">shadow 1</li>' +
-        '<content select=".second"></content>' +
-        '<li class="second">shadow 2</li>';
-    var shadow1 = shadowRoot.querySelector('.first');
-    var shadow2 = shadowRoot.querySelector('.second');
-    var content = shadowRoot.querySelector('content');
-
-    // Let the rendering happen.
-    window.setTimeout(distributionTest.step_func(function () {
-        assert_equals(host1.textContent, 'host 1');
-        assert_equals(host2.textContent, 'host 2');
-        assert_equals(shadow1.textContent, 'shadow 1');
-        assert_equals(shadow2.textContent, 'shadow 2');
-        assert_equals(content.textContent, '');
-
-        assert_equals(shadowHost.children.length, 2);
-        assert_equals(shadowHost.children[0], host1);
-        assert_equals(shadowHost.children[1], host2);
-        assert_equals(shadowRoot.children.length, 3);
-        assert_equals(shadowRoot.children[0], shadow1);
-        assert_equals(shadowRoot.children[1], content);
-        assert_equals(shadowRoot.children[2], shadow2);
-
-        assert_equals(host1.tagName, 'LI');
-        assert_equals(shadow1.tagName, 'LI');
-        assert_equals(content.tagName, 'CONTENT');
-
-        document.body.removeChild(shadowHost);
-        distributionTest.done();
-    }), 0);
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html
deleted file mode 100644
index d6ac365..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-003.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_02_03</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
-<meta name="assert" content="Lower-boundary encapsulation: The distribution is a result of executing a stable algorithm">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_02_03_T1 = async_test('A_04_02_03_T01');
-
-A_04_02_03_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_02_03_T1.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-            subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
-            s.appendChild(subdiv1);
-
-            //The order of <li> elements at this point should be the following:
-            //li3, li6, li11, li12, 1i13, li14, li15. Other elements (li1, li2, li4, li5) invisible
-            assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
-                'Point 1: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li11').offsetTop,
-                'Point 2: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
-                'Point 3: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
-                'Point 4: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
-                'Point 5: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
-                'Point 6: Elements that mach insertion point criteria don\'t participate in distribution');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 7: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 8: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li4').offsetTop, 0,
-                'Point 9: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 10: Elements that don\'t mach insertion point criteria participate in distribution');
-
-            var subdiv2 = document.createElement('div');
-            subdiv2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
-            s.appendChild(subdiv2);
-
-            // When class name changed distribution must reoccur
-            //The order of <li> elements should now be the following:
-            //li3, li6, li4, li11, li12, 1i13, li14, li15. Invisible: li1, li2, li5
-            assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
-                'Point 11: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li4').offsetTop,
-                'Point 12: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li4').offsetTop < d.querySelector('#li11').offsetTop,
-                'Point 13: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
-                'Point 14: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
-                'Point 15: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
-                'Point 16: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
-                'Point 17: Elements that mach insertion point criteria don\'t participate in distribution');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 18: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 19: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 20: Elements that don\'t mach insertion point criteria participate in distribution');
-
-            var subdiv3 = document.createElement('div');
-            subdiv3.innerHTML = '<ul><content select=".shadow"></content></ul>';
-            s.appendChild(subdiv3);
-
-            //There should be no change. Order:
-            //li3, li6, li4, li11, li12, 1i13, li14, li15. Invisible: li1, li2, li5
-            assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
-                'Point 21: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li4').offsetTop,
-                'Point 22: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li4').offsetTop < d.querySelector('#li11').offsetTop,
-                'Point 23: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
-                'Point 24: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
-                'Point 25: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
-                'Point 26: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
-                'Point 27: Elements that mach insertion point criteria don\'t participate in distribution');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 28: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 29: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 30: Elements that don\'t mach insertion point criteria participate in distribution');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_02_03_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html
deleted file mode 100644
index 19072ce67..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-004.html
+++ /dev/null
@@ -1,102 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_02_04</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
-<meta name="assert" content="Lower-boundary encapsulation: The distribution reoccurs whenever any variable affecting it is changed">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_02_04_T1 = async_test('A_04_02_04_T01');
-
-A_04_02_04_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_02_04_T1.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-            subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
-            s.appendChild(subdiv1);
-
-
-            //The order of <li> elements at this point should be the following:
-            //li3, li6, li11, li12, 1i13, li14, li15. Other elements (li1, li2, li4, li5) invisible
-            assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
-                'Point 1: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li11').offsetTop,
-                'Point 2: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
-                'Point 3: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
-                'Point 4: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
-                'Point 5: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
-                'Point 6: Elements that mach insertion point criteria don\'t participate in distribution');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 7: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 8: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li4').offsetTop, 0,
-                'Point 9: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 10: Elements that don\'t mach insertion point criteria participate in distribution');
-
-            var li5 = d.querySelector('#li5');
-            li5.className = 'shadow';
-
-            // When class name changed distribution must reoccur
-            //The order of <li> elements should now be the following:
-            //li3, li6, li5, li11, li12, 1i13, li14, li15. Invisible: li1, li2, li4
-            assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
-                'Point 11: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li5').offsetTop,
-                'Point 12: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li5').offsetTop < d.querySelector('#li11').offsetTop,
-                'Point 13: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
-                'Point 14: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
-                'Point 15: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
-                'Point 16: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
-                'Point 17: Elements that mach insertion point criteria don\'t participate in distribution');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 18: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 19: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li4').offsetTop, 0,
-                'Point 20: Elements that don\'t mach insertion point criteria participate in distribution');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_02_04_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html
deleted file mode 100644
index 7f916e5..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/lower-boundary-encapsulation/test-005.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_02_05</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
-<meta name="assert" content="Lower-boundary encapsulation: An insertion point may be active or inactive. An active insertion point participates in the distribution process, whereas the inactive insertion does not">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_02_05_T1 = async_test('A_04_02_05_T01');
-
-A_04_02_05_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_02_05_T1.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector("ul.stories");
-            var s = ul.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-            subdiv1.innerHTML = "<ul><content select='.nobody'><span id='shadowspan'>Inactive insertion point</span></content></ul>";
-            s.appendChild(subdiv1);
-
-            assert_true(s.querySelector('#shadowspan').offsetTop > 0,
-                'Inactive insertion point should be in a fallback content');
-
-            // All li1-li6 should be invisible, shadowspan visible
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li3').offsetTop, 0,
-                'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li4').offsetTop, 0,
-                'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li6').offsetTop, 0,
-                'Point 6: Elements that don\'t mach insertion point criteria participate in distribution');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_02_05_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-expected.html
index f4b8bab..3050cefe 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-expected.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest-expected.html
@@ -4,7 +4,7 @@
     <meta charset="utf-8" >
     <title>Shadow DOM Test Ref file - Tests nested shadow tree.</title>
     <link rel="author" title="shingo.miyazawa" href="mailto:kumatronik@gmail.com" >
-    <script src="../../testcommon.js"></script>
+    <script src="../../../../html/resources/common.js"></script>
     <meta name="assert" content="nested shadow tree style is valid." >
     <style>
       #host {
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html
index 679b70f0..8d02227 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/nested_tree_reftest.html
@@ -6,7 +6,7 @@
     <link rel="match" href="nested_tree_reftest-ref.html" >
     <link rel="author" title="shingo.miyazawa" href="mailto:kumatronik@gmail.com" >
     <link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#nested-shadow-trees" >
-    <script src="../../testcommon.js"></script>
+    <script src="../../../../html/resources/common.js"></script>
     <meta name="assert" content="nested shadow tree style is valid." >
     <style>
       #host {
@@ -21,9 +21,9 @@
     <div id='host'>
     </div>
     <script>
-      var shadowRoot = document.getElementById('host').createShadowRoot();
+      var shadowRoot = document.getElementById('host').attachShadow({mode: 'open'});
       shadowRoot.innerHTML = '<div id="sub" style="width: 100%;height:100%;"></div>';
-      var nestedRoot = shadowRoot.getElementById('sub').createShadowRoot();
+      var nestedRoot = shadowRoot.getElementById('sub').attachShadow({mode: 'open'});
       nestedRoot.innerHTML = '<div style="width:100%; height:100%;background-color: green;"></div>';
     </script>
   </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/test-001.html
deleted file mode 100644
index 6e619f8..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/nested-shadow-trees/test-001.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_08_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#nested-shadow-subtrees">
-<meta name="assert" content="Nested Shadow Subtrees:Any element in a shadow tree can be a shadow host, thus producing nested shadow trees">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_08_01_T1 = async_test('A_04_08_01_T01');
-
-A_04_08_01_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_08_01_T1.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector('ul.stories');
-
-            //make a shadow subtree
-            var s1 = ul.createShadowRoot();
-            var subdiv1 = d.createElement('div');
-            subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>' +
-            	'<div id="host_div">' +
-            		'<span id="sh_span">This span should be visible</span>' +
-            		'<ul id="host">' +
-	            		'<li id="sh_li1">Shadow li 1</li>' +
-	            		'<li id="sh_li2">Shadow li 2</li>' +
-	            		'<li id="sh_li3" class="shadow2">Shadow li 3</li>' +
-	            		'<li id="sh_li4">Shadow li 4</li>' +
-	            		'<li id="sh_li5">Shadow li 5</li>' +
-            		'</ul>' +
-            	'</div>';
-            s1.appendChild(subdiv1);
-
-            //make nested shadow subtree
-            var sh_ul = s1.querySelector('#host');
-            var s2 = sh_ul.createShadowRoot();
-            var subdiv2 = d.createElement('div');
-            subdiv2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
-            s2.appendChild(subdiv2);
-
-            //The order of DOM elements should be the following:
-            //li4, li3 and sh_li3 visible. Other elements invisible
-            assert_true(d.querySelector('#li3').offsetTop > 0,
-            	'Point 1: Shadow tree should take part in the distribution');
-            assert_true(d.querySelector('#li6').offsetTop > d.querySelector('#li3').offsetTop,
-            	'Point 2: Shadow tree should take part in the distribution');
-            assert_true(s1.querySelector('#sh_li3').offsetTop > 0,
-            	'Nested shadow subtree should take part in the distribution');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li4').offsetTop, 0,
-                'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-            	'Point 6: Elements that don\'t mach insertion point criteria participate in distribution');
-
-            assert_equals(s1.querySelector('#sh_li1').offsetTop, 0,
-            	'Point 7: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(s1.querySelector('#sh_li2').offsetTop, 0,
-            	'Point 8: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(s1.querySelector('#sh_li4').offsetTop, 0,
-        		'Point 9: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(s1.querySelector('#sh_li5').offsetTop, 0,
-        		'Point 10: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
-
-            assert_true(s1.querySelector('#sh_span').offsetTop > 0,
-            	'Shadow subtree elements that are not shadow host should take part in the distribution');
-
-
-        } finally {
-        	iframe.parentNode.removeChild(iframe);
-        }
-        A_04_08_01_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/rendering-shadow-trees/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/rendering-shadow-trees/test-001.html
deleted file mode 100644
index c8c8656..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/rendering-shadow-trees/test-001.html
+++ /dev/null
@@ -1,255 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_09_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#multiple-shadow-subtrees">
-<meta name="assert" content="Rendering Shadow DOM Subtrees:rendering algorithm">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-    var div = d.createElement('div');
-    div.innerHTML = '' +
-    	'<ul id="host">' +
-    		'<li id="li1" class="shadow">' +
-    			'<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
-    			'<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
-    			'<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
-    			'<a id="a14" class="cl3" href="#">Link14 Shadow</a>' +
-    		'</li>' +
-    		'<li id="li2">' +
-    			'<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
-    		'</li>' +
-    		'<li id="li3" class="shadow">' +
-    			'<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
-    		'</li>' +
-    		'<li id="li4" class="shadow2">' +
-    			'<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
-    		'</li>' +
-    		'<li id="li5" class="shadow2">' +
-    			'<a id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
-    		'</li>' +
-    	'</ul>';
-
-    d.body.appendChild(div);
-
-    //make nested shadow tree to check the reprojection
-    var li1 = d.querySelector('#li1');
-    var s = li1.createShadowRoot();
-    var shadowLI1 = document.createElement('li');
-    shadowLI1.innerHTML = '<content select=".cl1"></content>';
-    s.appendChild(shadowLI1);
-
-	//check the tree. a11 and a13 should be visible
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 1: Node that matches insertion point criteria should be rendered');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 2: Node that matches insertion point criteria should be rendered');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 3: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#a14').offsetTop, 0,
-		'Point 4: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
-
-
-    var shadowLI2 = document.createElement('li');
-    shadowLI2.innerHTML = '<content select=".cl3"></content>';
-    s.appendChild(shadowLI2);
-
-	//At this point a11, a13 and a14 should be visible
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 11: Node that matches insertion point criteria should be rendered');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 12: Node that matches insertion point criteria should be rendered');
-	assert_true(d.querySelector('#a14').offsetTop > d.querySelector('#a13').offsetTop,
-		'Point 13: Node that matches insertion point criteria should be rendered');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 14: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
-
-
-    //Shadow root to play with
-    var ul = d.querySelector('#host');
-
-    //make an old shadow tree
-    var s2 = ul.createShadowRoot();
-    var div2 = d.createElement('div');
-    div2.innerHTML = '<ul><content select=".shadow"></content></ul>';
-    s2.appendChild(div2);
-
-    // At this point visible: li1 and li3
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 21: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 22: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 23: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 24: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 25: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 26: Node that matches insertion point criteria should be rendered');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 27: Node that matches insertion point criteria should be rendered');
-	assert_true(d.querySelector('#a14').offsetTop > d.querySelector('#a13').offsetTop,
-		'Point 28: Node that matches insertion point criteria should be rendered');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 29: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
-
-
-
-    //make a young shadow tree
-    var s3 = ul.createShadowRoot();
-    var div3 = d.createElement('div');
-    div3.innerHTML = '<ul><content select=".shadow2"></content></ul>';
-    s3.appendChild(div3);
-
-    //At this point: li4 and li5 visible, others not
-    assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 31: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 32: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 33: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 34: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 35: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (all invisible)
-	assert_equals(d.querySelector('#a11').offsetTop, 0,
-	    'Point 36: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 37: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a13').offsetTop, 0,
-		'Point 38: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a14').offsetTop, 0,
-		'Point 39: Aleady distributed nodes should behave like a shadow host child nodes');
-
-	var shadow = d.createElement('shadow');
-	s3.appendChild(shadow);
-
-    //At this point: li1, li3, li4 and li5 visible li2 not
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 41: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 42: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 43: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 44: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 45: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (a11, a13, a14 visible, a12 not)
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 46: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 47: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 48: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a14').offsetTop > 0,
-		'Point 49: Aleady distributed nodes should behave like a shadow host child nodes');
-
-	var shadow2 = d.createElement('shadow');
-	s3.appendChild(shadow2);
-
-	// Nothing should be changed
-    //At this point: li1, li3, li4 and li5 visible li2 not
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 51: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 52: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 53: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 54: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 55: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (a11 and a13 visible, a12 not)
-	assert_true(d.querySelector('#a11').offsetTop > 0,
-	    'Point 56: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a12').offsetTop, 0,
-		'Point 57: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a13').offsetTop > 0,
-		'Point 58: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a14').offsetTop > 0,
-		'Point 59: Aleady distributed nodes should behave like a shadow host child nodes');
-
-	//replace the nested tree by younger one
-    var s4 = li1.createShadowRoot();
-    var shadowLI4 = document.createElement('li');
-    shadowLI4.innerHTML = '<content select=".cl2"></content>';
-    s4.appendChild(shadowLI4);
-
-    //At this point: li1, li3, li4 and li5 visible li2 not
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 61: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 62: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 63: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 64: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 65: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (a12 visible, others not)
-	assert_equals(d.querySelector('#a11').offsetTop, 0,
-	    'Point 66: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a12').offsetTop > 0,
-		'Point 67: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a13').offsetTop, 0,
-		'Point 68: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a14').offsetTop, 0,
-		'Point 69: Aleady distributed nodes should behave like a shadow host child nodes');
-
-
-	//Let's check that if we add a shadow insertion point to the tree nothing is
-	//changed in the nested three (old tree is still invisible)
-	var shadow3 = d.createElement('shadow');
-	s3.appendChild(shadow3);
-
-    //At this point: li1, li3, li4 and li5 visible li2 not
-    assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 61: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 62: Node that match insertion ' +
-		'point criteria should be rendered');
-	assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 63: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 64: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 65: Node that doen\'t match ' +
-		'insertion point criteria shouldn\'t be rendered');
-
-	//check the reprojected nodes (a12 visible, others not)
-	assert_equals(d.querySelector('#a11').offsetTop, 0,
-	    'Point 66: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_true(d.querySelector('#a12').offsetTop > 0,
-		'Point 67: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a13').offsetTop, 0,
-		'Point 68: Aleady distributed nodes should behave like a shadow host child nodes');
-	assert_equals(d.querySelector('#a14').offsetTop, 0,
-		'Point 69: Aleady distributed nodes should behave like a shadow host child nodes');
-}), 'A_04_09_01_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html
index 4744768a..53cee0d0 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html
@@ -17,7 +17,7 @@
 <link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
 <link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#reprojection">
 <meta name="assert" content="a node is distributed into more than one insertion point.">
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 <style>
 .pass { color: green; }
 </style>
@@ -29,11 +29,11 @@
   <div class="pass">Orange.</div>
 </div>
 <script>
-  var shadowRoot = host.createShadowRoot(host);
-  shadowRoot.innerHTML = '<div id="host2">Hello a Shadow Root.<content></content><div>Banana.</div></div>';
+  var shadowRoot = host.attachShadow({mode: 'open'});
+  shadowRoot.innerHTML = '<div id="host2">Hello a Shadow Root.<slot></slot><div>Banana.</div></div>';
   var host2 = shadowRoot.getElementById("host2");
-  var shadowRoot2 = host2.createShadowRoot(host2);
-  shadowRoot2.innerHTML = '<div>Hello a Shadow Root2.</div><div><content></content></div>';
+  var shadowRoot2 = host2.attachShadow({mode: 'open'});
+  shadowRoot2.innerHTML = '<div>Hello a Shadow Root2.</div><div><slot></slot></div>';
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-expected.html
deleted file mode 100644
index 9f4b04e9..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002-expected.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<meta charset="utf-8">
-<title>Shadow DOM Test: Basic reprojection with a select attribute (reference)</title>
-<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
-<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
-<style>
-.pass { color: green; }
-</style>
-</head>
-<body>
-<p>You should see green text saying "Apple" below.</p>
-<div id="host">
-  <div>Hello a Shadow Root2.</div>
-  <div>
-    <div class="pass">Apple.</div>
-  </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html
deleted file mode 100644
index d38ee98c..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-002.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<!DOCTYPE html>
-<head>
-<meta charset="utf-8">
-<title>Shadow DOM Test - Tests a reprojection with a select attribute.</title>
-<link rel="match" href="reprojection-002-ref.html">
-<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
-<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#reprojection">
-<meta name="assert" content="A node is distributed into more than one insertion point with a select attribute.">
-<script src="../../testcommon.js"></script>
-<style>
-.pass { color: green; }
-.fail { color: red; }
-</style>
-</head>
-<body>
-<p>You should see green text saying "Apple" below.</p>
-<div id="host">
-  <div class="A pass">Apple.</div>
-  <div class="B fail">Orange.</div>
-</div>
-<script>
-  var shadowRoot = host.createShadowRoot();
-  shadowRoot.innerHTML = '<div id="host2">Hello a Shadow Root.<content></content><div class="fail">Banana.</div></div>';
-  var host2 = shadowRoot.getElementById("host2");
-  var shadowRoot2 = host2.createShadowRoot();
-  shadowRoot2.innerHTML = '<div>Hello a Shadow Root2.</div><div><content select=".A"></content></div>';
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/test-001.html
deleted file mode 100644
index 9278b42..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/reprojection/test-001.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_06_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#reprojection">
-<meta name="assert" content="Reprojection: The nodes distributed into that insertion point must appear as if they were child nodes of the shadow host in the context of distribution within the shadow DOM subtree, hosted by said shadow host">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_06_01_T01 = async_test('A_04_06_01_T01');
-
-A_04_06_01_T01.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/blank.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_06_01_T01.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-
-            var div = d.createElement('div');
-            div.innerHTML = '' +
-            	'<ul id="host">' +
-            		'<li id="li1" class="shadow">' +
-            			'<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
-            			'<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
-            			'<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
-            		'</li>' +
-            		'<li id="li2">' +
-	        			'<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
-	        		'</li>' +
-            		'<li id="li3" class="shadow">' +
-	        			'<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
-	        		'</li>' +
-            		'<li id="li4" class="shadow2">' +
-	        			'<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
-	        		'</li>' +
-            		'<li id="li5" class="shadow2">' +
-	        			'<a id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
-	        		'</li>' +
-            	'</ul>';
-
-            d.body.appendChild(div);
-
-            var li1 = d.querySelector('#li1');
-            var s = li1.createShadowRoot();
-            //make shadow subtree
-            var shadowLI1 = document.createElement('li');
-            shadowLI1.innerHTML = '<li><content select=".cl1"></content></li>';
-            s.appendChild(shadowLI1);
-
-            var ul = d.querySelector('#host');
-            var s2 = ul.createShadowRoot();
-            var div2 = document.createElement('div');
-            div2.innerHTML = '<ul><content select=".shadow"></content></ul>';
-            s2.appendChild(div2);
-
-
-            assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 1: Node that match insertion ' +
-            	'point criteria should be rendered');
-            assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 2: Node that match insertion ' +
-            	'point criteria should be rendered');
-            assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 3: Node that doen\'t match ' +
-            	'insertion point criteria shouldn\'t be rendered');
-            assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Node that doen\'t match ' +
-            	'insertion point criteria shouldn\'t be rendered');
-            assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Node that doen\'t match ' +
-            	'insertion point criteria shouldn\'t be rendered');
-
-            //check the nested tree
-            assert_true(d.querySelector('#a11').offsetTop > 0,
-                'Point 6: Aleady distributed nodes should behave like a shadow host child nodes');
-            assert_true(d.querySelector('#a13').offsetTop > 0,
-            	'Point 7: Aleady distributed nodes should behave like a shadow host child nodes');
-            assert_equals(d.querySelector('#a12').offsetTop, 0,
-            	'Point 8: Aleady distributed nodes should behave like a shadow host child nodes');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_06_01_T01.done();
-    });
-});
-
-
-
-var A_04_06_01_T02 = async_test('A_04_06_01_T02');
-
-A_04_06_01_T02.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/blank.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_06_01_T02.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-
-            var div = d.createElement('div');
-            div.innerHTML = '' +
-            	'<ul id="host">' +
-            		'<li id="li1" class="shadow">' +
-            			'<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
-            			'<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
-            			'<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
-            		'</li>' +
-            		'<li id="li2">' +
-	        			'<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
-	        		'</li>' +
-            		'<li id="li3" class="shadow">' +
-	        			'<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
-	        		'</li>' +
-            		'<li id="li4" class="shadow2">' +
-	        			'<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
-	        		'</li>' +
-            		'<li id="li5" class="shadow2">' +
-	        			'<a class="cl1" id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
-	        		'</li>' +
-            	'</ul>';
-
-            d.body.appendChild(div);
-
-            var li1 = d.querySelector('#li1');
-            var s = li1.createShadowRoot();
-            //make shadow subtree
-            var shadowLI1 = document.createElement('li');
-            shadowLI1.innerHTML = '<li><content select=".cl1"></content></li>';
-            s.appendChild(shadowLI1);
-
-            var ul = d.querySelector('#host');
-            var s2 = ul.createShadowRoot();
-            var div2 = document.createElement('div');
-            div2.innerHTML = '<li><content select=".cl1"></content></li>';
-            s2.appendChild(div2);
-
-            // The second distribution shouldn't render anything
-            assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Node that doen\'t match ' +
-                'insertion point criteria shouldn\'t be rendered');
-            assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Node that doen\'t match ' +
-                'insertion point criteria shouldn\'t be rendered');
-            assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Node that doen\'t match ' +
-            	'insertion point criteria shouldn\'t be rendered');
-            assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Node that doen\'t match ' +
-            	'insertion point criteria shouldn\'t be rendered');
-            assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Node that doen\'t match ' +
-            	'insertion point criteria shouldn\'t be rendered');
-
-            //check the nested tree
-            assert_equals(d.querySelector('#a11').offsetTop, 0,
-                'Point 6: Aleady distributed nodes should behave like a shadow host child nodes');
-            assert_equals(d.querySelector('#a13').offsetTop,  0,
-            	'Point 7: Aleady distributed nodes should behave like a shadow host child nodes');
-            assert_equals(d.querySelector('#a12').offsetTop, 0,
-            	'Point 8: Aleady distributed nodes should behave like a shadow host child nodes');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_06_01_T02.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html
deleted file mode 100644
index 251b08c..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-001.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_03_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
-<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a type selector">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_03_01_T1 = async_test('A_04_03_01_T01');
-
-
-A_04_03_01_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_03_01_T1.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var div = d.querySelector('#divid');
-            var s = div.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-            subdiv1.innerHTML = '<content select="span"></content>';
-            s.appendChild(subdiv1);
-
-            //The order of DOM elements should be the following:
-            // <ul class='stories'>, <span>. Invisible: <ul id="ul2">
-
-            assert_true(d.querySelector('ul.stories').offsetTop < d.querySelector('#spandex').offsetTop,
-                'A valid selector fragment may contain \'span\' type selector');
-
-            assert_equals(d.querySelector('#ul2').offsetTop, 0,
-                '<ul> element shouldn\'t match "span" type selector');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_03_01_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html
deleted file mode 100644
index 41b9735..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-002.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_03_02</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
-<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain an universal selector">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_03_02_T1 = async_test('A_04_03_02_T01');
-
-
-A_04_03_02_T1.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_03_02_T1.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-
-            // TODO add tests for namespace universal selector ns|*
-            subdiv1.innerHTML = '<ul><content select="*"></content></ul>';
-            s.appendChild(subdiv1);
-
-            //The order of DOM elements should be the following:
-            // li1-li6 should be visible and located on-order
-            assert_true(d.querySelector('#li1').offsetTop < d.querySelector('#li2').offsetTop,
-                'Point 1: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li2').offsetTop < d.querySelector('#li3').offsetTop,
-                'Point 2: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li4').offsetTop,
-                'Point 3: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li4').offsetTop < d.querySelector('#li5').offsetTop,
-                'Point 4: Elements that mach insertion point criteria don\'t participate in distribution');
-            assert_true(d.querySelector('#li5').offsetTop < d.querySelector('#li6').offsetTop,
-                'Point 5: Elements that mach insertion point criteria don\'t participate in distribution');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_03_02_T1.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html
deleted file mode 100644
index 3995b81..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-003.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_03_03</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
-<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a class selector">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_03_03_T01 = async_test('A_04_03_03_T01');
-
-
-A_04_03_03_T01.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_03_03_T01.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-            subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
-            s.appendChild(subdiv1);
-
-            //The order of DOM elements should be the following:
-            //li3, li6. Other elements invisible
-            assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
-                'Class name should be a valid insertion point matching criteria');
-            assert_true(d.querySelector('#li3').offsetTop > 0,
-                'Class name should be a valid insertion point matching criteria, element should be visible');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li4').offsetTop, 0,
-                'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_03_03_T01.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html
deleted file mode 100644
index 8a7ef2d5..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-004.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_03_04</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
-<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain an ID selector">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_03_04_T01 = async_test('A_04_03_04_T01');
-
-A_04_03_04_T01.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_03_04_T01.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-            subdiv1.innerHTML = '<ul><content select="#li4"></content></ul>';
-            s.appendChild(subdiv1);
-
-            //The order of DOM elements should be the following:
-            //li4. Other elements invisible
-            assert_true(d.querySelector('#li4').offsetTop > 0,
-                'Class name should be a valid insertion point matching criteria, element should be visible');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li2').offsetTop, 0,
-                'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li3').offsetTop, 0,
-                'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li6').offsetTop, 0,
-                'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_03_04_T01.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html
deleted file mode 100644
index f1a9834f..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/satisfying-matching-criteria/test-005.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_04_03_05</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
-<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain an attribute selector">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-var A_04_03_05_T01 = async_test('A_04_03_05_T01');
-
-A_04_03_05_T01.step(function () {
-    var iframe = document.createElement('iframe');
-    iframe.src = '../../resources/bobs_page.html';
-    document.body.appendChild(iframe);
-
-    iframe.onload = A_04_03_05_T01.step_func(function () {
-        try {
-            var d = iframe.contentDocument;
-            var ul = d.querySelector('ul.stories');
-            var s = ul.createShadowRoot();
-
-            //make shadow subtree
-            var subdiv1 = document.createElement('div');
-            subdiv1.innerHTML = '<ul><content select="li[title]"></content></ul>';
-            s.appendChild(subdiv1);
-
-            //The order of DOM elements should be the following:
-            //li2. Other elements invisible
-            assert_true(d.querySelector('#li2').offsetTop > 0,
-                'Attribute should be a valid insertion point matching criteria, element should be visible');
-
-            assert_equals(d.querySelector('#li1').offsetTop, 0,
-                'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li3').offsetTop, 0,
-                'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li4').offsetTop, 0,
-                'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li5').offsetTop, 0,
-                'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
-            assert_equals(d.querySelector('#li6').offsetTop, 0,
-                'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
-        } finally {
-            iframe.parentNode.removeChild(iframe);
-        }
-        A_04_03_05_T01.done();
-    });
-});
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html
index 90432ae..b93392bc 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-001.html
@@ -16,7 +16,7 @@
 <link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
 <link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
 <meta name="assert" content="When a shadow root is attached, the shadow tree is rendered.">
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
 <style>
 p { color: black; }
 * { color: red; }
@@ -26,7 +26,7 @@
 <p>You should see green text saying "PASS" below.</p>
 <div id="host">FAIL</div>
 <script>
-var shadowRoot = window.host.createShadowRoot();
+var shadowRoot = window.host.attachShadow({mode: 'open'});
 shadowRoot.innerHTML =
     '<style>#pass { color: green; }</style>\n' +
     '<div id="pass">PASS</div>';
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-002.html
index 97201bea..cce4195 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/shadow-root-002.html
@@ -17,7 +17,7 @@
 <link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
 <link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
 <meta name="assert" content="On distribution, content element is replaced with the shadow host's children.">
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
 <style>
 p { color: black; }
 .pass { color: green; }
@@ -34,7 +34,7 @@
 <div class="pass">C</div>
 </div>
 <script>
-var shadowRoot = window.host.createShadowRoot();
+var shadowRoot = window.host.attachShadow({mode: 'open'});
 
 shadowRoot.innerHTML =
     '<style>\n' +
@@ -42,7 +42,7 @@
     '* { color: red; }\n' +
     '</style>' +
     '<div class="shadow-pass">A</div>\n' +
-    '<content>FAIL</content>' +
+    '<slot>FAIL</slot>' +
     '<div class="shadow-pass">D</div>';
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001-expected.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001-expected.html
index db3eede..8c10d25 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001-expected.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001-expected.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
-	<head>
-		<meta charset="utf-8">
-		<title>Shadow DOM Test</title>
-		<link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
-	</head>
-	<body>
-		<span>
-			if NOT underlined, it is success.
-		</span>
-	</body>
+    <head>
+        <meta charset="utf-8">
+        <title>Shadow DOM Test</title>
+        <link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+    </head>
+    <body>
+        <span>
+            if NOT underlined, it is success.
+        </span>
+    </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001.html
index 47d5efda..d8def126 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/text-decoration-001.html
@@ -13,7 +13,7 @@
         </span>
         <script>
             var parent = document.getElementById('parent');
-            var shadow = parent.createShadowRoot();
+            var shadow = parent.attachShadow({mode: 'open'});
             var child = document.createElement('span');
             child.textContent = "if NOT underlined, it is success.";
             shadow.appendChild(child);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html
index f923323..8963cee 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html
@@ -19,7 +19,7 @@
 <meta name="assert" content="Upper-boundary encapsulation: The shadow nodes and named shadow elements are not accessible using shadow host's document DOM tree accessors.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -66,7 +66,6 @@
     '<embed></embed>',
     '<form></form>',
     '<script><' + '/script>',
-    '<applet></applet>',
     '</body>'
 ].join('\n');
 
@@ -91,7 +90,7 @@
 function createDocumentForTesting() {
     var doc = document.implementation.createHTMLDocument('');
     populateTestContentToHostDocument(doc);
-    var shadowRoot = doc.documentElement.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     populateTestContentToShadowRoot(shadowRoot);
     return doc;
 }
@@ -121,13 +120,17 @@
 test(function () {
     var doc = document.implementation.createHTMLDocument('');
     populateTestContentToHostDocument(doc);
-    var shadowRoot = doc.documentElement.createShadowRoot();
+
+    // Note: this test is originally written to replace document.documentElement
+    // with shadow contents, but among Shadow DOM V1 allowed elements body is the
+    // most approximate to it, though some test may make lesser sense.
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     populateTestContentToShadowRoot(shadowRoot);
 
     // Replace the content of <title> to distinguish elements in a host
     // document and a shadow tree.
     doc.getElementsByTagName('title')[0].textContent = 'Title of host document';
-    shadowRoot.getElementsByTagName('title')[0].textContent =
+    shadowRoot.querySelector('title').textContent =
         'Title of shadow tree';
 
     assert_equals(doc.title, 'Title of host document');
@@ -165,7 +168,7 @@
 
 generate_tests(
     testHTMLCollection,
-    ['anchors', 'applets', 'all'].map(
+    ['anchors', 'all'].map(
         function (accessor) {
             return [
                 'Elements in a shadow tree should not be accessible from ' +
@@ -196,7 +199,7 @@
     body.appendChild(pHost);
     doc.documentElement.appendChild(body);
 
-    var shadowRoot = body.createShadowRoot();
+    var shadowRoot = body.attachShadow({mode: 'open'});
     var pShadow = doc.createElementNS(namespace, 'p');
     pShadow.className = "shadow";
     shadowRoot.appendChild(pShadow);
@@ -210,10 +213,10 @@
 test(function () {
     var doc = document.implementation.createHTMLDocument('');
     populateTestContentToHostDocument(doc);
-    var shadowRoot = doc.documentElement.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     populateTestContentToShadowRoot(shadowRoot);
 
-    shadowRoot.getElementsByTagName('p')[0].id = 'test-id';
+    shadowRoot.querySelectorAll('p')[0].id = 'test-id';
     assert_equals(doc.getElementById('test-id'), null);
 },
     'Elements in a shadow tree should not be accessible from owner ' +
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html
index 9d6401a..6401bafa 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html
@@ -18,7 +18,7 @@
 <meta name="assert" content="Upper-boundary encapsulation: The nodes are accessible using shadow root's DOM tree accessor methods.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -30,53 +30,33 @@
 
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var image = doc.createElement('img');
     shadowRoot.appendChild(image);
 
-    assert_singleton_node_list(shadowRoot.getElementsByTagName('img'), image);
+    assert_singleton_node_list(shadowRoot.querySelectorAll('img'), image);
 },
     'Elements in a shadow tree should be accessible via shadow root\'s ' +
-    'getElementsByTagName() DOM tree accessor.'
-);
-
-test(function () {
-    var namespace = 'http://www.w3.org/1999/xhtml';
-    var doc = document.implementation.createDocument(namespace, 'html');
-    doc.documentElement.appendChild(doc.createElementNS(namespace, 'head'));
-    var body = doc.createElementNS(namespace, 'body');
-    var imageHost = doc.createElementNS(namespace, 'img');
-    body.appendChild(imageHost);
-    doc.documentElement.appendChild(body);
-
-    var shadowRoot = body.createShadowRoot();
-    var imageShadow = doc.createElementNS(namespace, 'img');
-    shadowRoot.appendChild(imageShadow);
-
-    assert_singleton_node_list(
-        shadowRoot.getElementsByTagNameNS(namespace, 'img'), imageShadow);
-},
-    'Elements in a shadow tree should be accessible via shadow root\'s ' +
-    'getElementsByTagNameNS() DOM tree accessor.'
+    'querySelectorAll() DOM tree accessor.'
 );
 
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var div = doc.createElement('div');
     div.className = 'div-class';
     shadowRoot.appendChild(div);
 
     assert_singleton_node_list(
-        shadowRoot.getElementsByClassName('div-class'), div);
+        shadowRoot.querySelectorAll('.div-class'), div);
 },
-    'Elements in a shadow tree should be accessible via shadow root\'s ' +
-    'getElementsByClassName() DOM tree accessor.'
+    'Elements with a specific class in a shadow tree should be accessible via' +
+    'shadow root\'s querySelectorAll() DOM tree accessor.'
 );
 
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var div = doc.createElement('div');
     div.id = 'div-id';
     shadowRoot.appendChild(div);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html
index 501e6c4..d9d9600 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html
@@ -19,7 +19,7 @@
 <meta name="assert" content="Upper-boundary encapsulation: The ownerDocument property of all nodes in shadow tree refers to the document of the shadow host.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -27,11 +27,11 @@
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
     doc.body.innerHTML = '<div>A<div>B</div>C<div><span>D</span></div>E</div>';
-    var nodeIterator = doc.createNodeIterator(doc.documentElement,
+    var nodeIterator = doc.createNodeIterator(doc.body,
                                               NodeFilter.SHOW_ELEMENT, null);
     var node;
     while (node = nodeIterator.nextNode()) {
-        var shadowRoot = node.createShadowRoot();
+        var shadowRoot = node.attachShadow({mode: 'open'});
         assert_equals(shadowRoot.ownerDocument, doc);
     }
 }, 'ownerDocument property of a shadow root should be the document of the ' +
@@ -50,7 +50,7 @@
 
     for (var depth = 1; depth <= MAX_DEPTH; ++depth) {
         var host = doc.getElementById('depth-' + depth);
-        var shadowRoot = host.createShadowRoot();
+        var shadowRoot = host.attachShadow({mode: 'open'});
         assert_equals(shadowRoot.ownerDocument, doc,
                       'ownerDocument mismatch for #depth-' + depth);
     }
@@ -60,7 +60,7 @@
 
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var div = doc.createElement('div');
     shadowRoot.appendChild(div);
     assert_equals(div.ownerDocument, doc);
@@ -70,7 +70,7 @@
 test(function () {
     var doc1 = document.implementation.createHTMLDocument('Test 1');
     var doc2 = document.implementation.createHTMLDocument('Test 2');
-    var shadowRoot = doc1.body.createShadowRoot();
+    var shadowRoot = doc1.body.attachShadow({mode: 'open'});
     var div = doc2.createElement('div');
     shadowRoot.appendChild(div);
     assert_equals(div.ownerDocument, doc1);
@@ -81,7 +81,7 @@
 test(function () {
     var doc1 = document.implementation.createHTMLDocument('Test 1');
     var doc2 = document.implementation.createHTMLDocument('Test 2');
-    var shadowRoot = doc1.body.createShadowRoot();
+    var shadowRoot = doc1.body.attachShadow({mode: 'open'});
     doc2.body.innerHTML =
         '<div id="root">A<div>B</div>C<div><span>D</span></div>E</div>';
     shadowRoot.appendChild(doc2.getElementById('root'));
@@ -97,7 +97,7 @@
 test(function () {
     var doc1 = document.implementation.createHTMLDocument('Test 1');
     var doc2 = document.implementation.createHTMLDocument('Test 2');
-    var shadowRoot = doc1.body.createShadowRoot();
+    var shadowRoot = doc1.body.attachShadow({mode: 'open'});
     doc2.body.innerHTML = '<div id="parent"><div id="child"></div></div>';
     shadowRoot.appendChild(doc2.getElementById('child'));
     assert_equals(doc2.getElementById('parent').ownerDocument, doc2);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html
index da01748e..232fec8 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html
@@ -19,7 +19,8 @@
 <meta name="assert" content="Upper-boundary encapsulation: The ownerDocument property of all nodes in shadow tree refers to the document of the shadow host.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -28,8 +29,8 @@
     var doc = document.implementation.createHTMLDocument('Test');
     var element = doc.createElement(elementName);
     doc.body.appendChild(element);
-    var shadowRoot = element.createShadowRoot();
-    HTML5_ELEMENT_NAMES.forEach(function (name) {
+    var shadowRoot = element.attachShadow({mode: 'open'});
+    ATTACHSHADOW_SAFELISTED_ELEMENTS.forEach(function (name) {
         shadowRoot.appendChild(doc.createElement(name));
     });
 
@@ -40,7 +41,7 @@
     }
 }
 
-var testParameters = HTML5_ELEMENT_NAMES.map(function (name) {
+var testParameters = ATTACHSHADOW_SAFELISTED_ELEMENTS.map(function (name) {
     return [
         'ownerDocument property of any elements in a shadow tree should ' +
         'match the document of the shadow host, when the host is a "' +
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html
index 9c624db..1d7c918 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html
@@ -17,7 +17,7 @@
 <meta name="assert" content="Upper-boundary encapsulation: Nodes in a shadow tree must not be accessible through selector APIs of owner document.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -35,7 +35,7 @@
     pHost.className = 'test-class';
     pHost.id = 'test-id';
     doc.body.appendChild(pHost);
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var pShadow = doc.createElement('p');
     pShadow.className = 'test-class';
     pShadow.id = 'test-id';
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html
index 5cde8c1e..b5f0df1 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html
@@ -18,7 +18,7 @@
 <meta name="assert" content="Upper-boundary encapsulation: Nodes in a shadow tree must be accessible through selector APIs of the shadow root.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -36,7 +36,7 @@
     pHost.className = 'test-class';
     pHost.id = 'test-id';
     doc.body.appendChild(pHost);
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var pShadow = doc.createElement('p');
     pShadow.className = 'test-class';
     pShadow.id = 'test-id';
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html
index a33535a..7cd8f08 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html
@@ -18,29 +18,29 @@
 <meta name="assert" content="Upper-boundary encapsulation: The parentNode and parentElement attributes of the shadow root object must always return null.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     assert_equals(shadowRoot.parentNode, null);
 }, 'The parentNode attribute of a shadow root must always return null.');
 
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     assert_equals(shadowRoot.parentElement, null);
 }, 'The parentElement attribute of a shadow root must always return null.');
 
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var outerShadowRoot = doc.body.createShadowRoot();
+    var outerShadowRoot = doc.body.attachShadow({mode: 'open'});
     var div = doc.createElement('div');
     outerShadowRoot.appendChild(div);
-    var innerShadowRoot = div.createShadowRoot();
+    var innerShadowRoot = div.attachShadow({mode: 'open'});
     assert_equals(innerShadowRoot.parentNode, null);
 },
     'The parentNode attribute of a shadow root must always return null, ' +
@@ -49,10 +49,10 @@
 
 test(function () {
     var doc = document.implementation.createHTMLDocument('Test');
-    var outerShadowRoot = doc.body.createShadowRoot();
+    var outerShadowRoot = doc.body.attachShadow({mode: 'open'});
     var div = doc.createElement('div');
     outerShadowRoot.appendChild(div);
-    var innerShadowRoot = div.createShadowRoot();
+    var innerShadowRoot = div.attachShadow({mode: 'open'});
     assert_equals(innerShadowRoot.parentElement, null);
 },
     'The parentElement attribute of a shadow root must always return null, ' +
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-005.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-005.html
index 0d5a332..fe99746 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-005.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-005.html
@@ -16,7 +16,7 @@
 <meta name="assert" content="Upper-boundary encapsulation:The nodes with a unique id and named elements are not addressable from any attributes of elements in shadow host's document">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -26,7 +26,7 @@
     var d = newHTMLDocument();
     var div = d.createElement('div');
     d.body.appendChild(div);
-    var s = div.createShadowRoot();
+    var s = div.attachShadow({mode: 'open'});
 
     // node in shadow with id
     var input = d.createElement('input');
@@ -52,7 +52,7 @@
         var d = newHTMLDocument();
         var div = d.createElement('div');
         d.body.appendChild(div);
-        var s = div.createShadowRoot();
+        var s = div.attachShadow({mode: 'open'});
 
         var form = d.createElement('form');
         form.setAttribute('id', 'form_id');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-007.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-007.html
index 3b0b78b..1ffc0aa3 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-007.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-007.html
@@ -16,7 +16,7 @@
 <meta name="assert" content="Upper-boundary encapsulation:The nodes with a unique id and named elements are addressable from any attributes of elements in the same shadow DOM subtree">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -26,7 +26,7 @@
     var d = newHTMLDocument();
     var div = d.createElement('div');
     d.body.appendChild(div);
-    var s = div.createShadowRoot();
+    var s = div.attachShadow({mode: 'open'});
 
     var input = d.createElement('input');
     input.setAttribute('type', 'text');
@@ -61,7 +61,7 @@
         div = d.createElement('div');
         d.body.appendChild(div);
 
-        var s = div.createShadowRoot();
+        var s = div.attachShadow({mode: 'open'});
         s.appendChild(form);
         s.appendChild(el);
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-009.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-009.html
index 639fec1e..3f08ec2e7 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-009.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-009.html
@@ -18,7 +18,7 @@
 <meta name="assert" content="Upper-boundary encapsulation: no nodes other than shadow root descendants are accessible with shadow root DOM tree accessor methods">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -53,10 +53,10 @@
     ctx.d = newHTMLDocument();
     A_04_01_09.setupBlock(ctx, 'd', ctx.d.body);
 
-    ctx.s1 = ctx.d_p1.createShadowRoot();
+    ctx.s1 = ctx.d_p1.attachShadow({mode: 'open'});
     A_04_01_09.setupBlock(ctx, 's1', ctx.s1);
 
-    ctx.s2 = ctx.s1_p1.createShadowRoot();
+    ctx.s2 = ctx.s1_p1.attachShadow({mode: 'open'});
     A_04_01_09.setupBlock(ctx, 's2', ctx.s2);
 
     assert_true(ctx.d_div1 != null, 'setup:d_div1');
@@ -69,78 +69,38 @@
     return ctx;
 };
 
-//check getElementsByTagName
+//check querySelectorAll
 test(function () {
     var ctx = A_04_01_09.setup();
 
     assert_nodelist_contents_equal_noorder(
-        ctx.s1.getElementsByTagName('div'), [ctx.s1_div1, ctx.s1_div2],
+        ctx.s1.querySelectorAll('div'), [ctx.s1_div1, ctx.s1_div2],
         'nodes, other than shadow root descendants, should not be accessible with ' +
             'ShadowRoot.getElementsByTagName (s1)');
 
     assert_nodelist_contents_equal_noorder(
-        ctx.s2.getElementsByTagName('div'), [ctx.s2_div1, ctx.s2_div2],
+        ctx.s2.querySelectorAll('div'), [ctx.s2_div1, ctx.s2_div2],
         'nodes, other than shadow root descendants, should not be accessible with ' +
             'ShadowRoot.getElementsByTagName (s2)');
 
 }, 'A_04_01_09_T01');
 
-// getElementsByTagNameNS
+//check querySelectorAll for class
 test(function () {
     var ctx = A_04_01_09.setup();
 
     assert_nodelist_contents_equal_noorder(
-        ctx.s1.getElementsByTagNameNS('*', 'div'), [ctx.s1_div1, ctx.s1_div2],
-        'nodes, other than shadow root descendants, should not be accessible with ' +
-            'ShadowRoot.getElementsByTagNameNS (s1)');
-
-    assert_nodelist_contents_equal_noorder(
-        ctx.s2.getElementsByTagNameNS('*', 'div'), [ctx.s2_div1, ctx.s2_div2],
-        'nodes, other than shadow root descendants, should not be accessible with ' +
-            'ShadowRoot.getElementsByTagNameNS (s2)');
-
-}, 'A_04_01_09_T02');
-
-//check getElementsByClassName
-test(function () {
-    var ctx = A_04_01_09.setup();
-
-    assert_nodelist_contents_equal_noorder(
-        ctx.s1.getElementsByClassName('cls'), [ctx.s1_div1, ctx.s1_p1, ctx.s1_div2],
+        ctx.s1.querySelectorAll('.cls'), [ctx.s1_div1, ctx.s1_p1, ctx.s1_div2],
         'nodes, other than shadow root descendants, should not be accessible with ' +
             'ShadowRoot.getElementsByClassName (s1)');
 
     assert_nodelist_contents_equal_noorder(
-        ctx.s2.getElementsByClassName('cls'), [ctx.s2_div1, ctx.s2_p1, ctx.s2_div2],
+        ctx.s2.querySelectorAll('.cls'), [ctx.s2_div1, ctx.s2_p1, ctx.s2_div2],
         'nodes, other than shadow root descendants, should not be accessible with ' +
             'ShadowRoot.getElementsByClassName (s2)');
 
 }, 'A_04_01_09_T03');
 
-// check getElementById
-test(function () {
-    var ctx = A_04_01_09.setup();
-
-    assert_equals(ctx.s1.getElementById('d_id1'), null, 'Expected no access to d_div1 from s1.getElementById()');
-    assert_equals(ctx.s1.getElementById('d_id2'), null, 'Expected no access to d_div2 from s1.getElementById()');
-    assert_equals(ctx.s2.getElementById('d_id1'), null, 'Expected no access to d_div1 from s2.getElementById()');
-    assert_equals(ctx.s2.getElementById('d_id2'), null, 'Expected no access to d_div1 from s2.getElementById()');
-
-
-    assert_equals(ctx.s1.getElementById('s1_id1'), ctx.s1_div1, 'Expected access to s1_div1 form s1.getElementById()');
-    assert_equals(ctx.s1.getElementById('s1_id2'), ctx.s1_div2, 'Expected access to s1_div2 form s1.getElementById()');
-    assert_equals(ctx.s2.getElementById('s2_id1'), ctx.s2_div1, 'Expected access to s2_div1 form s2.getElementById()');
-    assert_equals(ctx.s2.getElementById('s2_id2'), ctx.s2_div2, 'Expected access to s2_div2 form s2.getElementById()');
-
-
-    assert_equals(ctx.s1.getElementById('s2_id1'), null, 'Expected no access to s2_div1 form s1.getElementById()');
-    assert_equals(ctx.s1.getElementById('s2_id2'), null, 'Expected no access to s2_div2 form s1.getElementById()');
-    assert_equals(ctx.s2.getElementById('s1_id1'), null, 'Expected no access to s1_div1 form s2.getElementById()');
-    assert_equals(ctx.s2.getElementById('s1_id2'), null, 'Expected no access to s1_div2 form s2.getElementById()');
-
-}, 'A_04_01_09_T04');
-
-
 // check querySelector for id
 test(function () {
     var ctx = A_04_01_09.setup();
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-011.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-011.html
index ff29fc9..48f6e2b 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-011.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/test-011.html
@@ -16,48 +16,30 @@
 <meta name="assert" content="Upper-boundary encapsulation:The style sheets, represented by the shadow nodes are not accessible using shadow host document's CSSOM extensions">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
-// check that <style> element added to head is not exposed
-var A_04_01_11_T1 = async_test('A_04_01_11_T01');
-
-A_04_01_11_T1.step(function () {
-    var ctx = newContext();
-    var iframe = newIFrame(ctx, '../../resources/blank.html');
-    iframe.onload = A_04_01_11_T1.step_func(step_unit(function () {
-        var d = iframe.contentDocument;
-        var initialStyleSheetsCount = d.styleSheets.length;
-        var s = d.head.createShadowRoot();
-        var style = d.createElement('style');
-        s.appendChild(style);
-        assert_equals(d.styleSheets.length, initialStyleSheetsCount, 'style elements in shadow DOM must not be exposed via ' +
-            'the document.styleSheets collection ');
-
-    }, ctx, A_04_01_11_T1));
-});
-
-
 // check that <link> element added to head is not exposed
 test(unit(function (ctx) {
 
-	var d = newRenderedHTMLDocument(ctx);
-	var initialStyleSheetsCount = d.styleSheets.length;
+    var d = newRenderedHTMLDocument(ctx);
+    var initialStyleSheetsCount = d.styleSheets.length;
 
-	var link = d.createElement('link');
-	link.setAttribute('rel', 'stylesheet');
-	d.body.appendChild(link);
+    var link = d.createElement('link');
+    link.setAttribute('rel', 'stylesheet');
+    d.body.appendChild(link);
 
-	//create Shadow root
-	var root = d.createElement('div');
-	d.body.appendChild(root);
-	var s = root.createShadowRoot();
+    //create Shadow root
+    var root = d.createElement('div');
+    d.body.appendChild(root);
+    var s = root.attachShadow({mode: 'open'});
 
-	s.appendChild(link);
+    s.appendChild(link);
 
-	assert_equals(d.styleSheets.length, initialStyleSheetsCount, 'stylesheet link elements in shadow DOM must not be ' +
+    assert_equals(d.styleSheets.length, initialStyleSheetsCount, 'stylesheet link elements in shadow DOM must not be ' +
             'exposed via the document.styleSheets collection');
 
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html
index 19998dc4..b861960 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html
@@ -18,7 +18,7 @@
 <meta name="assert" content="Upper-boundary encapsulation: The nodes and named elements are not accessible from Window object named properties.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -28,7 +28,7 @@
     try {
         host.style.display = 'none';
         document.body.appendChild(host);
-        var shadowRoot = host.createShadowRoot();
+        var shadowRoot = host.attachShadow({mode: 'open'});
         var iframe = document.createElement('iframe');
         iframe.style.display = 'none';
         iframe.name = 'test-name';
@@ -42,49 +42,6 @@
     'An iframe element in a shadow tree should not be accessible from ' +
     'window\'s named properties with its "name" attribute value.'
 );
-
-var frameTest = async_test(
-    'A frame element in a shadow tree should not be accessible from ' +
-    'window\'s named properties with its "name" attribute value.');
-
-frameTest.step(function () {
-    // To test a document with frames, an iframe containing frames is created.
-    var srcdoc = [
-        '<!DOCTYPE html>',
-        '<html>',
-        '<head>',
-        '<title>Frames Test</title>',
-        '<script src="../../testcommon.js"><' + '/script>',
-        '</head>',
-        '<frameset id="host" cols="50%,*">',
-        '<frame src="about:blank" name="host-frame1">',
-        '<frame src="about:blank" name="host-frame2">',
-        '</frameset>',
-        '</html>'
-    ].join('\n');
-    var iframe = document.createElement('iframe');
-    iframe.srcdoc = srcdoc;
-    iframe.style.display = 'none';
-
-    iframe.addEventListener('load', frameTest.step_func(function (event) {
-        try {
-            var doc = iframe.contentDocument;
-            var win = iframe.contentWindow;
-            var shadowRoot = doc.getElementById('host').createShadowRoot();
-            shadowRoot.innerHTML =
-                '<frame src="about:blank" name="shadow-frame1">\n' +
-                '<frame src="about:blank" name="shadow-frame2">';
-            assert_false('shadow-frame1' in win);
-            assert_false('shadow-frame2' in win);
-            frameTest.done();
-        } finally {
-            if (iframe.parentNode)
-                iframe.parentNode.removeChild(iframe);
-        }
-    }));
-
-    document.body.appendChild(iframe);
-});
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html
index 0d289304..7a05bc6 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html
@@ -18,14 +18,14 @@
 <meta name="assert" content="Upper-boundary encapsulation: The nodes and named elements are not accessible from Window object named properties.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 function testNameAttribute(elementName) {
     var doc = document.implementation.createHTMLDocument('Title');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var element = doc.createElement(elementName);
     element.name = 'test-name';
     shadowRoot.appendChild(element);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html
index 152dfa07a..e279292 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html
@@ -18,14 +18,15 @@
 <meta name="assert" content="Upper-boundary encapsulation: The nodes and named elements are not accessible from Window object named properties.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 function testIDAttribute(elementName) {
     var doc = document.implementation.createHTMLDocument('Title');
-    var shadowRoot = doc.body.createShadowRoot();
+    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     var element = doc.createElement(elementName);
     element.id = 'test-id';
     shadowRoot.appendChild(element);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/css-variables/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/css-variables/test-001.html
deleted file mode 100644
index b6d63d6..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/css-variables/test-001.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_06_01_01</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#css-variables">
-<meta name="assert" content="CSS variables: The shadow host styles being inherited by the children of the shadow root must also apply to CSS Variables.">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-//TODO For now (November, 2012) CSS variables support is not implemented yet
-// so this test won't work. Treat it as a placeholder for now
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-    d.head.innerHtml = '' +
-    	'<style>' +
-    	'body {font-size:10px;}' +
-    	'</style>';
-
-	d.body.innerHTML =
-		'<ul id="shHost">' +
-			'<li id="li1" class="shadow">1</li>' +
-			'<li id="li2" class="shadow2">2</li>' +
-			'<li id="li3" class="shadow">3</li>' +
-			'<li id="li4">4</li>' +
-			'<li id="li5" class="shadow">5</li>' +
-			'<li id="li6" class="shadow2">6</li>' +
-		'</ul>';
-
-
-	var host = d.querySelector('#shHost');
-	var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML ='<ul><content select=".shadow"></content></ul>';
-	s.appendChild(div);
-
-	var defHeight1 = d.querySelector('#li1').offsetHeight;
-	var defHeight3 = d.querySelector('#li3').offsetHeight;
-	var defHeight5 = d.querySelector('#li5').offsetHeight;
-
-	var style = d.createElement('style');
-	style.innerHTML =':root {' +
-		'var-text-size: 30px;' +
-		'}' +
-		'body {' +
-		'font-size: var(text-size);' +
-		'}';
-	s.appendChild(style);
-
-	assert_true(d.querySelector('#li1').offsetHeight > defHeight1, 'Point 1: Element height should be changed');
-	assert_true(d.querySelector('#li3').offsetHeight > defHeight3, 'Point 2: Element height should be changed');
-	assert_true(d.querySelector('#li5').offsetHeight > defHeight5, 'Point 3: Element height should be changed');
-
-}), 'A_06_01_01_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html
deleted file mode 100644
index b96daf8..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/deep-combinator/deep-combinator-001.html
+++ /dev/null
@@ -1,156 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: /deep/ combinator</title>
-<link rel="author" title="Kenji Baheux" href="mailto:kenjibaheux@google.com">
-<link rel="help" href="http://dev.w3.org/csswg/css-scoping/#deep-combinator">
-<meta name="assert" content="/deep/ should select through all Shadow trees">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-    var d = newRenderedHTMLDocument(ctx);
-
-    var outerhost = d.createElement('div');
-    outerhost.setAttribute('id', 'foo-host');
-    var span0 = d.createElement('span');
-    span0.setAttribute('id', 'outer-host');
-    outerhost.appendChild(span0);
-
-    var outerroot = outerhost.createShadowRoot();
-
-    var div1 = d.createElement('div');
-    var span1 = d.createElement('span');
-    span1.setAttribute('id', 'not-top');
-    div1.appendChild(span1);
-    outerroot.appendChild(div1);
-
-    var span2 = d.createElement('span');
-    span2.setAttribute('id', 'top');
-    outerroot.appendChild(span2);
-
-
-    var innerhost = d.createElement('div');
-    innerhost.setAttribute('id', 'bar-host');
-    var span3 = d.createElement('span');
-    span3.setAttribute('id', 'inner-host');
-    innerhost.appendChild(span3);
-
-    var innerroot = innerhost.createShadowRoot();
-
-    var span4 = d.createElement('span');
-    span4.setAttribute('id', 'nested');
-    innerroot.appendChild(span4);
-    outerroot.appendChild(innerhost);
-
-    d.body.appendChild(outerhost);
-
-
-    assert_equals(d.querySelectorAll('#foo-host /deep/ span').length, 5, 'Point 1: match only direct children of the outer shadow tree');
-    assert_equals(d.querySelectorAll('#foo-host /deep/ span')[0], span1, 'Point 2: incorrect match');
-    assert_equals(d.querySelectorAll('#foo-host /deep/ span')[1], span2, 'Point 3: incorrect match');
-    assert_equals(d.querySelectorAll('#foo-host /deep/ span')[2], span4, 'Point 4: incorrect match');
-    assert_equals(d.querySelectorAll('#foo-host /deep/ span')[3], span3, 'Point 5: incorrect match');
-    assert_equals(d.querySelectorAll('#foo-host /deep/ span')[4], span0, 'Point 6: incorrect match');
- }), 'SD_SHADOW_DEEP_QUERYSELECTOR_T1');
-
-test(unit(function (ctx) {
-    var d = newRenderedHTMLDocument(ctx);
-
-    var outerhost = d.createElement('div');
-    outerhost.setAttribute('id', 'foo-host');
-    var span0 = d.createElement('span');
-    span0.setAttribute('id', 'outer-host');
-    outerhost.appendChild(span0);
-
-    var s1 = outerhost.createShadowRoot();
-
-    var div1 = d.createElement('div');
-    var span1 = d.createElement('span');
-    span1.setAttribute('id', 'not-top');
-    div1.appendChild(span1);
-    s1.appendChild(div1);
-
-    var span2 = d.createElement('span');
-    span2.setAttribute('id', 'top');
-    s1.appendChild(span2);
-
-
-    var innerhost = d.createElement('div');
-    innerhost.setAttribute('id', 'bar-host');
-    var span3 = d.createElement('span');
-    span3.setAttribute('id', 'inner-host');
-    innerhost.appendChild(span3);
-
-    var s2 = innerhost.createShadowRoot();
-
-    var span4 = d.createElement('span');
-    span4.setAttribute('id', 'nested');
-    s2.appendChild(span4);
-    s1.appendChild(innerhost);
-
-    d.body.appendChild(outerhost);
-
-
-    assert_equals(s1.querySelectorAll('* /deep/ span').length, 3, 'Point 1: match only in the inner shadow tree');
-    assert_equals(s1.querySelectorAll('* /deep/ span')[0], span1, 'Point 2: incorrect match');
-    assert_equals(s1.querySelectorAll('* /deep/ span')[1], span4, 'Point 4: incorrect match');
-    assert_equals(s1.querySelectorAll('* /deep/ span')[2], span3, 'Point 5: incorrect match');
- }), 'SD_SHADOW_DEEP_QUERYSELECTOR_T2');
-
-test(unit(function (ctx) {
-    var d = newRenderedHTMLDocument(ctx);
-
-    var outerhost = d.createElement('div');
-    outerhost.setAttribute('id', 'foo-host');
-    var span0 = d.createElement('span');
-    span0.setAttribute('id', 'outer-host');
-    outerhost.appendChild(span0);
-
-    var s1 = outerhost.createShadowRoot();
-
-    var div1 = d.createElement('div');
-    var span1 = d.createElement('span');
-    span1.setAttribute('id', 'not-top');
-    div1.appendChild(span1);
-    s1.appendChild(div1);
-
-    var span2 = d.createElement('span');
-    span2.setAttribute('id', 'top');
-    s1.appendChild(span2);
-
-
-    var innerhost = d.createElement('div');
-    innerhost.setAttribute('id', 'bar-host');
-    var span3 = d.createElement('span');
-    span3.setAttribute('id', 'inner-host');
-    innerhost.appendChild(span3);
-
-    var s2 = innerhost.createShadowRoot();
-
-    var span4 = d.createElement('span');
-    span4.setAttribute('id', 'nested');
-    s2.appendChild(span4);
-    s1.appendChild(innerhost);
-
-    d.body.appendChild(outerhost);
-
-
-    assert_equals(s2.querySelectorAll('* /deep/ span').length, 0, 'Point 1: no match');
- }), 'SD_SHADOW_DEEP_QUERYSELECTOR_T3');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html
index b83dad0..a56be977 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/not-apply-in-shadow-root-001.html
@@ -15,7 +15,7 @@
 <link rel="author" title="Kazuhito Hokamura" href="mailto:k.hokamura@gmail.com">
 <link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
 <meta name="assert" content="Styles: CSS rules declared in an enclosing tree must not apply in a shadow tree if apply-author-styles flag is not set.">
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
 <style>
 div {
   width: 100px;
@@ -29,7 +29,7 @@
 <div id="shadow-host"></div>
 <script>
 var shadowHost = document.getElementById('shadow-host');
-var shadowRoot = shadowHost.createShadowRoot();
+var shadowRoot = shadowHost.attachShadow({mode: 'open'});
 var style = document.createElement('style');
 style.innerHTML = 'div { background: red }';
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/shadow-pseudoelement/shadow-pseudoelement-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/shadow-pseudoelement/shadow-pseudoelement-001.html
deleted file mode 100644
index 5ec45b5..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/shadow-pseudoelement/shadow-pseudoelement-001.html
+++ /dev/null
@@ -1,150 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: ::shadow pseudo element</title>
-<link rel="author" title="Kenji Baheux" href="mailto:kenjibaheux@google.com">
-<link rel="help" href="http://dev.w3.org/csswg/css-scoping/#shadow-pseudoelement">
-<meta name="assert" content="::shadow should match a shadow root">
-<script src="../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-    var d = newRenderedHTMLDocument(ctx);
-
-    var outerhost = d.createElement('div');
-    outerhost.setAttribute('id', 'foo-host');
-    var span0 = d.createElement('span');
-    span0.setAttribute('id', 'outer-host');
-    outerhost.appendChild(span0);
-
-    var s1 = outerhost.createShadowRoot();
-
-    var div1 = d.createElement('div');
-    var span1 = d.createElement('span');
-    span1.setAttribute('id', 'not-top');
-    div1.appendChild(span1);
-    s1.appendChild(div1);
-
-    var span2 = d.createElement('span');
-    span2.setAttribute('id', 'top');
-    s1.appendChild(span2);
-
-
-    var innerhost = d.createElement('div');
-    innerhost.setAttribute('id', 'bar-host');
-    var span3 = d.createElement('span');
-    span3.setAttribute('id', 'inner-host');
-    innerhost.appendChild(span3);
-
-    var s2 = innerhost.createShadowRoot();
-
-    var span4 = d.createElement('span');
-    span4.setAttribute('id', 'nested');
-    s2.appendChild(span4);
-    s1.appendChild(innerhost);
-
-    d.body.appendChild(outerhost);
-
-    assert_equals(d.querySelectorAll('#foo-host::shadow span').length, 3, 'Point 1: match only direct children of the outer shadow tree');
-    assert_equals(d.querySelectorAll('#foo-host::shadow span')[0], span1, 'Point 2: incorrect match');
-    assert_equals(d.querySelectorAll('#foo-host::shadow span')[1], span2, 'Point 3: incorrect match');
-    assert_equals(d.querySelectorAll('#foo-host::shadow span')[2], span3, 'Point 4: incorrect match');
- }), 'SD_SHADOW_PSEUDOELEMENT_QUERYSELECTOR_T1');
-
-test(unit(function (ctx) {
-    var d = newRenderedHTMLDocument(ctx);
-
-    var outerhost = d.createElement('div');
-    outerhost.setAttribute('id', 'foo-host');
-    var span0 = d.createElement('span');
-    span0.setAttribute('id', 'outer-host');
-    outerhost.appendChild(span0);
-
-    var s1 = outerhost.createShadowRoot();
-
-    var div1 = d.createElement('div');
-    var span1 = d.createElement('span');
-    span1.setAttribute('id', 'not-top');
-    div1.appendChild(span1);
-    s1.appendChild(div1);
-
-    var span2 = d.createElement('span');
-    span2.setAttribute('id', 'top');
-    s1.appendChild(span2);
-
-
-    var innerhost = d.createElement('div');
-    innerhost.setAttribute('id', 'bar-host');
-    var span3 = d.createElement('span');
-    span3.setAttribute('id', 'inner-host');
-    innerhost.appendChild(span3);
-
-    var s2 = innerhost.createShadowRoot();
-
-    var span4 = d.createElement('span');
-    span4.setAttribute('id', 'nested');
-    s2.appendChild(span4);
-    s1.appendChild(innerhost);
-
-    d.body.appendChild(outerhost);
-
-    assert_equals(s1.querySelectorAll('*::shadow span').length, 1, 'Point 1: match only in the inner shadow tree');
-    assert_equals(s1.querySelectorAll('*::shadow span')[0], span4, 'Point 2: incorrect match');
- }), 'SD_SHADOW_PSEUDOELEMENT_QUERYSELECTOR_T2');
-
-test(unit(function (ctx) {
-    var d = newRenderedHTMLDocument(ctx);
-
-    var outerhost = d.createElement('div');
-    outerhost.setAttribute('id', 'foo-host');
-    var span0 = d.createElement('span');
-    span0.setAttribute('id', 'outer-host');
-    outerhost.appendChild(span0);
-
-    var s1 = outerhost.createShadowRoot();
-
-    var div1 = d.createElement('div');
-    var span1 = d.createElement('span');
-    span1.setAttribute('id', 'not-top');
-    div1.appendChild(span1);
-    s1.appendChild(div1);
-
-    var span2 = d.createElement('span');
-    span2.setAttribute('id', 'top');
-    s1.appendChild(span2);
-
-
-    var innerhost = d.createElement('div');
-    innerhost.setAttribute('id', 'bar-host');
-    var span3 = d.createElement('span');
-    span3.setAttribute('id', 'inner-host');
-    innerhost.appendChild(span3);
-
-    var s2 = innerhost.createShadowRoot();
-
-    var span4 = d.createElement('span');
-    span4.setAttribute('id', 'nested');
-    s2.appendChild(span4);
-    s1.appendChild(innerhost);
-
-    d.body.appendChild(outerhost);
-
-    assert_equals(s2.querySelectorAll('*::shadow span').length, 0, 'Point 1: no match');
- }), 'SD_SHADOW_PSEUDOELEMENT_QUERYSELECTOR_T3');
-
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-001.html
index df53128..163fdc21d 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-001.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Styles: CSS rules declared in an enclosing tree must not apply in a shadow tree if apply-author-styles flag is set to false for this tree">
 <script src="../../../../../resources/testharness.js"></script>
 <script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
+<script src="../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -27,25 +28,25 @@
     var d = newRenderedHTMLDocument(ctx);
 
     d.head.innerHTML = '<style>' +
-		'.invis {' +
-		'display:none;' +
-		'}' +
-		'</style>';
+        '.invis {' +
+        'display:none;' +
+        '}' +
+        '</style>';
 
     var host = d.createElement('div');
     d.body.appendChild(host);
 
-	//Shadow root to play with
-	var s = host.createShadowRoot();
+    //Shadow root to play with
+    var s = host.attachShadow({mode: 'open'});
 
-	var div1 = d.createElement('div');
-	div1.innerHTML ='<span id="shd" class="invis">This is the shadow tree</span>';
-	s.appendChild(div1);
+    var div1 = d.createElement('div');
+    div1.innerHTML ='<span id="shd" class="invis">This is the shadow tree</span>';
+    s.appendChild(div1);
 
-	//apply-author-styles flag is false by default. Invisible style shouldn't be applied
-	assert_true(s.querySelector('#shd').offsetTop > 0,
-    	'CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
-    	'if the apply-author-styles flag is set to false');
+    //apply-author-styles flag is false by default. Invisible style shouldn't be applied
+    assert_true(s.querySelector('#shd').offsetTop > 0,
+        'CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+        'if the apply-author-styles flag is set to false');
 
 
 }), 'A_06_00_01_T01');
@@ -57,115 +58,28 @@
     var d = newRenderedHTMLDocument(ctx);
 
     d.head.innerHTML = '<style>' +
-		'.invis {' +
-		'display:none;' +
-		'}' +
-		'</style>';
+        '.invis {' +
+        'display:none;' +
+        '}' +
+        '</style>';
 
     var host = d.createElement('div');
     d.body.appendChild(host);
 
-	//Shadow root to play with
-	var s = host.createShadowRoot();
+    //Shadow root to play with
+    var s = host.attachShadow({mode: 'open'});
 
-	var div1 = d.createElement('div');
-	div1.innerHTML ='<span id="shd" class="invis">This is the shadow tree</span>';
-	s.appendChild(div1);
+    var div1 = d.createElement('div');
+    div1.innerHTML ='<span id="shd" class="invis">This is the shadow tree</span>';
+    s.appendChild(div1);
 
-	//apply-author-styles flag is set to false. Invisible style shouldn't be applied
-	assert_true(s.querySelector('#shd').offsetTop > 0,
-    	'CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
-    	'if the apply-author-styles flag is set to false');
+    //apply-author-styles flag is set to false. Invisible style shouldn't be applied
+    assert_true(s.querySelector('#shd').offsetTop > 0,
+        'CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+        'if the apply-author-styles flag is set to false');
 
 
 }), 'A_06_00_01_T02');
-
-//test apply-author-styles flag in a nested tree (default value)
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.head.innerHTML = '<style>' +
-		'.invis {' +
-		'display:none;' +
-		'}' +
-		'</style>';
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-	//Shadow root to play with
-	var s1 = host.createShadowRoot();
-
-	var div1 = d.createElement('div');
-	div1.innerHTML = '<span id="shd1" class="invis">This is an old shadow tree</span>';
-	s1.appendChild(div1);
-
-	//younger tree
-	var s2 = host.createShadowRoot();
-	var div1 = d.createElement('div');
-	div1.innerHTML = '<span id="shd2" class="invis">This is a young shadow tree</span>' +
-		'<shadow><span id="shd3" class="invis">This is the shadow tree fallback content</span></shadow>';
-	s2.appendChild(div1);
-
-
-	//apply-author-styles flag is false by default. Invisible style shouldn't be applied
-	//shd1 and shd2 should be visible. sh3 not because the tree should be active
-	assert_true(s1.querySelector('#shd1').offsetTop > 0,
-    	'Point 1: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
-    	'if the apply-author-styles flag is set to false');
-	assert_true(s2.querySelector('#shd2').offsetTop > 0,
-	    'Point 2: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
-	    'if the apply-author-styles flag is set to false');
-	assert_equals(s2.querySelector('#shd3').offsetTop, 0,
-		'Fallback content shouldn\'t be rendered for active tree');
-
-
-}), 'A_06_00_01_T03');
-
-
-//test apply-author-styles flag in a nested tree (set it)
-test(unit(function (ctx) {
-
-    var d = newRenderedHTMLDocument(ctx);
-
-    d.head.innerHTML = '<style>' +
-		'.invis {' +
-		'display:none;' +
-		'}' +
-		'</style>';
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-	//Shadow root to play with
-	var s1 = host.createShadowRoot();
-
-	var div1 = d.createElement('div');
-	div1.innerHTML = '<span id="shd1" class="invis">This is an old shadow tree</span>';
-	s1.appendChild(div1);
-
-	//younger tree
-	var s2 = host.createShadowRoot();
-	var div1 = d.createElement('div');
-	div1.innerHTML = '<span id="shd2" class="invis">This is a young shadow tree</span>' +
-		'<shadow><span id="shd3" class="invis">This is the shadow tree fallback content</span></shadow>';
-	s2.appendChild(div1);
-
-
-	//apply-author-styles flag is set to false. Invisible style shouldn't be applied
-	//shd1 and shd2 should be visible. sh3 not because the tree should be active
-	assert_true(s1.querySelector('#shd1').offsetTop > 0,
-    	'Point 1: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
-    	'if the apply-author-styles flag is set to false');
-	assert_true(s2.querySelector('#shd2').offsetTop > 0,
-    	'Point 2: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
-    	'if the apply-author-styles flag is set to false');
-	assert_equals(s2.querySelector('#shd3').offsetTop, 0,
-		'Fallback content shouldn\'t be rendered for active tree');
-
-
-}), 'A_06_00_01_T04');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-003.html
index 66cc937..285ba98 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-003.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="Styles: Each shadow root has an associated list of zero or more style sheets, named shadow root style sheets">
 <script src="../../../../../resources/testharness.js"></script>
 <script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
+<script src="../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -27,7 +28,7 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     assert_equals(s.styleSheets.length, 0, 'There should be no style sheets');
 }), 'A_06_00_03_T01');
@@ -40,9 +41,9 @@
     d.body.appendChild(host);
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
-	assert_equals(s.styleSheets.length, 0, 'There should be no style sheets');
+    assert_equals(s.styleSheets.length, 0, 'There should be no style sheets');
 }), 'A_06_00_03_T02');
 
 //TODO Now this tests produces an error on Chromium because styleSheets.length
@@ -53,7 +54,7 @@
     var host = d.createElement('div');
 
     //Shadow root to play with
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     var style = d.createElement('style');
     style.textContent = 'div {width: 50%;}';
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-005.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-005.html
index 77614e4..a66be228 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-005.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-005.html
@@ -16,45 +16,46 @@
 <meta name="assert" content="Styles:CSS rules declared in a shadow root style sheets must not apply in the document tree,">
 <script src="../../../../../resources/testharness.js"></script>
 <script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
+<script src="../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 //check querySelector method
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
     d.body.innerHTML =
-    	'<div>' +
-    		'<span class="invis" id="theTreeSpan">This is an element in the document tree</span>' +
-    	'</div>' +
-    	'<div id="sr">' +
-    	'</div>';
+        '<div>' +
+            '<span class="invis" id="theTreeSpan">This is an element in the document tree</span>' +
+        '</div>' +
+        '<div id="sr">' +
+        '</div>';
 
-	var host = d.querySelector('#sr');
+    var host = d.querySelector('#sr');
 
-	//Shadow root to play with
-	var s = host.createShadowRoot();
+    //Shadow root to play with
+    var s = host.attachShadow({mode: 'open'});
 
-	var style = d.createElement('style');
-	style.innerHTML ='.invis {display:none}';
-	s.appendChild(style);
+    var style = d.createElement('style');
+    style.innerHTML ='.invis {display:none}';
+    s.appendChild(style);
 
-	var span = d.createElement('span');
-	span.setAttribute('id', 'theShadowSpan');
-	span.setAttribute('class', 'invis');
-	s.appendChild(span);
+    var span = d.createElement('span');
+    span.setAttribute('id', 'theShadowSpan');
+    span.setAttribute('class', 'invis');
+    s.appendChild(span);
 
-	//theTreeSpan should be visible, theShadowSpan not
-	assert_true(d.querySelector('#theTreeSpan').offsetTop > 0,
-		'CSS styles declared in shadow tree must not be applied to the elements ' +
-		'in the document tree');
+    //theTreeSpan should be visible, theShadowSpan not
+    assert_true(d.querySelector('#theTreeSpan').offsetTop > 0,
+        'CSS styles declared in shadow tree must not be applied to the elements ' +
+        'in the document tree');
 
-	//theTreeSpan should be visible, theShadowSpan not
-	assert_equals(s.querySelector('#theShadowSpan').offsetTop, 0,
-		'CSS styles declared in shadow tree must be applied to the element ' +
-		'in the same shadow tree');
+    //theTreeSpan should be visible, theShadowSpan not
+    assert_equals(s.querySelector('#theShadowSpan').offsetTop, 0,
+        'CSS styles declared in shadow tree must be applied to the element ' +
+        'in the same shadow tree');
 
 }), 'A_06_00_06_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-007.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-007.html
deleted file mode 100644
index 16e22077..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-007.html
+++ /dev/null
@@ -1,133 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_06_00_08</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
-<meta name="assert" content="Styles:The @host @-rule matches a shadow host in the nesting tree.">
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-// The some of the tests below fails.
-// See https://bugs.webkit.org/show_bug.cgi?id=103608
-
-
-
-//Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103608
-test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-
-    d.head.innerHTML = ':host {display:none;}';
-
-    d.body.innerHTML =
-    	'<ul class="cls">' +
-    		'<li id="li1" class="shadow">1</li>' +
-    		'<li id="li2" class="shadow2">2</li>' +
-    		'<li id="li3" class="shadow">3</li>' +
-    		'<li id="li4">4</li>' +
-    		'<li id="li5" class="shadow">5</li>' +
-    		'<li id="li6" class="shadow2">6</li>' +
-    	'</ul>';
-
-    var host = d.querySelector('.cls');
-	//Shadow root to play with
-	var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML ='<ul><content select=".shadow"></content></ul>';
-	s.appendChild(div);
-
-	//:host rule shouldn't take any effect
-	assert_true(d.querySelector('#li1').offsetTop > 0,
-		'Point 1: element should be rendered');
-	assert_true(d.querySelector('#li3').offsetTop > 0,
-		'Point 2: element should be rendered');
-	assert_true(d.querySelector('#li5').offsetTop > 0,
-		'Point 3: element should be rendered');
-
-
-}), 'A_06_00_08_T01');
-
-//TODO (sgrekhov) Check the expected result at https://www.w3.org/Bugs/Public/show_bug.cgi?id=20150
-test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-    	'<ul class="cls">' +
-    		'<li id="li1" class="shadow">1</li>' +
-    		'<li id="li2" class="shadow2">2</li>' +
-    		'<li id="li3" class="shadow">3</li>' +
-    		'<li id="li4">4</li>' +
-    		'<li id="li5" class="shadow">5</li>' +
-    		'<li id="li6" class="shadow2">6</li>' +
-    	'</ul>';
-
-    var host = d.querySelector('.cls');
-	//Shadow root to play with
-	var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML ='<ul><content select=".shadow"></content></ul>';
-	s.appendChild(div);
-
-	var style = d.createElement('style');
-    style.innerHTML = ':host ul {display:none;}';
-	s.appendChild(style);
-
-	assert_equals(d.querySelector('#li1').offsetTop, 0,
-		'Point 1: element should be rendered');
-	assert_equals(d.querySelector('#li3').offsetTop, 0,
-		'Point 2: element should be rendered');
-	assert_equals(d.querySelector('#li5').offsetTop, 0,
-		'Point 3: element should be rendered');
-
-
-}), 'A_06_00_08_T02');
-
-
-//Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103608
-test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-
-    var host = d.createElement('div');
-    host.className = 'gone';
-    d.body.appendChild(host);
-
-	//Older tree
-	var s1 = host.createShadowRoot();
-	var div1 = d.createElement('div');
-	div1.innerHTML = '<span id="shd1">This is an old shadow tree</span>';
-	s1.appendChild(div1);
-
-	//Younger tree
-	var s2 = host.createShadowRoot();
-	var div1 = d.createElement('div');
-	div1.innerHTML = '<span id="shd2">This is a young shadow tree</span>' +
-		'<shadow><span id="shd3">This is the shadow tree fallback content</span></shadow>';
-	s2.appendChild(div1);
-
-	var style = d.createElement('style');
-    style.innerHTML = ':host {display:none;}';
-	s2.appendChild(style);
-
-	assert_equals(s1.querySelector('#shd1').offsetTop, 0,
-		'Point 1: element should not be rendered');
-
-
-}), 'A_06_00_08_T03');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-008.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-008.html
index 8648a26..431aa85 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-008.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-008.html
@@ -16,80 +16,41 @@
 <meta name="assert" content="Styles:the styles of the shadow host are inherited by the children of the shadow root">
 <script src="../../../../../resources/testharness.js"></script>
 <script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
+<script src="../../../html/resources/common.js"></script>
+<script src="../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
     d.body.innerHTML = '' +
-    	'<div id="shHost" style="font-size:10px">' +
-    	'<span id="spn1">This is a shadow host child</span>' +
-    	'</div>';
+        '<div id="shHost" style="font-size:10px">' +
+        '<span id="spn1">This is a shadow host child</span>' +
+        '</div>';
 
     var host = d.querySelector('#shHost');
 
-	var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
-	var div = d.createElement('div');
-	div.innerHTML ='<span id="spn2">This is a shadow root child</span>';
-	s.appendChild(div);
+    var div = d.createElement('div');
+    div.innerHTML ='<span id="spn2">This is a shadow root child</span>';
+    s.appendChild(div);
 
-	assert_equals(d.querySelector('#spn1').offsetTop, 0,
-		'Element should not be rendered');
-	assert_true(s.querySelector('#spn2').offsetTop > 0,
-		'Element should be rendered');
+    assert_equals(d.querySelector('#spn1').offsetTop, 0,
+        'Element should not be rendered');
+    assert_true(s.querySelector('#spn2').offsetTop > 0,
+        'Element should be rendered');
 
-	var oldHeight = s.querySelector('#spn2').offsetHeight;
+    var oldHeight = s.querySelector('#spn2').offsetHeight;
 
-	host.setAttribute('style', 'font-size:20px');
+    host.setAttribute('style', 'font-size:20px');
 
-	assert_true(s.querySelector('#spn2').offsetHeight > oldHeight,
-		'Shadow host style must be aplied to the shadow root children');
+    assert_true(s.querySelector('#spn2').offsetHeight > oldHeight,
+        'Shadow host style must be aplied to the shadow root children');
 
 }), 'A_06_00_09_T01');
-
-
-
-
-test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-    	'<ul class="cls" style="font-size: 10px">' +
-    		'<li id="li1" class="shadow">1</li>' +
-    		'<li id="li2" class="shadow2">2</li>' +
-    		'<li id="li3" class="shadow">3</li>' +
-    		'<li id="li4">4</li>' +
-    		'<li id="li5" class="shadow">5</li>' +
-    		'<li id="li6" class="shadow2">6</li>' +
-    	'</ul>';
-
-    var host = d.querySelector('.cls');
-	//Shadow root to play with
-	var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML ='<ul><content select=".shadow"></content></ul>';
-	s.appendChild(div);
-
-	var height1 = d.querySelector('#li1').offsetHeight;
-	var height3 = d.querySelector('#li3').offsetHeight;
-	var height5 = d.querySelector('#li5').offsetHeight;
-
-	host.setAttribute('style', 'font-size: 20px');
-
-	assert_true(d.querySelector('#li1').offsetHeight > height1,
-		'Point 1: Shadow host style must be aplied to the shadow root children');
-	assert_true(d.querySelector('#li3').offsetHeight > height3,
-		'Point 2: Shadow host style must be aplied to the shadow root children');
-	assert_true(d.querySelector('#li5').offsetHeight > height5,
-		'Point 3: Shadow host style must be aplied to the shadow root children');
-
-
-}), 'A_06_00_09_T02');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-009.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-009.html
deleted file mode 100644
index 64916113..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-009.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_06_00_10</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
-<meta name="assert" content="Styles:the styles of the insertion point nodes are inherited by those child nodes of the shadow host that are assigned to this insertion point">
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-
-    d.body.innerHTML =
-    	'<ul class="cls" style="font-size: 10px">' +
-    		'<li id="li1" class="shadow">1</li>' +
-    		'<li id="li2" class="shadow2">2</li>' +
-    		'<li id="li3" class="shadow">3</li>' +
-    		'<li id="li4">4</li>' +
-    		'<li id="li5" class="shadow">5</li>' +
-    		'<li id="li6" class="shadow2">6</li>' +
-    	'</ul>';
-
-
-	var height1 = d.querySelector('#li1').offsetHeight;
-	var height2 = d.querySelector('#li2').offsetHeight;
-	var height3 = d.querySelector('#li3').offsetHeight;
-	var height4 = d.querySelector('#li4').offsetHeight;
-	var height5 = d.querySelector('#li5').offsetHeight;
-	var height6 = d.querySelector('#li6').offsetHeight;
-
-	assert_true(height1 > 0, 'Point 1: Element height should be greater than zero');
-	assert_true(height2 > 0, 'Point 2: Element height should be greater than zero');
-	assert_true(height3 > 0, 'Point 3: Element height should be greater than zero');
-	assert_true(height4 > 0, 'Point 4: Element height should be greater than zero');
-	assert_true(height5 > 0, 'Point 5: Element height should be greater than zero');
-	assert_true(height6 > 0, 'Point 6: Element height should be greater than zero');
-
-    var host = d.querySelector('.cls');
-	//Shadow root to play with
-    var s = host.createShadowRoot();
-
-	var div = d.createElement('div');
-	div.innerHTML ='<ul><content select=".shadow" style="font-size:20px"></content></ul>';
-	s.appendChild(div);
-
-
-	host.setAttribute('style', 'font-size: 20px');
-
-	assert_true(d.querySelector('#li1').offsetHeight > height1,
-		'Point 11: Insertion point style must be aplied to the node distributed into this point');
-	assert_true(d.querySelector('#li3').offsetHeight > height3,
-		'Point 12: Insertion point style must be aplied to the node distributed into this point');
-	assert_true(d.querySelector('#li5').offsetHeight > height5,
-		'Point 13: Insertion point style must be aplied to the node distributed into this point');
-
-}), 'A_06_00_10_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-010.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-010.html
deleted file mode 100644
index a1364b97..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/styles/test-010.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html>
-<!-- 
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
- -->
-<html>
-<head>
-<title>Shadow DOM Test: A_06_00_11</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
-<meta name="assert" content="Styles:the styles of the shadow insertion point node are inherited by the child nodes of the shadow root of the shadow tree, distributed to this shadow insertion point">
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-</head>
-<body>
-<div id="log"></div>
-<script>
-// Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103625
-test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
-
-    var host = d.createElement('div');
-    d.body.appendChild(host);
-
-	//Old tree
-	var s1 = host.createShadowRoot();
-
-	var div1 = d.createElement('div');
-	div1.setAttribute('style', 'font-size: 10px');
-	div1.innerHTML = '<span id="shd1">This is an old shadow tree</span>';
-	s1.appendChild(div1);
-
-	var height1 = s1.querySelector('#shd1').offsetHeight;
-
-	assert_true(height1 > 0, 'Element height should be greater than zero');
-
-	//younger tree
-	var s2 = host.createShadowRoot();
-	var div2 = d.createElement('div');
-	div2.innerHTML =  '<shadow style="font-size:20px"></shadow>';
-	s2.appendChild(div2);
-
-	assert_true(s1.querySelector('#shd1').offsetHeight > height1,
-		'Shadow insertion point style must be aplied to the child nodes of ' +
-    	'the shadow host that are assigned to this insertion point');
-}), 'A_06_00_11_T01');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/testcommon.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/testcommon.js
deleted file mode 100644
index cce78e9c..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/testcommon.js
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-
-/*
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
-*/
-
-"use strict";
-
-var HTML5_ELEMENT_NAMES = [
-    'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio',
-    'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button',
-    'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'command',
-    'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt',
-    'em', 'embed',
-    'fieldset', 'figcaption', 'figure', 'footer', 'form',
-    'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr',
-    'html',
-    'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen',
-    'label', 'legend', 'li', 'link',
-    'map', 'mark', 'menu', 'meta', 'meter',
-    'nav', 'noscript',
-    'object', 'ol', 'optgroup', 'option', 'output',
-    'p', 'param', 'pre', 'progress',
-    'q',
-    'rp', 'rt', 'ruby',
-    's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span',
-    'strong', 'style', 'sub',
-    'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time',
-    'title', 'tr', 'track',
-    'u', 'ul',
-    'var', 'video',
-    'wbr'
-];
-
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#form-associated-element
-var HTML5_FORM_ASSOCIATED_ELEMENTS = ['button', 'fieldset', 'input', 'keygen', 'label',
-                                      'object', 'output', 'select', 'textarea'];
-
-// Whether to work around vendor prefixes.
-var USE_VENDOR_SPECIFIC_WORKAROUND = true;
-
-function activateVendorSpecificWorkaround() {
-    if (Element.prototype.webkitCreateShadowRoot &&
-        !Element.prototype.createShadowRoot) {
-        Element.prototype.createShadowRoot =
-            Element.prototype.webkitCreateShadowRoot;
-
-        Object.defineProperty(Element.prototype, 'pseudo', {
-            get: function () { return this.webkitPseudo; },
-            set: function (value) { return this.webkitPseudo = value; }
-        });
-
-        Object.defineProperty(Element.prototype, 'shadowRoot', {
-            get: function () { return this.webkitShadowRoot; }
-        });
-    }
-}
-
-if (USE_VENDOR_SPECIFIC_WORKAROUND)
-    activateVendorSpecificWorkaround();
-
-// ----------------------------------------------------------------------------
-// Deprecated: The code below is preserved only for the existing tests that are
-// using it. Now vendor prefixes are handled in a way that does not require
-// manual intervention. New tests should just use unprefixed APIs and you
-// are all set.
-//
-// These functions will eventually be removed when no tests use them.
-
-function ShadowDomNotSupportedError() {
-    this.message = "Shadow DOM is not supported";
-}
-
-// To allow using of both prefixed and non-prefixed API we do
-// the following hook
-function addPrefixed(element) {
-	if (element && !element.pseudo) {
-		Object.defineProperty(element, 'pseudo', {
-			  get: function () { return element.webkitPseudo; },
-			  set: function (value) { return element.webkitPseudo = value; }
-		});
-	}
-}
-
-function addDocumentPrefixed(d) {
-	if (d) {
-		if (d.body) {
-		    addPrefixed(d.body);
-		}
-		if (d.head) {
-		    addPrefixed(d.head);			
-		}
-		if (d.documentElement) {
-			addPrefixed(d.documentElement);
-		}
-		d.oldCreate = d.createElement;
-		d.createElement = function(tagName) {
-			var el = d.oldCreate(tagName);
-			addPrefixed(el);
-			return el;
-		};		
-	}	
-}
-
-
-function rethrowInternalErrors(e) {
-    if (e instanceof ShadowDomNotSupportedError) {
-        throw e;
-    }
-
-}
-
-function newDocument() {
-    var d = document.implementation.createDocument(
-        'http://www.w3.org/1999/xhtml', 'html');
-    //FIXME remove the call below when non-prefixed API is used
-    addDocumentPrefixed(d);
-    return d;        
-}
-
-function newHTMLDocument() {
-	var d = document.implementation.createHTMLDocument('Test Document');
-    //FIXME remove the call below when non-prefixed API is used
-    addDocumentPrefixed(d);
-    return d;
-}
-
-function newIFrame(ctx, src) {
-    if (typeof(ctx) == 'undefined' || typeof (ctx.iframes) != 'object') {
-        assert_unreached('Illegal context object in newIFrame');
-    }
-
-    var iframe = document.createElement('iframe');
-    if (!ctx.debug) {
-        iframe.style.display = 'none';
-    }
-    if (typeof(src) != 'undefined') {
-        iframe.src = src;
-    }
-    document.body.appendChild(iframe);
-    ctx.iframes.push(iframe);
-
-    assert_true(typeof(iframe.contentWindow) != 'undefined'
-        && typeof(iframe.contentWindow.document) != 'undefined'
-        && iframe.contentWindow.document != document, 'Failed to create new rendered document'
-    );
-    return iframe;
-}
-function newRenderedHTMLDocument(ctx) {
-    var frame = newIFrame(ctx);
-    var d = frame.contentWindow.document;
-    //FIXME remove the call below when non-prefixed API is used
-    addDocumentPrefixed(d);
-    return d;    
-}
-
-// End deprecated.
-// ----------------------------------------------------------------------------
-
-function newContext() {
-    return {iframes:[]};
-}
-
-function cleanContext(ctx) {
-    if (!ctx.debug) {
-        ctx.iframes.forEach(function (e) {
-            e.parentNode.removeChild(e);
-        });
-    }
-}
-
-function unit(f) {
-    return function () {
-        var ctx = newContext();
-        try {
-            f(ctx);
-        } finally {
-            cleanContext(ctx);
-        }
-    }
-}
-
-function step_unit(f, ctx, t) {
-    return function () {
-        var done = false;
-        try {
-            f();
-            done = true;
-        } finally {
-            if (done) {
-                t.done();
-            }
-            cleanContext(ctx);
-        }
-    }
-}
-
-function assert_nodelist_contents_equal_noorder(actual, expected, message) {
-    assert_equals(actual.length, expected.length, message);
-    var used = [];
-    for (var i = 0; i < expected.length; i++) {
-        used.push(false);
-    }
-    for (i = 0; i < expected.length; i++) {
-        var found = false;
-        for (var j = 0; j < actual.length; j++) {
-            if (used[j] == false && expected[i] == actual[j]) {
-                used[j] = true;
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
-            assert_unreached(message + ". Fail reason:  element not found: " + expected[i]);
-        }
-    }
-}
-
-
-//Example taken from http://www.w3.org/TR/shadow-dom/#event-retargeting-example
-function createTestMediaPlayer(d) {
-    d.body.innerHTML = '' +
-	'<div id="player">' +
-		'<input type="checkbox" id="outside-control">' +
-		'<div id="player-shadow-host">' +
-	    '</div>' +
-	'</div>';
-
-	var playerShadowRoot = d.querySelector('#player-shadow-host').createShadowRoot();
-	playerShadowRoot.innerHTML = '' +
-		'<div id="controls">' +
-			'<button class="play-button">PLAY</button>' +
-			'<div tabindex="0" id="timeline">' +
-				'<div id="timeline-shadow-host">' +
-				'</div>' +
-			'</div>' +
-		    '<div class="volume-slider-container" id="volume-slider-container">' +
-		        '<div tabindex="0" class="volume-slider" id="volume-slider">' +
-		            '<div id="volume-shadow-host">' +
-		            '</div>' +
-		        '</div>' +
-		    '</div>' +
-		'</div>';
-
-	var timeLineShadowRoot = playerShadowRoot.querySelector('#timeline-shadow-host').createShadowRoot();
-	timeLineShadowRoot.innerHTML =  '<div class="slider-thumb" id="timeline-slider-thumb"></div>';
-
-	var volumeShadowRoot = playerShadowRoot.querySelector('#volume-shadow-host').createShadowRoot();
-	volumeShadowRoot.innerHTML = '<div class="slider-thumb" id="volume-slider-thumb"></div>';
-
-	return {
-		'playerShadowRoot': playerShadowRoot,
-		'timeLineShadowRoot': timeLineShadowRoot,
-		'volumeShadowRoot': volumeShadowRoot
-		};
-}
-
-//FIXME This call of initKeyboardEvent works for WebKit-only.
-//See https://bugs.webkit.org/show_bug.cgi?id=16735
-// and https://bugs.webkit.org/show_bug.cgi?id=13368. Add check for browser here
-function fireKeyboardEvent(doc, element, key) {
-    var event = doc.createEvent('KeyboardEvent');
-    event.initKeyboardEvent("keydown", true, true, doc.defaultView, key, 0, false, false, false, false);
-    element.dispatchEvent(event);
-}
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html
index a8fcf53f..e8be26c 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-001.html
@@ -16,30 +16,31 @@
 <meta name="assert" content="User Interaction: each shadow root must also have an activeElement property to store the value of the focused element in the shadow tree.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp = d.createElement('input');
-	inp.setAttribute('type', 'text');
-	inp.setAttribute('id', 'inpId');
-	inp.setAttribute('value', 'Some text');
-	s.appendChild(inp);
+    var inp = d.createElement('input');
+    inp.setAttribute('type', 'text');
+    inp.setAttribute('id', 'inpId');
+    inp.setAttribute('value', 'Some text');
+    s.appendChild(inp);
 
-	inp.focus();
+    inp.focus();
 
     assert_equals(s.activeElement.tagName, 'INPUT', 'Point 1:activeElement property of shadow root ' +
-    		'must return the value of the focused element in the shadow tree');
+            'must return the value of the focused element in the shadow tree');
     assert_equals(s.activeElement.getAttribute('id'), 'inpId', 'Point 2:activeElement property of shadow root ' +
-    	'must return the value of the focused element in the shadow tree');
+        'must return the value of the focused element in the shadow tree');
 
 }), 'A_07_03_01_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html
index fcabc27..69330ed1 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/active-element/test-002.html
@@ -16,31 +16,32 @@
 <meta name="assert" content="User Interaction: Document's activeElement property must be adjusted">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	host.setAttribute('id', 'shRoot');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    host.setAttribute('id', 'shRoot');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp = d.createElement('input');
-	inp.setAttribute('type', 'text');
-	inp.setAttribute('id', 'inpId');
-	inp.setAttribute('value', 'Some text');
-	s.appendChild(inp);
+    var inp = d.createElement('input');
+    inp.setAttribute('type', 'text');
+    inp.setAttribute('id', 'inpId');
+    inp.setAttribute('value', 'Some text');
+    s.appendChild(inp);
 
-	inp.focus();
+    inp.focus();
 
     assert_equals(d.activeElement.tagName, 'DIV', 'Point 1: document\'s activeElement property  ' +
-    		'must return adjusted the value of the focused element in the shadow tree');
+            'must return adjusted the value of the focused element in the shadow tree');
     assert_equals(d.activeElement.getAttribute('id'), 'shRoot', 'Point 2: document\'s activeElement property  ' +
-    		'must return adjusted the value of the focused element in the shadow tree');
+            'must return adjusted the value of the focused element in the shadow tree');
 
 }), 'A_07_03_02_T01');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html
index 1ca864e..22181763 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/editing/inheritance-of-content-editable-001.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="User Interaction: Shadow trees must not be propagated contentEditable attribute from shadow host">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -28,7 +29,7 @@
     host.contentEditable = "true";
     d.body.appendChild(host);
 
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     assert_equals(host.contentEditable, "true");
     assert_equals(s.contentEditable, undefined);
@@ -41,7 +42,7 @@
     host.contentEditable = "false";
     d.body.appendChild(host);
 
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     assert_equals(host.contentEditable, 'false');
     assert_equals(s.contentEditable, undefined);
@@ -54,7 +55,7 @@
     d.body.appendChild(host);
     d.body.contentEditable = "true";
 
-    var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
     assert_equals(host.contentEditable, 'inherit');
     assert_equals(s.contentEditable, undefined);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html
index 2724fd5..0f7198a1 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -25,60 +26,60 @@
 
 A_07_02_01_T01.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	chb1.setAttribute('id', 'chb1');
-	chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-	}), false);
-	d.body.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    chb1.setAttribute('id', 'chb1');
+    chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+    }), false);
+    d.body.appendChild(chb1);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-	}), false);
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+    }), false);
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-	}), false);
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+    }), false);
+    s.appendChild(inp2);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
-	}), false);
-	d.body.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
+    }), false);
+    d.body.appendChild(chb2);
 
-	chb1.focus();
+    chb1.focus();
 
-	//simulate TAB clicks
-	fireKeyboardEvent(d, chb1, 'U+0009');
+    //simulate TAB clicks
+    fireKeyboardEvent(d, chb1, 'U+0009');
 
-	fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
 
-	fireKeyboardEvent(d, inp2, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
 
-	fireKeyboardEvent(d, chb2, 'U+0009');
+    fireKeyboardEvent(d, chb2, 'U+0009');
 
-	A_07_02_01_T01.done();
+    A_07_02_01_T01.done();
 }));
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html
index 151c0501..aa325f5 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered  with the exception of any elements, distributed its insertion points, and is called shadow DOM navigation order.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -26,99 +27,99 @@
 
 A_07_02_02_T01.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var expectations = [];
+    var expectations = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    d.body.appendChild(host);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	chb1.setAttribute('id', 'chb1');
-	chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-		assert_true(false, 'Element shouldn\'t be rendered');
-	}), false);
-	host.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    chb1.setAttribute('id', 'chb1');
+    chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+        assert_true(false, 'Element shouldn\'t be rendered');
+    }), false);
+    host.appendChild(chb1);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	chb2.setAttribute('class', 'shadow');
-	chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-		expectations[1] = true;
-	}), false);
-	expectations[1] = false;
-	host.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    chb2.setAttribute('slot', 'shadow');
+    chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+        expectations[1] = true;
+    }), false);
+    expectations[1] = false;
+    host.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	chb3.setAttribute('class', 'shadow');
-	chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-		expectations[2] = true;
-	}), false);
-	expectations[2] = false;
-	host.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    chb3.setAttribute('slot', 'shadow');
+    chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+        expectations[2] = true;
+    }), false);
+    expectations[2] = false;
+    host.appendChild(chb3);
 
-	var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
-	var div = d.createElement('div');
-	div.innerHTML = '<content select=".shadow"></content>';
-	s.appendChild(div);
+    var div = d.createElement('div');
+    div.innerHTML = '<slot name="shadow"></slot>';
+    s.appendChild(div);
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-		expectations[3] = false;
-	}), false);
-	expectations[3] = true;
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+        expectations[3] = false;
+    }), false);
+    expectations[3] = true;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-		expectations[4] = false;
-	}), false);
-	expectations[4] = true;
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+        expectations[4] = false;
+    }), false);
+    expectations[4] = true;
+    s.appendChild(inp2);
 
-	var chb4 = d.createElement('input');
-	chb4.setAttribute('type', 'checkbox');
-	chb4.setAttribute('id', 'chb4');
-	chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
-		expectations[5] = true;
-	}), false);
-	expectations[5] = false;
-	d.body.appendChild(chb4);
+    var chb4 = d.createElement('input');
+    chb4.setAttribute('type', 'checkbox');
+    chb4.setAttribute('id', 'chb4');
+    chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
+        expectations[5] = true;
+    }), false);
+    expectations[5] = false;
+    d.body.appendChild(chb4);
 
-	chb2.focus();
+    chb2.focus();
 
-	//simulate TAB clicks
-	fireKeyboardEvent(d, chb2, 'U+0009');
+    //simulate TAB clicks
+    fireKeyboardEvent(d, chb2, 'U+0009');
 
-	fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
 
-	fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
 
-	fireKeyboardEvent(d, inp2, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
 
-	fireKeyboardEvent(d, chb4, 'U+0009');
+    fireKeyboardEvent(d, chb4, 'U+0009');
 
-	for (var i = 1; i < expectations.length; i++) {
-		if (!expectations[i]) {
-			assert_true(false, 'Point ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < expectations.length; i++) {
+        if (!expectations[i]) {
+            assert_true(false, 'Point ' + i + ' event listener was not invoked');
+        }
+    }
 
     A_07_02_02_T01.done();
 }));
@@ -127,108 +128,108 @@
 
 A_07_02_02_T02.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var expectations = [];
+    var expectations = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var chb0 = d.createElement('input');
-	chb0.setAttribute('type', 'checkbox');
-	chb0.setAttribute('id', 'chb0');
+    var chb0 = d.createElement('input');
+    chb0.setAttribute('type', 'checkbox');
+    chb0.setAttribute('id', 'chb0');
         d.body.appendChild(chb0);
 
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    d.body.appendChild(host);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	chb1.setAttribute('id', 'chb1');
-	chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-		assert_true(false, 'Element shouldn\'t be rendered');
-	}), false);
-	host.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    chb1.setAttribute('id', 'chb1');
+    chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+        assert_true(false, 'Element shouldn\'t be rendered');
+    }), false);
+    host.appendChild(chb1);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	chb2.setAttribute('class', 'shadow');
-	chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-		expectations[1] = true;
-	}), false);
-	expectations[1] = false;
-	host.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    chb2.setAttribute('slot', 'shadow');
+    chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+        expectations[1] = true;
+    }), false);
+    expectations[1] = false;
+    host.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	chb3.setAttribute('class', 'shadow');
-	chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
-		expectations[2] = true;
-	}), false);
-	expectations[2] = false;
-	host.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    chb3.setAttribute('slot', 'shadow');
+    chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
+        expectations[2] = true;
+    }), false);
+    expectations[2] = false;
+    host.appendChild(chb3);
 
-	var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
-	var div = d.createElement('div');
-	div.innerHTML = '<content select=".shadow"></content>';
-	s.appendChild(div);
+    var div = d.createElement('div');
+    div.innerHTML = '<slot name="shadow"></slot>';
+    s.appendChild(div);
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
 
-		expectations[3] = true;
-	}), false);
-	expectations[3] = false;
-	s.appendChild(inp1);
+        expectations[3] = true;
+    }), false);
+    expectations[3] = false;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-		expectations[4] = true;
-	}), false);
-	expectations[4] = false;
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+        expectations[4] = true;
+    }), false);
+    expectations[4] = false;
+    s.appendChild(inp2);
 
-	var chb4 = d.createElement('input');
-	chb4.setAttribute('type', 'checkbox');
-	chb4.setAttribute('id', 'chb4');
-	chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
-		assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
-		expectations[5] = true;
-	}), false);
-	expectations[5] = false;
-	d.body.appendChild(chb4);
+    var chb4 = d.createElement('input');
+    chb4.setAttribute('type', 'checkbox');
+    chb4.setAttribute('id', 'chb4');
+    chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+        assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
+        expectations[5] = true;
+    }), false);
+    expectations[5] = false;
+    d.body.appendChild(chb4);
 
-	chb0.focus();
+    chb0.focus();
 
-	//simulate TAB clicks
-	fireKeyboardEvent(d, inp1, 'U+0009');
+    //simulate TAB clicks
+    fireKeyboardEvent(d, inp1, 'U+0009');
 
-	fireKeyboardEvent(d, inp2, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
 
-	fireKeyboardEvent(d, chb2, 'U+0009');
+    fireKeyboardEvent(d, chb2, 'U+0009');
 
-	fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
 
-	fireKeyboardEvent(d, chb4, 'U+0009');
+    fireKeyboardEvent(d, chb4, 'U+0009');
 
-	for (var i = 1; i < expectations.length; i++) {
-		if (!expectations[i]) {
-			assert_true(false, 'Point ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < expectations.length; i++) {
+        if (!expectations[i]) {
+            assert_true(false, 'Point ' + i + ' event listener was not invoked');
+        }
+    }
 
     A_07_02_02_T02.done();
 }));
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html
index 3efa221..0563cae 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order in place of the shadow host as if the shadow host were assigned the value of auto for determining its position and shadow host is not focusable">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -25,99 +26,99 @@
 
 A_07_02_03_T01.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var invoked = [];
+    var invoked = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	// TODO according CSS3 nav-index is a replacement for tabindex
-	//chb1.setAttribute('nav-index', '4');
-	chb1.setAttribute('tabindex', '4');
-	chb1.setAttribute('id', 'chb1');
-	chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 1: wrong focus navigation order');
-		invoked[1] = true;
-	}), false);
-	invoked[1] = false;
-	d.body.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    // TODO according CSS3 nav-index is a replacement for tabindex
+    //chb1.setAttribute('nav-index', '4');
+    chb1.setAttribute('tabindex', '4');
+    chb1.setAttribute('id', 'chb1');
+    chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 1: wrong focus navigation order');
+        invoked[1] = true;
+    }), false);
+    invoked[1] = false;
+    d.body.appendChild(chb1);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	//inp1.setAttribute('nav-index', '3');
-	inp1.setAttribute('tabindex', '3');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-		assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
-		invoked[2] = true;
-	}), false);
-	invoked[2] = false;
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    //inp1.setAttribute('nav-index', '3');
+    inp1.setAttribute('tabindex', '3');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+        assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
+        invoked[2] = true;
+    }), false);
+    invoked[2] = false;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	//inp2.setAttribute('nav-index', '2');
-	inp2.setAttribute('tabindex', '2');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 3: wrong focus navigation order');
-		invoked[3] = true;
-	}), false);
-	invoked[3] = false;
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    //inp2.setAttribute('nav-index', '2');
+    inp2.setAttribute('tabindex', '2');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 3: wrong focus navigation order');
+        invoked[3] = true;
+    }), false);
+    invoked[3] = false;
+    s.appendChild(inp2);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	//chb2.setAttribute('nav-index', '1');
-	chb2.setAttribute('tabindex', '1');
-	chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 4: wrong focus navigation order');
-		invoked[4] = true;
-	}), false);
-	invoked[4] = false;
-	d.body.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    //chb2.setAttribute('nav-index', '1');
+    chb2.setAttribute('tabindex', '1');
+    chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 4: wrong focus navigation order');
+        invoked[4] = true;
+    }), false);
+    invoked[4] = false;
+    d.body.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	//chb3.setAttribute('nav-index', '5');
-	chb3.setAttribute('tabindex', '5');
-	chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
-		invoked[5] = true;
-	}), false);
-	invoked[5] = false;
-	d.body.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    //chb3.setAttribute('nav-index', '5');
+    chb3.setAttribute('tabindex', '5');
+    chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
+        invoked[5] = true;
+    }), false);
+    invoked[5] = false;
+    d.body.appendChild(chb3);
 
-	chb2.focus();
+    chb2.focus();
 
-	//simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1
-	fireKeyboardEvent(d, chb2, 'U+0009');
+    //simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1
+    fireKeyboardEvent(d, chb2, 'U+0009');
 
-	fireKeyboardEvent(d, chb1, 'U+0009');
+    fireKeyboardEvent(d, chb1, 'U+0009');
 
-	fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
 
-	fireKeyboardEvent(d, inp2, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
 
-	fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
 
-	for (var i = 1; i < invoked.length; i++) {
-		if (!invoked[i]) {
-			assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < invoked.length; i++) {
+        if (!invoked[i]) {
+            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+        }
+    }
 
-	A_07_02_03_T01.done();
+    A_07_02_03_T01.done();
 }));
 
 // test nodes, distributed into insertion points
@@ -125,111 +126,111 @@
 
 A_07_02_03_T02.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var invoked = [];
+    var invoked = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    d.body.appendChild(host);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	chb1.setAttribute('id', 'chb1');
-	chb1.setAttribute('tabindex', '1');
-	chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-		invoked[1] = true;
-	}), false);
-	invoked[1] = false;
-	d.body.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    chb1.setAttribute('id', 'chb1');
+    chb1.setAttribute('tabindex', '1');
+    chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+        invoked[1] = true;
+    }), false);
+    invoked[1] = false;
+    d.body.appendChild(chb1);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	chb2.setAttribute('class', 'shadow');
-	chb2.setAttribute('tabindex', '3');
-	chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 2: wrong focus navigation order');
-		invoked[2] = true;
-	}), false);
-	invoked[2] = false;
-	host.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    chb2.setAttribute('slot', 'shadow');
+    chb2.setAttribute('tabindex', '3');
+    chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 2: wrong focus navigation order');
+        invoked[2] = true;
+    }), false);
+    invoked[2] = false;
+    host.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	chb3.setAttribute('class', 'shadow');
-	chb3.setAttribute('tabindex', '2');
-	chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
-		invoked[3] = true;
-	}), false);
-	invoked[3] = false;
-	host.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    chb3.setAttribute('slot', 'shadow');
+    chb3.setAttribute('tabindex', '2');
+    chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
+        invoked[3] = true;
+    }), false);
+    invoked[3] = false;
+    host.appendChild(chb3);
 
-	var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
-	var div = d.createElement('div');
-	div.innerHTML = '<content select=".shadow"></content>';
-	s.appendChild(div);
+    var div = d.createElement('div');
+    div.innerHTML = '<slot name="shadow"></slot>';
+    s.appendChild(div);
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.setAttribute('tabindex', '4');
-	inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-		assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
-		invoked[4] = true;
-	}), false);
-	invoked[4] = false;
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.setAttribute('tabindex', '4');
+    inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+        assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
+        invoked[4] = true;
+    }), false);
+    invoked[4] = false;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.setAttribute('tabindex', '5');
-	inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-		assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
-		invoked[5] = true;
-	}), false);
-	invoked[5] = false;
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.setAttribute('tabindex', '5');
+    inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+        assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
+        invoked[5] = true;
+    }), false);
+    invoked[5] = false;
+    s.appendChild(inp2);
 
-	var chb4 = d.createElement('input');
-	chb4.setAttribute('type', 'checkbox');
-	chb4.setAttribute('id', 'chb4');
-	chb4.setAttribute('tabindex', '6');
-	chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 6: wrong focus navigation order');
-		invoked[6] = true;
-	}), false);
-	invoked[6] = false;
-	d.body.appendChild(chb4);
+    var chb4 = d.createElement('input');
+    chb4.setAttribute('type', 'checkbox');
+    chb4.setAttribute('id', 'chb4');
+    chb4.setAttribute('tabindex', '6');
+    chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 6: wrong focus navigation order');
+        invoked[6] = true;
+    }), false);
+    invoked[6] = false;
+    d.body.appendChild(chb4);
 
-	chb1.focus();
+    chb1.focus();
 
-	//simulate TAB clicks
-	//Expected order: chb1, chb3, chb2, chb4, inp1, inp2
-	fireKeyboardEvent(d, chb1, 'U+0009');
-	fireKeyboardEvent(d, chb3, 'U+0009');
-	fireKeyboardEvent(d, chb2, 'U+0009');
-	fireKeyboardEvent(d, chb4, 'U+0009');
-	fireKeyboardEvent(d, inp1, 'U+0009');
-	fireKeyboardEvent(d, inp2, 'U+0009');
+    //simulate TAB clicks
+    //Expected order: chb1, chb3, chb2, chb4, inp1, inp2
+    fireKeyboardEvent(d, chb1, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, chb2, 'U+0009');
+    fireKeyboardEvent(d, chb4, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
 
 
 
-	for (var i = 1; i < invoked.length; i++) {
-		if (!invoked[i]) {
-			assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < invoked.length; i++) {
+        if (!invoked[i]) {
+            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+        }
+    }
 
-	A_07_02_03_T02.done();
+    A_07_02_03_T02.done();
 }));
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html
index 3f95cbd..3048d2b 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html
@@ -16,7 +16,8 @@
 <meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order immediately after the shadow host, if the shadow host is focusable;">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
@@ -25,101 +26,101 @@
 
 A_07_02_04_T01.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var invoked = [];
+    var invoked = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	// TODO according CSS3 nav-index is a replacement for tabindex
-	//chb1.setAttribute('nav-index', '4');
-	chb1.setAttribute('tabindex', '1');
-	chb1.setAttribute('id', 'chb1');
-	chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-		invoked[1] = true;
-	}), false);
-	invoked[1] = false;
-	d.body.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    // TODO according CSS3 nav-index is a replacement for tabindex
+    //chb1.setAttribute('nav-index', '4');
+    chb1.setAttribute('tabindex', '1');
+    chb1.setAttribute('id', 'chb1');
+    chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+        invoked[1] = true;
+    }), false);
+    invoked[1] = false;
+    d.body.appendChild(chb1);
 
-	var host = d.createElement('div');
-	//make shadow host focusable
-	host.setAttribute('tabindex', '3');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    //make shadow host focusable
+    host.setAttribute('tabindex', '3');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	//inp1.setAttribute('nav-index', '3');
-	inp1.setAttribute('tabindex', '2');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
-		invoked[2] = true;
-	}), false);
-	invoked[2] = false;
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    //inp1.setAttribute('nav-index', '3');
+    inp1.setAttribute('tabindex', '2');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
+        invoked[2] = true;
+    }), false);
+    invoked[2] = false;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	//inp2.setAttribute('nav-index', '2');
-	inp2.setAttribute('tabindex', '1');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-		invoked[3] = true;
-	}), false);
-	invoked[3] = false;
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    //inp2.setAttribute('nav-index', '2');
+    inp2.setAttribute('tabindex', '1');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+        invoked[3] = true;
+    }), false);
+    invoked[3] = false;
+    s.appendChild(inp2);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	//chb2.setAttribute('nav-index', '1');
-	chb2.setAttribute('tabindex', '2');
-	chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 4: wrong focus navigation order');
-		invoked[4] = true;
-	}), false);
-	invoked[4] = false;
-	d.body.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    //chb2.setAttribute('nav-index', '1');
+    chb2.setAttribute('tabindex', '2');
+    chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 4: wrong focus navigation order');
+        invoked[4] = true;
+    }), false);
+    invoked[4] = false;
+    d.body.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	//chb3.setAttribute('nav-index', '5');
-	chb3.setAttribute('tabindex', '4');
-	chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
-		assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
-		invoked[5] = true;
-	}), false);
-	invoked[5] = false;
-	d.body.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    //chb3.setAttribute('nav-index', '5');
+    chb3.setAttribute('tabindex', '4');
+    chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+        assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
+        invoked[5] = true;
+    }), false);
+    invoked[5] = false;
+    d.body.appendChild(chb3);
 
-	chb1.focus();
+    chb1.focus();
 
-	//simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3
-	fireKeyboardEvent(d, chb1, 'U+0009');
+    //simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3
+    fireKeyboardEvent(d, chb1, 'U+0009');
 
-	fireKeyboardEvent(d, chb2, 'U+0009');
+    fireKeyboardEvent(d, chb2, 'U+0009');
 
-	fireKeyboardEvent(d, inp2, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
 
-	fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
 
-	fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
 
-	for (var i = 1; i < invoked.length; i++) {
-		if (!invoked[i]) {
-			assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < invoked.length; i++) {
+        if (!invoked[i]) {
+            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+        }
+    }
 
-	A_07_02_04_T01.done();
+    A_07_02_04_T01.done();
 }));
 
 
@@ -129,112 +130,112 @@
 
 A_07_02_04_T02.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var invoked = [];
+    var invoked = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	host.setAttribute('tabindex', '3');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    host.setAttribute('tabindex', '3');
+    d.body.appendChild(host);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	chb1.setAttribute('id', 'chb1');
-	chb1.setAttribute('tabindex', '1');
-	chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-		invoked[1] = true;
-	}), false);
-	invoked[1] = false;
-	d.body.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    chb1.setAttribute('id', 'chb1');
+    chb1.setAttribute('tabindex', '1');
+    chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+        invoked[1] = true;
+    }), false);
+    invoked[1] = false;
+    d.body.appendChild(chb1);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	chb2.setAttribute('class', 'shadow');
-	chb2.setAttribute('tabindex', '3');
-	chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-		assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
-		invoked[2] = true;
-	}), false);
-	invoked[2] = false;
-	host.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    chb2.setAttribute('slot', 'shadow');
+    chb2.setAttribute('tabindex', '3');
+    chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+        assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
+        invoked[2] = true;
+    }), false);
+    invoked[2] = false;
+    host.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	chb3.setAttribute('class', 'shadow');
-	chb3.setAttribute('tabindex', '2');
-	chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
-		invoked[3] = true;
-	}), false);
-	invoked[3] = false;
-	host.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    chb3.setAttribute('slot', 'shadow');
+    chb3.setAttribute('tabindex', '2');
+    chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
+        invoked[3] = true;
+    }), false);
+    invoked[3] = false;
+    host.appendChild(chb3);
 
-	var s = host.createShadowRoot();
+    var s = host.attachShadow({mode: 'open'});
 
-	var div = d.createElement('div');
-	div.innerHTML = '<content select=".shadow"></content>';
-	s.appendChild(div);
+    var div = d.createElement('div');
+    div.innerHTML = '<slot name="shadow"></slot>';
+    s.appendChild(div);
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.setAttribute('tabindex', '4');
-	inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
-		invoked[4] = true;
-	}), false);
-	invoked[4] = false;
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.setAttribute('tabindex', '4');
+    inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
+        invoked[4] = true;
+    }), false);
+    invoked[4] = false;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.setAttribute('tabindex', '4');
-	inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-		assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
-		invoked[5] = true;
-	}), false);
-	invoked[5] = false;
-	d.body.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.setAttribute('tabindex', '4');
+    inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+        assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
+        invoked[5] = true;
+    }), false);
+    invoked[5] = false;
+    d.body.appendChild(inp2);
 
-	var chb4 = d.createElement('input');
-	chb4.setAttribute('type', 'checkbox');
-	chb4.setAttribute('id', 'chb4');
-	chb4.setAttribute('tabindex', '2');
-	chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 6: wrong focus navigation order');
-		invoked[6] = true;
-	}), false);
-	invoked[6] = false;
-	d.body.appendChild(chb4);
+    var chb4 = d.createElement('input');
+    chb4.setAttribute('type', 'checkbox');
+    chb4.setAttribute('id', 'chb4');
+    chb4.setAttribute('tabindex', '2');
+    chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 6: wrong focus navigation order');
+        invoked[6] = true;
+    }), false);
+    invoked[6] = false;
+    d.body.appendChild(chb4);
 
-	chb1.focus();
+    chb1.focus();
 
-	//simulate TAB clicks
-	//Expected order: chb1, chb3, chb4, chb2, inp1, inp2
-	fireKeyboardEvent(d, chb1, 'U+0009');
-	fireKeyboardEvent(d, chb3, 'U+0009');
-	fireKeyboardEvent(d, chb4, 'U+0009');
-	fireKeyboardEvent(d, chb2, 'U+0009');
-	fireKeyboardEvent(d, inp1, 'U+0009');
-	fireKeyboardEvent(d, inp2, 'U+0009');
+    //simulate TAB clicks
+    //Expected order: chb1, chb3, chb4, chb2, inp1, inp2
+    fireKeyboardEvent(d, chb1, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, chb4, 'U+0009');
+    fireKeyboardEvent(d, chb2, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
 
 
 
-	for (var i = 1; i < invoked.length; i++) {
-		if (!invoked[i]) {
-			assert_true(false, 'Point ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < invoked.length; i++) {
+        if (!invoked[i]) {
+            assert_true(false, 'Point ' + i + ' event listener was not invoked');
+        }
+    }
 
-	A_07_02_04_T02.done();
+    A_07_02_04_T02.done();
 }));
 
 
@@ -244,90 +245,90 @@
 
 A_07_02_04_T03.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var invoked = [];
+    var invoked = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	chb1.setAttribute('tabindex', '3');
-	chb1.setAttribute('id', 'chb1');
-	chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-		assert_equals(counter++, 4, 'Point 1: wrong focus navigation order');
-		invoked[1] = true;
-	}), false);
-	invoked[1] = false;
-	d.body.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    chb1.setAttribute('tabindex', '3');
+    chb1.setAttribute('id', 'chb1');
+    chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+        assert_equals(counter++, 4, 'Point 1: wrong focus navigation order');
+        invoked[1] = true;
+    }), false);
+    invoked[1] = false;
+    d.body.appendChild(chb1);
 
-	var host = d.createElement('div');
-	host.setAttribute('tabindex', '1');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    host.setAttribute('tabindex', '1');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	inp1.setAttribute('tabindex', '2');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
-		invoked[2] = true;
-	}), false);
-	invoked[2] = false;
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    inp1.setAttribute('tabindex', '2');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+        invoked[2] = true;
+    }), false);
+    invoked[2] = false;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	inp2.setAttribute('tabindex', '1');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 3: wrong focus navigation order');
-		invoked[3] = true;
-	}), false);
-	invoked[3] = false;
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    inp2.setAttribute('tabindex', '1');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 3: wrong focus navigation order');
+        invoked[3] = true;
+    }), false);
+    invoked[3] = false;
+    s.appendChild(inp2);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	chb2.setAttribute('tabindex', '3');
-	chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 4: wrong focus navigation order');
-		invoked[4] = true;
-	}), false);
-	invoked[4] = false;
-	s.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    chb2.setAttribute('tabindex', '3');
+    chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 4: wrong focus navigation order');
+        invoked[4] = true;
+    }), false);
+    invoked[4] = false;
+    s.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	chb3.setAttribute('tabindex', '2');
-	chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 5: wrong focus navigation order');
-		invoked[5] = true;
-	}), false);
-	invoked[5] = false;
-	d.body.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    chb3.setAttribute('tabindex', '2');
+    chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 5: wrong focus navigation order');
+        invoked[5] = true;
+    }), false);
+    invoked[5] = false;
+    d.body.appendChild(chb3);
 
-	host.focus();
+    host.focus();
 
-	//simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
-	fireKeyboardEvent(d, inp2, 'U+0009');
-	fireKeyboardEvent(d, inp1, 'U+0009');
-	fireKeyboardEvent(d, chb2, 'U+0009');
-	fireKeyboardEvent(d, chb3, 'U+0009');
-	fireKeyboardEvent(d, chb1, 'U+0009');
+    //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
+    fireKeyboardEvent(d, inp2, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, chb2, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, chb1, 'U+0009');
 
-	for (var i = 1; i < invoked.length; i++) {
-		if (!invoked[i]) {
-			assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < invoked.length; i++) {
+        if (!invoked[i]) {
+            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+        }
+    }
 
-	A_07_02_04_T03.done();
+    A_07_02_04_T03.done();
 }));
 
 
@@ -336,90 +337,90 @@
 
 A_07_02_04_T04.step(unit(function (ctx) {
 
-	var counter = 0;
+    var counter = 0;
 
-	var invoked = [];
+    var invoked = [];
 
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var chb1 = d.createElement('input');
-	chb1.setAttribute('type', 'checkbox');
-	chb1.setAttribute('tabindex', '1');
-	chb1.setAttribute('id', 'chb1');
-	chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-		assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
-		invoked[1] = true;
-	}), false);
-	invoked[1] = false;
-	d.body.appendChild(chb1);
+    var chb1 = d.createElement('input');
+    chb1.setAttribute('type', 'checkbox');
+    chb1.setAttribute('tabindex', '1');
+    chb1.setAttribute('id', 'chb1');
+    chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+        assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+        invoked[1] = true;
+    }), false);
+    invoked[1] = false;
+    d.body.appendChild(chb1);
 
-	var host = d.createElement('div');
-	host.setAttribute('tabindex', '3');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    host.setAttribute('tabindex', '3');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var inp1 = d.createElement('input');
-	inp1.setAttribute('type', 'text');
-	inp1.setAttribute('id', 'shInp1');
-	inp1.setAttribute('tabindex', '2');
-	inp1.setAttribute('value', 'Input 1');
-	inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-		assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
-		invoked[2] = true;
-	}), false);
-	invoked[2] = false;
-	s.appendChild(inp1);
+    var inp1 = d.createElement('input');
+    inp1.setAttribute('type', 'text');
+    inp1.setAttribute('id', 'shInp1');
+    inp1.setAttribute('tabindex', '2');
+    inp1.setAttribute('value', 'Input 1');
+    inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+        assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
+        invoked[2] = true;
+    }), false);
+    invoked[2] = false;
+    s.appendChild(inp1);
 
-	var inp2 = d.createElement('input');
-	inp2.setAttribute('type', 'text');
-	inp2.setAttribute('id', 'shInp2');
-	inp2.setAttribute('tabindex', '1');
-	inp2.setAttribute('value', 'Input 2');
-	inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-		assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
-		invoked[3] = true;
-	}), false);
-	invoked[3] = false;
-	s.appendChild(inp2);
+    var inp2 = d.createElement('input');
+    inp2.setAttribute('type', 'text');
+    inp2.setAttribute('id', 'shInp2');
+    inp2.setAttribute('tabindex', '1');
+    inp2.setAttribute('value', 'Input 2');
+    inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+        assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+        invoked[3] = true;
+    }), false);
+    invoked[3] = false;
+    s.appendChild(inp2);
 
-	var chb2 = d.createElement('input');
-	chb2.setAttribute('type', 'checkbox');
-	chb2.setAttribute('id', 'chb2');
-	chb2.setAttribute('tabindex', '3');
-	chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-		assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
-		invoked[4] = true;
-	}), false);
-	invoked[4] = false;
-	s.appendChild(chb2);
+    var chb2 = d.createElement('input');
+    chb2.setAttribute('type', 'checkbox');
+    chb2.setAttribute('id', 'chb2');
+    chb2.setAttribute('tabindex', '3');
+    chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+        assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
+        invoked[4] = true;
+    }), false);
+    invoked[4] = false;
+    s.appendChild(chb2);
 
-	var chb3 = d.createElement('input');
-	chb3.setAttribute('type', 'checkbox');
-	chb3.setAttribute('id', 'chb3');
-	chb3.setAttribute('tabindex', '2');
-	chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
-		assert_equals(counter++, 1, 'Point 5: wrong focus navigation order');
-		invoked[5] = true;
-	}), false);
-	invoked[5] = false;
-	d.body.appendChild(chb3);
+    var chb3 = d.createElement('input');
+    chb3.setAttribute('type', 'checkbox');
+    chb3.setAttribute('id', 'chb3');
+    chb3.setAttribute('tabindex', '2');
+    chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+        assert_equals(counter++, 1, 'Point 5: wrong focus navigation order');
+        invoked[5] = true;
+    }), false);
+    invoked[5] = false;
+    d.body.appendChild(chb3);
 
-	chb1.focus();
+    chb1.focus();
 
-	//simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
-	fireKeyboardEvent(d, chb1, 'U+0009');
-	fireKeyboardEvent(d, chb3, 'U+0009');
-	fireKeyboardEvent(d, inp2, 'U+0009');
-	fireKeyboardEvent(d, inp1, 'U+0009');
-	fireKeyboardEvent(d, chb2, 'U+0009');
+    //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
+    fireKeyboardEvent(d, chb1, 'U+0009');
+    fireKeyboardEvent(d, chb3, 'U+0009');
+    fireKeyboardEvent(d, inp2, 'U+0009');
+    fireKeyboardEvent(d, inp1, 'U+0009');
+    fireKeyboardEvent(d, chb2, 'U+0009');
 
-	for (var i = 1; i < invoked.length; i++) {
-		if (!invoked[i]) {
-			assert_true(false, 'Piont ' + i + ' event listener was not invoked');
-		}
-	}
+    for (var i = 1; i < invoked.length; i++) {
+        if (!invoked[i]) {
+            assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+        }
+    }
 
-	A_07_02_04_T04.done();
+    A_07_02_04_T04.done();
 }));
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html
index 50fe650..88c479b 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-001.html
@@ -16,62 +16,64 @@
 <meta name="assert" content="User Interaction: Selection, returned by the window.getSelection() method must never return a selection within a shadow tree">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var span = d.createElement('span');
-	span.innerHTML = 'Some text';
-	s.appendChild(span);
+    var span = d.createElement('span');
+    span.innerHTML = 'Some text';
+    s.appendChild(span);
 
-	var range = d.createRange();
-	range.setStart(span.firstChild, 0);
-	range.setEnd(span.firstChild, 3);
+    var range = d.createRange();
+    range.setStart(span.firstChild, 0);
+    range.setEnd(span.firstChild, 3);
 
-	var selection = window.getSelection();
+    var selection = window.getSelection();
     selection.removeAllRanges();
     selection.addRange(range);
 
     var sl = window.getSelection();
     assert_equals(sl.toString(), '', 'window.getSelection() method must never return a selection ' +
-    		'within a shadow tree');
+            'within a shadow tree');
 
 }), 'A_07_07_01_T01');
 
 
 // test distributed nodes
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    d.body.appendChild(host);
 
-	var span = d.createElement('span');
-	span.innerHTML = 'Some text';
-	host.appendChild(span);
+    var span = d.createElement('span');
+    span.innerHTML = 'Some text';
+    span.setAttribute('slot', 'span');
+    host.appendChild(span);
 
-	var s = host.createShadowRoot();
-	s.innerHTML = '<content select="span"></content>';
+    var s = host.attachShadow({mode: 'open'});
+    s.innerHTML = '<slot name="span"></slot>';
 
-	var range = d.createRange();
-	range.setStart(span.firstChild, 0);
-	range.setEnd(span.firstChild, 3);
+    var range = d.createRange();
+    range.setStart(span.firstChild, 0);
+    range.setEnd(span.firstChild, 3);
 
-	var selection = window.getSelection();
+    var selection = window.getSelection();
     selection.removeAllRanges();
     selection.addRange(range);
 
     var sl = window.getSelection();
     assert_equals(sl.toString(), '', 'window.getSelection() method must never return a selection ' +
-    	'within a shadow tree');
+        'within a shadow tree');
 
 }), 'A_07_07_01_T02');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html
index 386de90..197cbdf 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html
@@ -16,62 +16,64 @@
 <meta name="assert" content="User Interaction: The getSelection() method of the shadow root object must return the current selection in this shadow tree.">
 <script src="../../../../../../resources/testharness.js"></script>
 <script src="../../../../../../resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
+<script src="../../../../html/resources/common.js"></script>
+<script src="../../../resources/shadow-dom-utils.js"></script>
 </head>
 <body>
 <div id="log"></div>
 <script>
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
-	var s = host.createShadowRoot();
+    var host = d.createElement('div');
+    d.body.appendChild(host);
+    var s = host.attachShadow({mode: 'open'});
 
-	var span = d.createElement('span');
-	span.innerHTML = 'Some text';
-	s.appendChild(span);
+    var span = d.createElement('span');
+    span.innerHTML = 'Some text';
+    s.appendChild(span);
 
-	var range = d.createRange();
-	range.setStart(span.firstChild, 0);
-	range.setEnd(span.firstChild, 3);
+    var range = d.createRange();
+    range.setStart(span.firstChild, 0);
+    range.setEnd(span.firstChild, 3);
 
-	var selection = window.getSelection();
+    var selection = d.defaultView.getSelection();
     selection.removeAllRanges();
     selection.addRange(range);
 
     var sl = s.getSelection();
     assert_equals(sl.toString(), 'Som', 'The getSelection() method of the shadow root object must return ' +
-    		'the current selection in this shadow tree');
+            'the current selection in this shadow tree');
 
 }), 'A_07_01_02_T01');
 
 
 //test distributed nodes
 test(unit(function (ctx) {
-	var d = newRenderedHTMLDocument(ctx);
+    var d = newRenderedHTMLDocument(ctx);
 
-	var host = d.createElement('div');
-	d.body.appendChild(host);
+    var host = d.createElement('div');
+    d.body.appendChild(host);
 
-	var span = d.createElement('span');
-	span.innerHTML = 'Some text';
-	host.appendChild(span);
+    var span = d.createElement('span');
+    span.innerHTML = 'Some text';
+    span.setAttribute('slot', 'slot');
+    host.appendChild(span);
 
-	var s = host.createShadowRoot();
-	s.innerHTML = '<content select="span"></content>';
+    var s = host.attachShadow({mode: 'open'});
+    s.innerHTML = '<slot name="slot"></slot>';
 
-	var range = d.createRange();
-	range.setStart(span.firstChild, 0);
-	range.setEnd(span.firstChild, 3);
+    var range = d.createRange();
+    range.setStart(span.firstChild, 0);
+    range.setEnd(span.firstChild, 3);
 
-	var selection = window.getSelection();
+    var selection = d.defaultView.getSelection();
     selection.removeAllRanges();
     selection.addRange(range);
 
     var sl = s.getSelection();
     assert_equals(sl.toString(), 'Som', 'The getSelection() method of the shadow root object must return ' +
-    		'the current selection in this shadow tree');
+            'the current selection in this shadow tree');
 
 }), 'A_07_07_02_T02');
 </script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/delay-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/delay-expected.txt
new file mode 100644
index 0000000..dc3e34b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/delay-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL set delay 100 anim.effect.getComputedTiming is not a function
+FAIL set delay -100 anim.effect.getComputedTiming is not a function
+FAIL Test adding a positive delay to an animation without a backwards fill makes it no longer active anim.effect.getComputedTiming is not a function
+FAIL Test seeking an animation by setting a negative delay anim.effect.getComputedTiming is not a function
+FAIL Test finishing an animation using a large negative delay anim.effect.getComputedTiming is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/delay.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/delay.html
new file mode 100644
index 0000000..25b2113
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/delay.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>delay tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-delay">
+<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
+  anim.effect.timing.delay = 100;
+  assert_equals(anim.effect.timing.delay, 100, 'set delay 100');
+  assert_equals(anim.effect.getComputedTiming().delay, 100,
+                  'getComputedTiming() after set delay 100');
+}, 'set delay 100');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
+  anim.effect.timing.delay = -100;
+  assert_equals(anim.effect.timing.delay, -100, 'set delay -100');
+  assert_equals(anim.effect.getComputedTiming().delay, -100,
+                'getComputedTiming() after set delay -100');
+}, 'set delay -100');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
+  anim.effect.timing.delay = 100;
+  assert_equals(anim.effect.getComputedTiming().progress, null);
+  assert_equals(anim.effect.getComputedTiming().currentIteration, null);
+}, 'Test adding a positive delay to an animation without a backwards fill ' +
+   'makes it no longer active');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] },
+                         { fill: 'both',
+                           duration: 100 });
+  anim.effect.timing.delay = -50;
+  assert_equals(anim.effect.getComputedTiming().progress, 0.5);
+}, 'Test seeking an animation by setting a negative delay');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] },
+                         { fill: 'both',
+                           duration: 100 });
+  anim.effect.timing.delay = -100;
+  assert_equals(anim.effect.getComputedTiming().progress, 1);
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
+}, 'Test finishing an animation using a large negative delay');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/direction.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/direction.html
new file mode 100644
index 0000000..83fb0fa0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/direction.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>direction tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-direction">
+<link rel="author" title="Ryo Kato" href="mailto:foobar094@gmail.com">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+
+  var directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
+  directions.forEach(function(direction) {
+    anim.effect.timing.direction = direction;
+    assert_equals(anim.effect.timing.direction, direction,
+                  'set direction to ' + direction);
+  });
+}, 'set direction to a valid keyword');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations-expected.txt
index c6b3964..01aa3b2 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations-expected.txt
@@ -1,6 +1,7 @@
 This is a testharness.js-based test.
 PASS when duration is changed 
 FAIL when endDelay is changed assert_equals: set negative endDelay so as endTime is less than currentTime expected 0 but got 1
+PASS when iterations is changed 
 FAIL when currentTime changed in duration:1000, delay: 500, endDelay: -500 assert_equals: set currentTime 1000 expected 0 but got 1
 FAIL when currentTime changed in duration:1000, delay: -500, endDelay: -500 assert_equals: when currentTime 0 expected 0 but got 1
 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html
index fb47ae8..bc3f69eb 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getAnimations.html
@@ -53,6 +53,19 @@
 
 test(function(t) {
   var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  anim.finish();
+  assert_equals(div.getAnimations().length, 0, 'animation finished');
+  anim.effect.timing.iterations = 10;
+  assert_equals(div.getAnimations()[0], anim, 'set iterations 10');
+  anim.effect.timing.iterations = 0;
+  assert_equals(div.getAnimations().length, 0, 'set iterations 0');
+  anim.effect.timing.iterations = Infinity;
+  assert_equals(div.getAnimations().length, 1, 'set iterations Infinity');
+}, 'when iterations is changed');
+
+test(function(t) {
+  var div = createDiv(t);
   var anim = div.animate({ opacity: [ 0, 1 ] },
                          { duration: 1000, delay: 500, endDelay: -500 });
   assert_equals(div.getAnimations()[0], anim, 'when currentTime 0');
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle-expected.txt
index 58d9dff6..cce72c5d 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle-expected.txt
@@ -1,8 +1,13 @@
 This is a testharness.js-based test.
 PASS changed duration immediately updates its computed styles 
+PASS changed iterations immediately updates its computed styles 
 PASS change currentTime when fill is none and endDelay is positive 
 PASS change currentTime when fill forwards and endDelay is positive 
 PASS change currentTime when fill none and endDelay is negative 
 FAIL change currentTime when fill forwards and endDelay is negative assert_equals: set currentTime same as endTime expected "0" but got "0.5"
+PASS change direction from "normal" to "reverse" 
+PASS change direction from "normal" to "alternate" 
+PASS change direction from "normal" to "alternate-reverse" 
+PASS change direction from "normal" to "reverse" 
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html
index 278392c..0eae355 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/getComputedStyle.html
@@ -26,6 +26,19 @@
 
 test(function(t) {
   var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 100000);
+  anim.finish();
+  assert_equals(getComputedStyle(div).opacity, '1', 'animation finished');
+  anim.effect.timing.iterations = 2;
+  assert_equals(getComputedStyle(div).opacity, '0', 'set 2 iterations');
+  anim.effect.timing.iterations = 0;
+  assert_equals(getComputedStyle(div).opacity, '1', 'set iterations 0');
+  anim.effect.timing.iterations = Infinity;
+  assert_equals(getComputedStyle(div).opacity, '0', 'set iterations Infinity');
+}, 'changed iterations immediately updates its computed styles');
+
+test(function(t) {
+  var div = createDiv(t);
   var anim = div.animate({ opacity: [ 1, 0 ] },
                          { duration: 10000, endDelay: 1000, fill: 'none' });
 
@@ -103,5 +116,61 @@
                 'set currentTime after endTime');
 }, 'change currentTime when fill forwards and endDelay is negative');
 
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] },
+                         { duration: 10000,
+                           direction: 'normal' });
+
+  anim.currentTime = 7000;
+  anim.effect.timing.direction = 'reverse';
+
+  assert_equals(getComputedStyle(div).opacity, '0.3',
+                'change direction from "normal" to "reverse"');
+}, 'change direction from "normal" to "reverse"');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] },
+                         { iterations: 2,
+                           duration: 10000,
+                           direction: 'normal' });
+
+  anim.currentTime = 17000;
+  anim.effect.timing.direction = 'alternate';
+
+  assert_equals(getComputedStyle(div).opacity, '0.3',
+                'change direction from "normal" to "alternate"');
+  }, 'change direction from "normal" to "alternate"');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] },
+                         { iterations: 2,
+                           duration: 10000,
+                           direction: 'normal' });
+
+  anim.currentTime = 17000;
+  anim.effect.timing.direction = 'alternate-reverse';
+
+  assert_equals(getComputedStyle(div).opacity, '0.7',
+                'change direction from "normal" to "alternate-reverse"');
+}, 'change direction from "normal" to "alternate-reverse"');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] },
+                         { fill: 'backwards',
+                           duration: 10000,
+                           direction: 'normal' });
+
+  // test for a flip of value at the currentTime = 0
+  anim.effect.timing.direction = 'reverse';
+
+  assert_equals(getComputedStyle(div).opacity, '1',
+                'change direction from "normal" to "reverse" ' +
+                'at the starting point');
+}, 'change direction from "normal" to "reverse"');
+
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/iterations-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/iterations-expected.txt
new file mode 100644
index 0000000..e7b8d19
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/iterations-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL set iterations 2 anim.effect.getComputedTiming is not a function
+FAIL set iterations Infinity anim.effect.getComputedTiming is not a function
+FAIL set negative iterations assert_throws: function "function () {
+    anim.effect.timing.iterations = -1;
+  }" did not throw
+FAIL set negative infinity iterations  assert_throws: function "function () {
+    anim.effect.timing.iterations = -Infini..." did not throw
+FAIL set NaN iterations assert_throws: function "function () {
+    anim.effect.timing.iterations = NaN;
+  }" did not throw
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/iterations.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/iterations.html
new file mode 100644
index 0000000..7e2eb05
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-effect-timing/iterations.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>iterations tests</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-iterations">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  anim.effect.timing.iterations = 2;
+  assert_equals(anim.effect.timing.iterations, 2, 'set duration 2');
+  assert_equals(anim.effect.getComputedTiming().iterations, 2,
+                       'getComputedTiming() after set iterations 2');
+}, 'set iterations 2');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  anim.effect.timing.iterations = Infinity;
+  assert_equals(anim.effect.timing.iterations, Infinity, 'set duration Infinity');
+  assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
+                       'getComputedTiming() after set iterations Infinity');
+}, 'set iterations Infinity');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  assert_throws({ name: 'TypeError' }, function() {
+    anim.effect.timing.iterations = -1;
+  });
+}, 'set negative iterations');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  assert_throws({ name: 'TypeError' }, function() {
+    anim.effect.timing.iterations = -Infinity;
+  });
+}, 'set negative infinity iterations ');
+
+test(function(t) {
+  var div = createDiv(t);
+  var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  assert_throws({ name: 'TypeError' }, function() {
+    anim.effect.timing.iterations = NaN;
+  });
+}, 'set NaN iterations');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-after-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-after-expected.txt
deleted file mode 100644
index 80d9de7b..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-after-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This is a testharness.js-based test.
-FAIL AnimationNode.after() does nothing if the node has no parent animation group. HierarchyRequestError is not thrown in call node.after(null) Animation is not defined
-FAIL AnimationNode.after() does nothing if the node has no parent animation group. No HierarchyRequestError is thrown if the node is inserted after itself Animation is not defined
-FAIL AnimationNode.after() does nothing if there is no parent animation group Animation is not defined
-FAIL HierarchyRequestError is thrown if node is inserted after itself AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if direct parent is inserted after the node AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if an inclusive ancestor is inserted after the node AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if an inclusive ancestor is inserted after the node. Test several arguments in after() call AnimationGroup is not defined
-FAIL AnimationNode.after() inserts nodes after this node AnimationGroup is not defined
-FAIL AnimationNode.after() inserts nodes after this node. Inserted node is on the same level in the tree AnimationGroup is not defined
-FAIL Test AnimationNode.after() inserts node after this node even if inserted node is already after this one AnimationGroup is not defined
-FAIL Test AnimationNode.after() inserts node after this node. The previous position of the inserted node is deeper in the tree than current node AnimationGroup is not defined
-FAIL Test AnimationNode.after() inserts node after this node. The previous position of the inserted node is shallower in the tree than current node, but not ancestor AnimationGroup is not defined
-FAIL Test AnimationNode.after() inserts several nodes after this node AnimationGroup is not defined
-FAIL Test AnimationNode.after() inserts several nodes after this node, duplicate nodes are ignored AnimationGroup is not defined
-FAIL Test AnimationNode.after() inserts several nodes after this node, check insertion order AnimationGroup is not defined
-FAIL Test AnimationNode.after() disassociates the inserted node from the player, if node is directly associated with a player AnimationGroup is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-after.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-after.html
deleted file mode 100644
index 3db07eee..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-after.html
+++ /dev/null
@@ -1,419 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationNode after() method tests</title>
-<meta name="assert" content="Inserts nodes after this animation node">
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-after">
-<link rel="help" href="http://w3c.github.io/web-animations/#insert-children">
-<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-// Test step 1. If there is no parent animation group, terminate these steps.
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        try {
-            node.after(null);
-        } catch(e) {
-            assert_unreached(type(node) + '.after(null) throws unexpected exception: ' + e);
-        }
-    });
-}, 'AnimationNode.after() does nothing if the node has no parent animation group. ' +
-    'HierarchyRequestError is not thrown in call node.after(null)');
-
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        try {
-            node.after(node);
-        } catch(e) {
-            assert_unreached(type(node) + '.after() throws unexpected exception: ' + e);
-        }
-    });
-}, 'AnimationNode.after() does nothing if the node has no parent animation group. ' +
-    'No HierarchyRequestError is thrown if the node is inserted after itself');
-
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    var node2 = newAnimation(createDiv(this));
-    nodes.forEach(function(node1) {
-        node1.after(node2);
-
-        assert_equals(node1.nextSibling, null, type(node1) + '.after() should do nothing ' +
-            'if the node has no parent animation group');
-        assert_equals(node2.previousSibling, null, type(node1) + '.after() should do nothing ' +
-            'if the node has no parent animation group');
-    });
-}, 'AnimationNode.after() does nothing if there is no parent animation group');
-
-// Test step 2. If any of the animation nodes in nodes is an inclusive ancestor of this animation node throw a HierarchyRequestError exception and terminate these steps.
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.after(node);
-            }, type(node) + '.after() should throw HierarchyRequestError ' +
-                'if inserting node after itself');
-            assert_equals(node.parent, parent, type(node) + '.after() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent.children, [node], type(node) + '.after() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if node is inserted after itself');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.after(parent);
-            }, type(node) + '.after() should throw HierarchyRequestError ' +
-                'if inserting node\'s parent');
-            assert_equals(node.parent, parent, type(node) + '.after() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent.children, [node], type(node) + '.after() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if direct parent is inserted after the node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent1 = new parentCtor([node]);
-            var parent2 = new parentCtor([parent1]);
-            var parent3 = new parentCtor([parent2]);
-            var parent4 = new parentCtor([parent3]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.after(parent3);
-            }, type(node) + '.after() should throw HierarchyRequestError ' +
-                'if inserting node\'s ancestor');
-            assert_equals(node.parent, parent1, type(node) + '.after() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent1.children, [node], type(node) + '.after() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-            assert_equals(parent3.parent, parent4, type(node) + '.after() should not change ' +
-                'parent attribute of inserted node before throwing HierarchyRequestError');
-            assert_array_equals(parent4.children, [parent3], type(node) + '.after() ' +
-                'should not change inserted node parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted after the node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([parent1]);
-            var parent3 = new parentCtor([parent2]);
-            var parent4 = new parentCtor([parent3]);
-            var parent5 = new ParentCtor([node3]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node1.after(node3, parent3);
-            }, type(node1) + '.after() should throw HierarchyRequestError ' +
-                'if inserting node\'s parent');
-            assert_equals(node1.parent, parent1, type(node1) + '.after() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent1.children, [node1, node2], type(node1) + '.after() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-            assert_equals(parent3.parent, parent4, type(node1) + '.after() should not change ' +
-                'parent attribute of inserted node before throwing HierarchyRequestError');
-            assert_array_equals(parent4.children, [parent3], type(node1) + '.after() ' +
-                'should not change inserted node parent children before throwing HierarchyRequestError');
-            assert_equals(node3.parent, parent5, type(node1) + '.after() should not change ' +
-                'parent attribute of inserted node before throwing HierarchyRequestError');
-            assert_array_equals(parent5.children, [node3], type(node1) + '.after() ' +
-                'should not change inserted node parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted after the node. ' +
-    'Test several arguments in after() call');
-
-// Test step 3 and 4.
-// 3. Let reference child be the next sibling of this animation node not in nodes.
-// 4. Insert nodes before reference child.
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-
-            node1.after(node2);
-
-            assert_equals(node2.previousSibling, node1, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node2.parent, parent, 'Node should be inserted into the tree');
-            assert_equals(node1.nextSibling, node2, 'Node should be inserted into the tree ' +
-                'after this node');
-            assert_equals(parent.children, [node1, node2], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'AnimationNode.after() inserts nodes after this node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.after(node1);
-
-            assert_equals(node2.previousSibling, null, type(node2) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node2.nextSibling, node1, 'Node should be inserted into the tree ' +
-                'after this node');
-            assert_equals(node1.previousSibling, node2, type(node2) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node1.nextSibling, null, 'Node should be inserted into the tree ' +
-                'after this node');
-            assert_equals(parent.children, [node2, node1], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'AnimationNode.after() inserts nodes after this node. Inserted node is on the same ' +
-    'level in the tree');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node1.after(node2);
-
-            assert_equals(node1.nextSibling, node2, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node2.previousSibling, node1, 'Node should be inserted into the tree ' +
-                'after this node');
-            assert_equals(parent.children, [node1, node2], parentCtor.name +
-                '.children should not be changed');
-        });
-    });
-}, 'Test AnimationNode.after() inserts node after this node even if inserted ' +
-    'node is already after this one');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node3) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3, parent1, node4]);
-
-            node3.after(node1);
-
-            assert_equals(node1.nextSibling, parent1, type(node3) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node1.parent, parent2, 'Parent group of the inserted node should be changed');
-            assert_equals(node1.previousSibling, node3, 'Node should be inserted into the tree ' +
-                'after this node');
-
-            assert_equals(node3.nextSibling, node1, type(node3) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(parent1.previousSibling, node1, type(node3) + '.after() should insert ' +
-                'nodes after this node');
-
-            assert_equals(node2.previousSibling, null, 'Inserted node should be removed from its ' +
-                'previous position in the tree');
-            assert_array_equals(parent1.children, [node2], 'Inserted node should be removed from its ' +
-                'previous position in the tree');
-            assert_array_equals(parent2.children, [node1, node3, parent1, node4], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.after() inserts node after this node. The previous position ' +
-    'of the inserted node is deeper in the tree than current node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3, parent1, node4]);
-
-            node1.after(node4);
-
-            assert_equals(node4.nextSibling, node2, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.parent, parent1, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node1, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-
-            assert_equals(node1.nextSibling, node4, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node2.previousSibling, node4, 'Node should be inserted into the tree ' +
-                'after this node');
-
-            assert_equals(parent1.nextSibling, null, 'Inserted node should be removed from its ' +
-                'previous position in the tree');
-            assert_array_equals(parent1.children, [node1, node4, node2], parentCtor.name +
-                '.children should be updated');
-            assert_array_equals(parent2.children, [node3, parent1], 'Inserted node should be ' +
-                'removed from its previous position in the tree');
-        });
-    });
-}, 'Test AnimationNode.after() inserts node after this node. The previous position ' +
-    'of the inserted node is shallower in the tree than current node, but not ancestor');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node1.after(node3, node4);
-
-            assert_equals(node1.nextSibling, node3, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.previousSibling, node1, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.nextSibling, node4, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node3, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.nextSibling, node2, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node2.previousSibling, node4, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.after() inserts several nodes after this node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node1.after(node3, node4, node3, node4);
-
-            assert_equals(node1.nextSibling, node3, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.previousSibling, node1, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.nextSibling, node4, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node3, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.nextSibling, node2, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node2.previousSibling, node4, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.after() inserts several nodes after this node, duplicate nodes are ignored');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node1.after(node3, node4, node3);
-
-            assert_equals(node1.nextSibling, node4, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.previousSibling, node1, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.nextSibling, node3, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node3.previousSibling, node4, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.nextSibling, node2, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node2.previousSibling, node3, type(node1) + '.after() should insert ' +
-                'nodes after this node');
-            assert_array_equals(parent.children, [node1, node4, node3, node2], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.after() inserts several nodes after this node, check insertion order');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-            var player = document.timeline.play(node2);
-
-            assert_equals(player.source, node2, 'The node should be associated with its player');
-            node1.after(node2);
-            assert_equals(player.source, null, 'The node should be disassociated from its player');
-        });
-    });
-}, 'Test AnimationNode.after() disassociates the inserted node from the player, ' +
-    'if node is directly associated with a player');
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-before-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-before-expected.txt
deleted file mode 100644
index f2e2ebf4..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-before-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This is a testharness.js-based test.
-FAIL AnimationNode.before() does nothing if the node has no parent animation group. HierarchyRequestError is not thrown in call node.before(null) Animation is not defined
-FAIL AnimationNode.before() does nothing if the node has no parent animation group. No HierarchyRequestError is thrown if the node is inserted before itself Animation is not defined
-FAIL AnimationNode.before() does nothing if there is no parent animation group Animation is not defined
-FAIL HierarchyRequestError is thrown if node is inserted before itself AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if direct parent is inserted before the node AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if an inclusive ancestor is inserted before the node AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if an inclusive ancestor is inserted before the node. Test several arguments in before() call AnimationGroup is not defined
-FAIL AnimationNode.before() inserts nodes before this node AnimationGroup is not defined
-FAIL AnimationNode.before() inserts nodes before this node. Inserted node is on the same level in the tree AnimationGroup is not defined
-FAIL Test AnimationNode.before() inserts node before this node even if inserted node is already before this one AnimationGroup is not defined
-FAIL Test AnimationNode.before() inserts node before this node. The previous position of the inserted node is deeper in the tree than current node AnimationGroup is not defined
-FAIL Test AnimationNode.before() inserts node before this node. The previous position of the inserted node is shallower in the tree than current node, but not ancestor AnimationGroup is not defined
-FAIL Test AnimationNode.before() inserts several nodes before this node AnimationGroup is not defined
-FAIL Test AnimationNode.before() inserts several nodes before this node, duplicate nodes are ignored AnimationGroup is not defined
-FAIL Test AnimationNode.before() inserts several nodes before this node, check insertion order AnimationGroup is not defined
-FAIL Test AnimationNode.before() disassociates the inserted node from the player, if node is directly associated with a player AnimationGroup is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-before.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-before.html
deleted file mode 100644
index 22caa02..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-before.html
+++ /dev/null
@@ -1,418 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationNode before() method tests</title>
-<meta name="assert" content="Inserts nodes before this animation node.">
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-before">
-<link rel="help" href="http://w3c.github.io/web-animations/#insert-children">
-<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-// Test step 1. If there is no parent animation group, terminate these steps.
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        try {
-            node.before(null);
-        } catch(e) {
-            assert_unreached(type(node) + '.before(null) throws unexpected exception: ' + e);
-        }
-    });
-}, 'AnimationNode.before() does nothing if the node has no parent animation group. ' +
-    'HierarchyRequestError is not thrown in call node.before(null)');
-
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        try {
-            node.before(node);
-        } catch(e) {
-            assert_unreached(type(node) + '.before() throws unexpected exception: ' + e);
-        }
-    });
-}, 'AnimationNode.before() does nothing if the node has no parent animation group. ' +
-    'No HierarchyRequestError is thrown if the node is inserted before itself');
-
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    var node2 = newAnimation(createDiv(this));
-    nodes.forEach(function(node1) {
-        node1.before(node2);
-
-        assert_equals(node1.nextSibling, null, type(node1) + '.before() should do nothing ' +
-            'if the node has no parent animation group');
-        assert_equals(node2.previousSibling, null, type(node1) + '.before() should do nothing ' +
-            'if the node has no parent animation group');
-    });
-}, 'AnimationNode.before() does nothing if there is no parent animation group');
-
-// Test step 2. If any of the animation nodes in nodes is an inclusive ancestor of this animation node throw a HierarchyRequestError exception and terminate these steps.
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.before(node);
-            }, type(node) + '.before() should throw HierarchyRequestError ' +
-                'if inserting node before itself');
-            assert_equals(node.parent, parent, type(node) + '.before() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent.children, [node], type(node) + '.before() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-
-        });
-    });
-}, 'HierarchyRequestError is thrown if node is inserted before itself');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.before(parent);
-            }, type(node) + '.before() should throw HierarchyRequestError ' +
-                'if inserting node\'s parent');
-            assert_equals(node.parent, parent, type(node) + '.before() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent.children, [node], type(node) + '.before() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if direct parent is inserted before the node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent1 = new parentCtor([node]);
-            var parent2 = new parentCtor([parent1]);
-            var parent3 = new parentCtor([parent2]);
-            var parent4 = new parentCtor([parent3]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.before(parent4);
-            }, type(node) + '.before() should throw HierarchyRequestError ' +
-                'if inserting node\'s ancestor');
-            assert_equals(node.parent, parent1, type(node) + '.before() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent1.children, [node], type(node) + '.before() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-            assert_equals(parent3.parent, parent4, type(node) + '.before() should not change ' +
-                'parent attribute of inserted node before throwing HierarchyRequestError');
-            assert_array_equals(parent4.children, [parent3], type(node) + '.before() ' +
-                'should not change inserted node parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted before the node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([parent1]);
-            var parent3 = new parentCtor([parent2]);
-            var parent4 = new parentCtor([parent3]);
-            var parent5 = new ParentCtor([node3]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node1.before(node3, parent3);
-            }, type(node1) + '.before() should throw HierarchyRequestError ' +
-                'if inserting node\'s parent');
-            assert_equals(node1.parent, parent1, type(node1) + '.before() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent1.children, [node1, node2], type(node1) + '.before() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-            assert_equals(parent3.parent, parent4, type(node1) + '.before() should not change ' +
-                'parent attribute of inserted node before throwing HierarchyRequestError');
-            assert_array_equals(parent4.children, [parent3], type(node1) + '.before() ' +
-                'should not change inserted node parent children before throwing HierarchyRequestError');
-            assert_equals(node3.parent, parent5, type(node1) + '.before() should not change ' +
-                'parent attribute of inserted node before throwing HierarchyRequestError');
-            assert_array_equals(parent5.children, [node3], type(node1) + '.before() ' +
-                'should not change inserted node parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted before the node. ' +
-    'Test several arguments in before() call');
-
-// Test step 3. Insert nodes before this animation node.
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-
-            node1.before(node2);
-
-            assert_equals(node1.previousSibling, node2, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node2.parent, parent, 'Node should be inserted into the tree');
-            assert_equals(node2.nextSibling, node1, 'Node should be inserted into the tree ' +
-                'before this node');
-            assert_equals(parent.children, [node2, node1], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'AnimationNode.before() inserts nodes before this node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node1.before(node2);
-
-            assert_equals(node2.previousSibling, null, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node2.nextSibling, node1, 'Node should be inserted into the tree ' +
-                'before this node');
-            assert_equals(node1.previousSibling, node2, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node1.nextSibling, null, 'Node should be inserted into the tree ' +
-                'before this node');
-            assert_equals(parent.children, [node2, node1], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'AnimationNode.before() inserts nodes before this node. Inserted node is on the same ' +
-    'level in the tree');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.before(node1);
-
-            assert_equals(node1.nextSibling, node2, type(node2) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node2.previousSibling, node1, 'Node should be inserted into the tree ' +
-                'before this node');
-            assert_equals(parent.children, [node1, node2], parentCtor.name +
-                '.children should not be changed');
-        });
-    });
-}, 'Test AnimationNode.before() inserts node before this node even if inserted ' +
-    'node is already before this one');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node4) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3, parent1, node4]);
-
-            node4.before(node1);
-
-            assert_equals(node1.nextSibling, parent1, type(node4) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node1.parent, parent2, 'Parent group of the inserted node should be changed');
-            assert_equals(node1.previousSibling, parent1, 'Node should be inserted into the tree ' +
-                'before this node');
-
-            assert_equals(parent1.nextSibling, node1, type(node4) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.previousSibling, node1, type(node4) + '.before() should insert ' +
-                'nodes before this node');
-
-            assert_equals(node2.previousSibling, null, 'Inserted node should be removed from its ' +
-                'previous position in the tree');
-            assert_array_equals(parent1.children, [node2], 'Inserted node should be removed from its ' +
-                'previous position in the tree');
-            assert_array_equals(parent2.children, [node3, parent1, node1, node4], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.before() inserts node before this node. The previous position ' +
-    'of the inserted node is deeper in the tree than current node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3, parent1, node4]);
-
-            node2.before(node4);
-
-            assert_equals(node4.nextSibling, node2, type(node2) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.parent, parent1, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node1, type(node2) + '.before() should insert ' +
-                'nodes before this node');
-
-            assert_equals(node1.nextSibling, node4, type(node2) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node2.previousSibling, node4, 'Node should be inserted into the tree ' +
-                'before this node');
-
-            assert_equals(parent1.nextSibling, null, 'Inserted node should be removed from its ' +
-                'previous position in the tree');
-            assert_array_equals(parent1.children, [node1, node4, node2], parentCtor.name +
-                '.children should be updated');
-            assert_array_equals(parent2.children, [node3, parent1], 'Inserted node should be ' +
-                'removed from its previous position in the tree');
-        });
-    });
-}, 'Test AnimationNode.before() inserts node before this node. The previous position ' +
-    'of the inserted node is shallower in the tree than current node, but not ancestor');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.before(node3, node4);
-
-            assert_equals(node1.nextSibling, node3, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.previousSibling, node1, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.nextSibling, node4, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node3, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.nextSibling, node2, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node2.previousSibling, node4, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.before() inserts several nodes before this node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.before(node3, node4, node3, node4);
-
-            assert_equals(node1.nextSibling, node3, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.previousSibling, node1, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.nextSibling, node4, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node3, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.nextSibling, node2, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node2.previousSibling, node4, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.before() inserts several nodes before this node, duplicate nodes are ignored');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.before(node3, node4, node3);
-
-            assert_equals(node1.nextSibling, node4, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.previousSibling, node1, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.nextSibling, node3, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node3.previousSibling, node4, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.nextSibling, node2, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node2.previousSibling, node3, type(node1) + '.before() should insert ' +
-                'nodes before this node');
-            assert_array_equals(parent.children, [node1, node4, node3, node2], parentCtor.name +
-                '.children should be updated');
-        });
-    });
-}, 'Test AnimationNode.before() inserts several nodes before this node, check insertion order');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-            var player = document.timeline.play(node2);
-
-            assert_equals(player.source, node2, 'The node should be associated with its player');
-            node1.before(node2);
-            assert_equals(player.source, null, 'The node should be disassociated from its player');
-        });
-    });
-}, 'Test AnimationNode.before() disassociates the inserted node from the player, ' +
-    'if node is directly associated with a player');
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-next-sibling-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-next-sibling-expected.txt
deleted file mode 100644
index 9625203..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-next-sibling-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a testharness.js-based test.
-FAIL AnimationNode.nextSibling is null if the node is standalone Animation is not defined
-FAIL AnimationNode.nextSibling is null if the node is the only child of its parent AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node. Test first child AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node. Test second child AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node. Test tree structure with AnimationGroup Animation is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node. Test tree structure with AnimationSequence Animation is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is changed by method before() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is removed by method before() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, several nodes are added by method before() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is changed by method after() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is removed by method after() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, several nodes are added by method after() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is changed by method replace() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is removed by method replace() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, several nodes are added by method replace() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is changed by method remove() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is changed by method AnimationGroup.prepend() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is removed by method AnimationGroup.prepend() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, several nodes are added by method AnimationGroup.prepend() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is changed by method AnimationGroup.append() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, the next sibling is removed by method AnimationGroup.append() AnimationGroup is not defined
-FAIL AnimationNode.nextSibling returns next sibling of this animation node, several nodes are added by method AnimationGroup.append() AnimationGroup is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html
deleted file mode 100644
index 8a6b4a8..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html
+++ /dev/null
@@ -1,503 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationNode nextSibling attribute tests</title>
-<meta name="assert" content="The next sibling of this animation node">
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-nextsibling">
-<link rel="help" href="http://www.w3.org/TR/dom/#concept-tree-next-sibling">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        assert_equals(node.nextSibling, null, type(node) + '.nextSibling should be null');
-    });
-}, 'AnimationNode.nextSibling is null if the node is standalone');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_equals(node.nextSibling, null, type(node) + '.nextSibling ' +
-                'should be null');
-        });
-    });
-}, 'AnimationNode.nextSibling is null if the node is the only child of its parent');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            assert_equals(node1.nextSibling, node2, type(node1) + '.nextSibling should return ' +
-                'next sibling of this animation node');
-            assert_equals(node2.nextSibling, null, type(node2) + '.nextSibling should be null');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test first child');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            assert_equals(node1.nextSibling, node2, type(node1) + '.nextSibling should return ' +
-                'next sibling of this animation node');
-            assert_equals(node2.nextSibling, null, type(node2) + '.nextSibling should be null');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test second child');
-
-test(function() {
-    var node1 = newAnimation(createDiv(this));
-    var node2 = newAnimation(createDiv(this));
-    var node3 = newAnimation(createDiv(this));
-    var node4 = newAnimation(createDiv(this));
-    var node5 = newAnimation(createDiv(this));
-    var node6 = newAnimation(createDiv(this));
-    var node7 = new AnimationGroup([node3, node4]);
-    var node8 = new AnimationGroup([node5, node6]);
-    var node9 = newAnimation(createDiv(this));
-    var group = new AnimationGroup([node1, node2, node7, node8, node9]);
-
-    assert_equals(group.nextSibling, null, 'AnimationNode.nextSibling should return ' +
-        'null (root node)');
-    assert_equals(node1.nextSibling, node2, 'AnimationNode.nextSibling should return ' +
-        'next sibling for the first node in the group');
-    assert_equals(node2.nextSibling, node7, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node');
-    assert_equals(node3.nextSibling, node4, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (first node in the nested group)');
-    assert_equals(node4.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
-        'for the last node in the nested group');
-	assert_equals(node5.nextSibling, node6, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (first node in the second nested group)');
-    assert_equals(node6.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
-        'for the last node in the second nested group');
-    assert_equals(node7.nextSibling, node8, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (first nested group)');
-    assert_equals(node8.nextSibling, node9, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (second nested group)');
-    assert_equals(node9.nextSibling, null, 'AnimationNode.nextSibling should return ' +
-        'null (the last node)');
-}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test ' +
-    'tree structure with AnimationGroup');
-
-test(function() {
-    var node1 = newAnimation(createDiv(this));
-    var node2 = newAnimation(createDiv(this));
-    var node3 = newAnimation(createDiv(this));
-    var node4 = newAnimation(createDiv(this));
-    var node5 = newAnimation(createDiv(this));
-    var node6 = newAnimation(createDiv(this));
-    var node7 = new AnimationSequence([node3, node4]);
-    var node8 = new AnimationSequence([node5, node6]);
-    var node9 = newAnimation(createDiv(this));
-    var sequence = new AnimationSequence([node1, node2, node7, node8, node9]);
-
-    assert_equals(sequence.nextSibling, null, 'AnimationNode.nextSibling should return ' +
-        'null (root node)');
-    assert_equals(node1.nextSibling, node2, 'AnimationNode.nextSibling should return ' +
-        'next sibling for the first node in the sequence');
-    assert_equals(node2.nextSibling, node7, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node');
-    assert_equals(node3.nextSibling, node4, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (first node in the nested sequence)');
-    assert_equals(node4.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
-        'for the last node in the nested sequence');
-	assert_equals(node5.nextSibling, node6, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (first node in the second nested sequence)');
-    assert_equals(node6.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
-        'for the last node in the second nested sequence');
-    assert_equals(node7.nextSibling, node8, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (first nested sequence)');
-    assert_equals(node8.nextSibling, node9, 'AnimationNode.nextSibling should return ' +
-        'next sibling of this animation node (second nested sequence)');
-    assert_equals(node9.nextSibling, null, 'AnimationNode.nextSibling should return ' +
-        'null (the last node)');
-}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test ' +
-    'tree structure with AnimationSequence');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-            node2.before(node3);
-
-            assert_equals(node1.nextSibling, node3, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-            assert_equals(node3.nextSibling, node2, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is changed by method before()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node3) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            node3.before(node2);
-
-            assert_equals(node1.nextSibling, null, type(node3) + '.before() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, node3, type(node3) + '.before() should update ' +
-                'next sibling of animation node');
-        });
-    });
-},  'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is removed by method before()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = new AnimationGroup([]);
-            var node5 = new AnimationSequence([]);
-            var parent = new parentCtor([node1, node2]);
-            node2.before(node3, node4, node5);
-
-            assert_equals(node1.nextSibling, node3, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-            assert_equals(node3.nextSibling, node4, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-            assert_equals(node4.nextSibling, node5, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-            assert_equals(node5.nextSibling, node2, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node2) + '.before() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'several nodes are added by method before()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-            node1.after(node3);
-
-            assert_equals(node1.nextSibling, node3, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-            assert_equals(node3.nextSibling, node2, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is changed by method after()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node3) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            node3.after(node2);
-
-            assert_equals(node1.nextSibling, null, type(node3) + '.after() should update ' +
-                'next sibling of animation node');
-            assert_equals(node3.nextSibling, node2, type(node3) + '.after() should update ' +
-                'next sibling of animation node');
-        });
-    });
-},  'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is removed by method after()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = new AnimationGroup([]);
-            var node5 = new AnimationSequence([]);
-            var parent = new parentCtor([node1, node2]);
-            node1.after(node3, node4, node5);
-
-            assert_equals(node1.nextSibling, node3, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-            assert_equals(node3.nextSibling, node4, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-            assert_equals(node4.nextSibling, node5, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-            assert_equals(node5.nextSibling, node2, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node1) + '.after() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'several nodes are added by method after()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2, node3]);
-            node2.replace(node4);
-
-            assert_equals(node1.nextSibling, node4, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node4.nextSibling, node3, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is changed by method replace()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node4) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2, node3]);
-            var parent2 = new parentCtor([node4]);
-
-            node4.replace(node2);
-
-            assert_equals(node1.nextSibling, node3, type(node4) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node4) + '.replace() should update ' +
-                'next sibling of animation node');
-        });
-    });
-},  'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is removed by method replace()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var node5 = new AnimationGroup([]);
-            var node6 = new AnimationSequence([]);
-            var parent = new parentCtor([node1, node2, node3]);
-            node2.replace(node4, node5, node6);
-
-            assert_equals(node1.nextSibling, node4, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node4.nextSibling, node5, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node5.nextSibling, node6, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node6.nextSibling, node3, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'several nodes are added by method replace()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2, node3]);
-            node2.remove();
-
-            assert_equals(node1.nextSibling, node3, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, type(node2) + '.replace() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is changed by method remove()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-            parent.prepend(node2);
-
-            assert_equals(node2.nextSibling, node1, parentCtor.name + '.prepend() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is changed by method AnimationGroup.prepend()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            parent2.prepend(node2);
-
-            assert_equals(node1.nextSibling, null, parentCtor.name + '.prepend() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, node3, parentCtor.name + '.prepend() should update ' +
-                'next sibling of animation node');
-        });
-    });
-},  'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is removed by method AnimationGroup.prepend()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var node1 = newAnimation(createDiv(test));
-        var node2 = new AnimationGroup([]);
-        var node3 = new AnimationSequence([]);
-        var node4 = newAnimation(createDiv(test));
-        var parent = new parentCtor([node1]);
-        parent.prepend(node2, node3, node4);
-
-        assert_equals(node2.nextSibling, node3, parentCtor.name + '.prepend() should update ' +
-            'next sibling of animation node');
-        assert_equals(node3.nextSibling, node4, parentCtor.name + '.prepend() should update ' +
-            'next sibling of animation node');
-        assert_equals(node4.nextSibling, node1, parentCtor.name + '.prepend() should update ' +
-            'next sibling of animation node');
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'several nodes are added by method AnimationGroup.prepend()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-            parent.append(node2);
-
-            assert_equals(node1.nextSibling, node2, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, null, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is changed by method AnimationGroup.append()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            parent2.append(node2);
-
-            assert_equals(node1.nextSibling, null, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-            assert_equals(node3.nextSibling, node2, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-        });
-    });
-},  'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'the next sibling is removed by method AnimationGroup.append()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = new AnimationGroup([]);
-            var node4 = new AnimationSequence([]);
-            var parent = new parentCtor([node1]);
-            parent.append(node2, node3, node4);
-
-            assert_equals(node1.nextSibling, node2, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-            assert_equals(node2.nextSibling, node3, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-            assert_equals(node3.nextSibling, node4, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-            assert_equals(node4.nextSibling, null, parentCtor.name + '.append() should update ' +
-                'next sibling of animation node');
-        });
-    });
-}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
-    'several nodes are added by method AnimationGroup.append()');
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-parent-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-parent-expected.txt
deleted file mode 100644
index 0602142..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-parent-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL AnimationNode.parent is null if animation node does not have a parent animation group Animation is not defined
-FAIL AnimationNode.parent returns parent animation group of this animation node AnimationGroup is not defined
-FAIL AnimationNode.parent returns parent animation group of this animation node. The group has several children nodes AnimationGroup is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-parent.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-parent.html
deleted file mode 100644
index 1c4ac6f..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-parent.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationNode parent attribute tests</title>
-<meta name="assert" content="The parent animation group of this animation node or null if this animation node does not have a parent animation group">
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-parent">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        assert_equals(node.parent, null, type(node) + '.parent should be null');
-    });
-}, 'AnimationNode.parent is null if animation node does not have a parent animation group');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_equals(node.parent, parent, type(node) + '.parent should return ' +
-                'parent animation group of this animation node');
-        });
-    });
-}, 'AnimationNode.parent returns parent animation group of this animation node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        var parent = new parentCtor([nodes[0], nodes[1], nodes[2]]);
-        nodes.forEach(function(node) {
-            assert_equals(node.parent, parent, type(node) + '.parent should return ' +
-                'parent animation group of this animation node');
-        });
-    });
-}, 'AnimationNode.parent returns parent animation group of this animation node. ' +
-    'The group has several children nodes');
-
-// The rest is tested in mutator methods: AnimationNode.before(), AnimationNode.after(),
-// AnimationNode.replace(), AnimationNode.remove(),
-// AnimationGroup.prepend(), AnimationGroup.append(), AnimationGroup.clone()
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling-expected.txt
deleted file mode 100644
index 3a790fa..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a testharness.js-based test.
-FAIL AnimationNode.previousSibling is null if the node is standalone Animation is not defined
-FAIL AnimationNode.previousSibling is null if the node is the only child of its parent AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node. Test first child AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node. Test second child AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node. Test tree structure with AnimationGroup Animation is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node. Test tree structure with AnimationSequence Animation is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is changed by method before() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is removed by method before() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, several nodes are added by method before() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is changed by method after() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is removed by method after() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, several nodes are added by method after() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is changed by method replace() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is removed by method replace() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, several nodes are added by method replace() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is changed by method remove() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is changed by method AnimationGroup.prepend() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is removed by method AnimationGroup.prepend() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, several nodes are added by method AnimationGroup.prepend() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is changed by method AnimationGroup.append() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, the previous sibling is removed by method AnimationGroup.append() AnimationGroup is not defined
-FAIL AnimationNode.previousSibling returns previous sibling of this animation node, several nodes are added by method AnimationGroup.append() AnimationGroup is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html
deleted file mode 100644
index 16f1936..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html
+++ /dev/null
@@ -1,511 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationNode previousSibling attribute tests</title>
-<meta name="assert" content="The previous sibling of this animation node">
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-previoussibling">
-<link rel="help" href="http://www.w3.org/TR/dom/#concept-tree-previous-sibling">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-test(function() {
-    var nodes = [
-        newAnimation(createDiv(this)),
-        new AnimationGroup([]),
-        new AnimationSequence([])
-    ];
-    nodes.forEach(function(node) {
-        assert_equals(node.previousSibling, null, type(node) + '.previousSibling should be null');
-    });
-}, 'AnimationNode.previousSibling is null if the node is standalone');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_equals(node.previousSibling, null, type(node) + '.previousSibling ' +
-                'should be null');
-        });
-    });
-}, 'AnimationNode.previousSibling is null if the node is the only child of its parent');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            assert_equals(node1.previousSibling, null, type(node1) + '.previousSibling should be null');
-            assert_equals(node2.previousSibling, node1, type(node2) + '.previousSibling should return ' +
-                'previous sibling of this animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test first child');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            assert_equals(node1.previousSibling, null, type(node1) + '.previousSibling should be null');
-            assert_equals(node2.previousSibling, node1, type(node2) + '.previousSibling should return ' +
-                'previous sibling of this animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test second child');
-
-test(function() {
-    var node1 = newAnimation(createDiv(this));
-    var node2 = newAnimation(createDiv(this));
-    var node3 = newAnimation(createDiv(this));
-    var node4 = newAnimation(createDiv(this));
-    var node5 = newAnimation(createDiv(this));
-    var node6 = newAnimation(createDiv(this));
-    var node7 = new AnimationGroup([node3, node4]);
-    var node8 = new AnimationGroup([node5, node6]);
-    var node9 = newAnimation(createDiv(this));
-    var group = new AnimationGroup([node1, node2, node7, node8, node9]);
-
-    assert_equals(group.previousSibling, null, 'AnimationNode.previousSibling should return ' +
-        'null (root node)');
-    assert_equals(node1.previousSibling, null, 'AnimationNode.previousSibling should return ' +
-        'null for the first node in the group');
-    assert_equals(node2.previousSibling, node1, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node');
-    assert_equals(node3.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
-        'for the first node in the nested group');
-    assert_equals(node4.previousSibling, node3, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (first node in the nested group)');
-    assert_equals(node5.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
-        'for the first node in the second nested group');
-	assert_equals(node6.previousSibling, node5, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (first node in the second nested group)');
-    assert_equals(node7.previousSibling, node2, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (first nested group)');
-    assert_equals(node8.previousSibling, node7, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (second nested group)');
-    assert_equals(node9.previousSibling, node8, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node');
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test ' +
-    'tree structure with AnimationGroup');
-
-test(function() {
-    var node1 = newAnimation(createDiv(this));
-    var node2 = newAnimation(createDiv(this));
-    var node3 = newAnimation(createDiv(this));
-    var node4 = newAnimation(createDiv(this));
-    var node5 = newAnimation(createDiv(this));
-    var node6 = newAnimation(createDiv(this));
-    var node7 = new AnimationSequence([node3, node4]);
-    var node8 = new AnimationSequence([node5, node6]);
-    var node9 = newAnimation(createDiv(this));
-    var sequence = new AnimationSequence([node1, node2, node7, node8, node9]);
-
-    assert_equals(sequence.previousSibling, null, 'AnimationNode.previousSibling should return ' +
-        'null (root node)');
-    assert_equals(node1.previousSibling, null, 'AnimationNode.previousSibling should return ' +
-        'null for the first node in the group');
-    assert_equals(node2.previousSibling, node1, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node');
-    assert_equals(node3.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
-        'for the first node in the nested group');
-    assert_equals(node4.previousSibling, node3, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (first node in the nested group)');
-    assert_equals(node5.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
-        'for the first node in the second nested group');
-	assert_equals(node6.previousSibling, node5, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (first node in the second nested group)');
-    assert_equals(node7.previousSibling, node2, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (first nested group)');
-    assert_equals(node8.previousSibling, node7, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node (second nested group)');
-    assert_equals(node9.previousSibling, node8, 'AnimationNode.previousSibling should return ' +
-        'previous sibling of this animation node');
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test ' +
-    'tree structure with AnimationSequence');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-            node2.before(node3);
-
-            assert_equals(node1.previousSibling, null, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node1, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, node3, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is changed by method before()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node3) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            node3.before(node1);
-
-            assert_equals(node1.previousSibling, null, type(node3) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, null, type(node3) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node1, type(node3) + '.before() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-},  'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is removed by method before()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = new AnimationGroup([]);
-            var node5 = new AnimationSequence([]);
-            var parent = new parentCtor([node1, node2]);
-            node2.before(node3, node4, node5);
-
-            assert_equals(node1.previousSibling, null, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node1, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node4.previousSibling, node3, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node5.previousSibling, node4, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, node5, type(node2) + '.before() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'several nodes are added by method before()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-            node1.after(node3);
-
-            assert_equals(node1.previousSibling, null, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node1, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, node3, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is changed by method after()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node3) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            node3.after(node1);
-
-            assert_equals(node1.previousSibling, node3, type(node3) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, null, type(node3) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, null, type(node3) + '.after() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-},  'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is removed by method after()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = new AnimationGroup([]);
-            var node5 = new AnimationSequence([]);
-            var parent = new parentCtor([node1, node2]);
-            node1.after(node3, node4, node5);
-
-            assert_equals(node1.previousSibling, null, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node1, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node4.previousSibling, node3, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node5.previousSibling, node4, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, node5, type(node1) + '.after() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'several nodes are added by method after()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2, node3]);
-            node2.replace(node4);
-
-            assert_equals(node4.previousSibling, node1, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, null, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node4, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is changed by method replace()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node4) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2, node3]);
-            var parent2 = new parentCtor([node4]);
-
-            node4.replace(node2);
-
-            assert_equals(node3.previousSibling, node1, type(node4) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, null, type(node4) + '.replace() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-},  'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is removed by method replace()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var node5 = new AnimationGroup([]);
-            var node6 = new AnimationSequence([]);
-            var parent = new parentCtor([node1, node2, node3]);
-            node2.replace(node4, node5, node6);
-
-            assert_equals(node4.previousSibling, node1, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node5.previousSibling, node4, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node6.previousSibling, node5, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node6, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, null, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'several nodes are added by method replace()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2, node3]);
-            node2.remove();
-
-            assert_equals(node3.previousSibling, node1, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, null, type(node2) + '.replace() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is changed by method remove()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-            parent.prepend(node2);
-
-            assert_equals(node1.previousSibling, node2, parentCtor.name + '.prepend() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is changed by method AnimationGroup.prepend()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            parent2.prepend(node1);
-
-            assert_equals(node2.previousSibling, null, parentCtor.name + '.prepend() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node1, parentCtor.name + '.prepend() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-},  'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is removed by method AnimationGroup.prepend()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var node1 = newAnimation(createDiv(test));
-        var node2 = new AnimationGroup([]);
-        var node3 = new AnimationSequence([]);
-        var node4 = newAnimation(createDiv(test));
-        var parent = new parentCtor([node1]);
-        parent.prepend(node2, node3, node4);
-
-        assert_equals(node2.previousSibling, null, parentCtor.name + '.prepend() should update ' +
-            'previous sibling of animation node');
-        assert_equals(node3.previousSibling, node2, parentCtor.name + '.prepend() should update ' +
-            'previous sibling of animation node');
-        assert_equals(node4.previousSibling, node3, parentCtor.name + '.prepend() should update ' +
-            'previous sibling of animation node');
-        assert_equals(node1.previousSibling, node4, parentCtor.name + '.prepend() should update ' +
-            'previous sibling of animation node');
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'several nodes are added by method AnimationGroup.prepend()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-            parent.append(node2);
-
-            assert_equals(node1.previousSibling, null, parentCtor.name + '.append() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node2.previousSibling, node1, parentCtor.name + '.append() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is changed by method AnimationGroup.append()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3]);
-
-            parent2.append(node1);
-
-            assert_equals(node2.previousSibling, null, parentCtor.name + '.append() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node1.previousSibling, node3, parentCtor.name + '.append() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-},  'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'the previous sibling is removed by method AnimationGroup.append()');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var node3 = new AnimationGroup([]);
-            var node4 = new AnimationSequence([]);
-            var parent = new parentCtor([node1]);
-            parent.append(node2, node3, node4);
-
-            assert_equals(node2.previousSibling, node1, parentCtor.name + '.append() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node3.previousSibling, node2, parentCtor.name + '.append() should update ' +
-                'previous sibling of animation node');
-            assert_equals(node4.previousSibling, node3, parentCtor.name + '.append() should update ' +
-                'previous sibling of animation node');
-        });
-    });
-}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
-    'several nodes are added by method AnimationGroup.append()');
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-remove-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-remove-expected.txt
deleted file mode 100644
index 46be5d3..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-remove-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-FAIL AnimationNode.remove() does nothing for standalone node Animation is not defined
-FAIL AnimationNode.remove() removes node from the parent animation group. Removed node is the only node in the tree AnimationGroup is not defined
-FAIL AnimationNode.remove() removes node from the parent animation group. Remove the first node in the group AnimationGroup is not defined
-FAIL AnimationNode.remove() removes node from the parent animation group. Remove the last node in the group AnimationGroup is not defined
-FAIL AnimationNode.remove() removes node from the parent animation group. Remove node from the middle of the group AnimationGroup is not defined
-FAIL Test removing a node that has children AnimationGroup is not defined
-FAIL AnimationNode.remove() disassociates the node from player, if node is directly associated with a player Animation is not defined
-FAIL AnimationNode.remove() keeps parent direct association with the player AnimationGroup is not defined
-FAIL AnimationNode.remove() on the root of a non-trivial tree does not change child structure AnimationGroup is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-remove.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-remove.html
deleted file mode 100644
index 97f657e..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-remove.html
+++ /dev/null
@@ -1,239 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationNode remove() method tests</title>
-<meta name="assert" content="Removes this animation node from its parent animation group or player">
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-remove">
-<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        node.remove();
-
-        assert_equals(node.parent, null, type(node) + ' node parent attribute should be null');
-    });
-}, 'AnimationNode.remove() does nothing for standalone node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-            node.remove();
-
-            assert_array_equals(parent.children, [], type(node) +
-                ' node should be removed from the parent ' + parentCtor.name);
-            assert_equals(node.parent, null, type(node) +
-                ' node parent attribute should be updated');
-        });
-    });
-}, 'AnimationNode.remove() removes node from the parent animation group. ' +
-    'Removed node is the only node in the tree');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node1.remove();
-
-            assert_array_equals(parent.children, [node2], type(node1) +
-                ' node should be removed from the parent ' + parentCtor.name);
-            assert_equals(parent.firstChild, node2, 'Parent ' + parentCtor.name +
-                ' firstChild attribute should be updated');
-            assert_equals(node1.parent, null, 'Removed ' + type(node1) +
-                ' node parent attribute should be updated');
-            assert_equals(node1.nextSibling, null, 'Removed ' + type(node1) +
-                ' node nextSibling attribute should be updated');
-            assert_equals(node2.previousSibling, null,
-                'Remaining node previousSibling attribute should be updated');
-        });
-    });
-}, 'AnimationNode.remove() removes node from the parent animation group. ' +
-    'Remove the first node in the group');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.remove();
-
-            assert_array_equals(parent.children, [node1], type(node2) +
-                ' node should be removed from the parent ' + parentCtor.name);
-            assert_equals(parent.lastChild, node1, 'Parent ' + parentCtor.name +
-                ' lastChild attribute should be updated');
-            assert_equals(node2.parent, null, 'Removed ' + type(node2) +
-                ' node parent attribute should be updated');
-            assert_equals(node1.nextSibling, null,
-                'Remaining node nextSibling attribute should be updated');
-            assert_equals(node2.previousSibling, null, 'Removed ' + type(node2) +
-                ' node previousSibling attribute should be updated');
-        });
-    });
-}, 'AnimationNode.remove() removes node from the parent animation group. ' +
-    'Remove the last node in the group');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2, node3]);
-
-            node2.remove();
-
-            assert_array_equals(parent.children, [node1, node3], type(node2) +
-                ' node should be removed from the parent ' + parentCtor.name);
-            assert_equals(node2.parent, null, 'Removed ' + type(node2) +
-                ' node parent attribute should be updated');
-            assert_equals(node2.nextSibling, null, 'Removed ' + type(node2) +
-                ' node nextSibling attribute should be updated');
-            assert_equals(node2.previousSibling, null, 'Removed ' + type(node2) +
-                ' node previousSibling attribute should be updated');
-            assert_equals(node1.nextSibling, node3,
-                'Remaining node nextSibling attribute should be updated');
-            assert_equals(node3.previousSibling, node1,
-                'Remaining node previousSibling attribute should be updated');
-        });
-    });
-}, 'AnimationNode.remove() removes node from the parent animation group. ' +
-    'Remove node from the middle of the group');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        parents.forEach(function(nodeCtor) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = new nodeCtor([node1, node2]);
-            var node5 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node3, node4, node5]);
-
-            node4.remove();
-
-            assert_array_equals(node4.children, [node1, node2], 'Removed ' +
-                type(node4) + ' node children should not be changed');
-            assert_array_equals(parent.children, [node3, node5], type(node4) +
-                ' node should be removed from the parent ' + parentCtor.name);
-            assert_equals(node4.parent, null, 'Removed ' + type(node2) +
-                ' node parent attribute should be updated');
-            assert_equals(node4.nextSibling, null, 'Removed ' + type(node2) +
-                ' node nextSibling attribute should be updated');
-            assert_equals(node4.previousSibling, null, 'Removed ' + type(node2) +
-                ' node previousSibling attribute should be updated');
-            assert_equals(node3.nextSibling, node5,
-                'Remaining node nextSibling attribute should be updated');
-            assert_equals(node5.previousSibling, node3,
-                'Remaining node previousSibling attribute should be updated');
-        });
-    });
-}, 'Test removing a node that has children');
-
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        var player = document.timeline.play(node);
-        node.remove();
-
-        assert_equals(player.source, null, type(node) +
-            ' node should be disassociated from the player');
-    });
-}, 'AnimationNode.remove() disassociates the node from player, ' +
-    'if node is directly associated with a player');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2, node3]);
-            var player = document.timeline.play(parent);
-
-            node2.remove();
-
-            assert_equals(player.source, parent, type(node2) +
-                ' parent node should remain associated with the player');
-        });
-    });
-}, 'AnimationNode.remove() keeps parent direct association with the player');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        parents.forEach(function(nodeCtor) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var node5 = new parentCtor([node4]);
-            var group1 = new AnimationGroup([node3, node5]);
-            var node6 = newAnimation(createDiv(test));
-            var node7 = new parentCtor([node6]);
-            var node8 = newAnimation(createDiv(test));
-            var sequence1 = new AnimationSequence([node7,node8]);
-            var node9 = new nodeCtor([node1, group1, node2, sequence1]);
-            var node10 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node9, node10]);
-
-            node9.remove();
-
-            assert_equals(node9.parent, null, 'Removed ' + type(node9) +
-                ' node parent attribute should be updated');
-            assert_array_equals(node9.children, [node1, group1, node2, sequence1],
-                'Removed ' + type(node9) + ' node children should not be changed');
-            for (var i = 0; i < node9.children.length; i++) {
-                assert_equals(node9.children[i].parent, node9, 'Removed ' + type(node9) +
-                    ' node children parent attribute should not be changed for child ' + i);
-            }
-            assert_array_equals(group1.children, [node3, node5],
-                'Removed ' + type(node9) + ' node grand children should not be changed');
-            for (var i = 0; i < group1.children.length; i++) {
-                assert_equals(group1.children[i].parent, group1, 'Removed ' + type(node9) +
-                    ' node grand children parent attribute should not be changed for child ' + i);
-            }
-            assert_array_equals(sequence1.children, [node7,node8],
-                'Removed ' + type(node9) + ' node grand children should not be changed');
-            for (var i = 0; i < sequence1.children.length; i++) {
-                assert_equals(sequence1.children[i].parent, sequence1, 'Removed ' + type(node9) +
-                    ' node grand children parent attribute should not be changed for child ' + i);
-            }
-            assert_array_equals(node5.children, [node4],
-                'Removed ' + type(node9) + ' node grand children should not be changed');
-            assert_equals(node4.parent, node5, 'Removed ' + type(node9) +
-                ' node grand children parent attribute should not be changed');
-            assert_array_equals(node7.children, [node6],
-                'Removed ' + type(node9) + ' node grand children should not be changed');
-            assert_equals(node6.parent, node7, 'Removed ' + type(node9) +
-                ' node grand children parent attribute should not be changed');
-        });
-    });
-}, 'AnimationNode.remove() on the root of a non-trivial tree does not change child structure');
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-replace-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-replace-expected.txt
deleted file mode 100644
index 9379969..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-replace-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-This is a testharness.js-based test.
-FAIL AnimationNode.replace(null) does nothing if node has no parent animation group Animation is not defined
-FAIL AnimationNode.replace() does nothing if node has no parent animation group. HierarchyRequestError is not thrown if the node is replacing itself Animation is not defined
-FAIL AnimationNode.replace() does nothing if node has no parent animation group Animation is not defined
-FAIL HierarchyRequestError is thrown if the node replaces itself AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if the node is replaced by its parent AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if the node is replaced by its inclusive ancestor AnimationGroup is not defined
-FAIL HierarchyRequestError is thrown if node is replaced by its inclusive ancestor. Test several arguments in replace() call AnimationGroup is not defined
-FAIL AnimationNode.replace() without arguments removes the node from the parent animation group AnimationGroup is not defined
-FAIL AnimationNode.replace() removes the node from its parent animation group AnimationGroup is not defined
-FAIL AnimationNode.replace(next sibling) removes the node from its parent animation group AnimationGroup is not defined
-FAIL AnimationNode.replace() replaces node in the parent animation group AnimationGroup is not defined
-FAIL Test AnimationNode.replace() replaces given node. The previous position of the replacement node is deeper in the tree than the current node AnimationGroup is not defined
-FAIL Test AnimationNode.replace() replaces given node. The previous position of the replacement node is shallower in the tree than current node, but is not an ancestor AnimationGroup is not defined
-FAIL Test AnimationNode.replace() replaces given node. Test several arguments AnimationGroup is not defined
-FAIL Test AnimationNode.replace() replaces given node by several nodes, duplicate nodes are ignored AnimationGroup is not defined
-FAIL Test AnimationNode.replace() replaces given node by several nodes, check replacement order AnimationGroup is not defined
-FAIL Test AnimationNode.replace() disassociates the inserted node from the player, if node is directly associated with a player AnimationGroup is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-replace.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-replace.html
deleted file mode 100644
index f4cebc4..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/animation-node-replace.html
+++ /dev/null
@@ -1,444 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationNode replace() method tests</title>
-<meta name="assert" content="Replaces this AnimationNode with the passed in nodes parameter">
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-replace">
-<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
-<link rel="help" href="http://w3c.github.io/web-animations/#insert-children">
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-// Step 1. If there is no parent animation group, terminate these steps.
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        try {
-            node.replace(null);
-        } catch(e) {
-            assert_unreached(type(node) + '.replace(null) throws unexpected exception: ' + e);
-        }
-    });
-}, 'AnimationNode.replace(null) does nothing if node has no parent animation group');
-
-test(function() {
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node) {
-        try {
-            node.replace(node);
-        } catch(e) {
-            assert_unreached(type(node) + '.replace(node) throws unexpected exception: ' + e);
-        }
-    });
-}, 'AnimationNode.replace() does nothing if node has no parent animation group. ' +
-    'HierarchyRequestError is not thrown if the node is replacing itself');
-
-test(function() {
-    var test = this;
-    var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
-    nodes.forEach(function(node1) {
-        var node2 = newAnimation(createDiv(test));
-
-        try {
-            node1.replace(node2);
-        } catch(e) {
-            assert_unreached(type(node1) + '.replace() throws unexpected exception: ' + e);
-        }
-    });
-}, 'AnimationNode.replace() does nothing if node has no parent animation group');
-
-// Step 2. If any of the animation nodes in nodes is an inclusive ancestor
-// of the parent animation group throw a HierarchyRequestError exception and terminate these steps.
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.replace(node);
-            }, 'HierarchyRequestError should be thrown if ' + type(node) +
-                ' replaces itself');
-            assert_equals(node.parent, parent, type(node) + '.replace() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent.children, [node], type(node) + '.replace() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if the node replaces itself');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.replace(parent);
-            }, 'HierarchyRequestError should be thrown if ' + type(node) +
-                ' is replaced by its parent ' + parentCtor.name);
-            assert_equals(node.parent, parent, type(node) + '.replace() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent.children, [node], type(node) + '.replace() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if the node is replaced by its parent');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent1 = new parentCtor([node]);
-            var parent2 = new parentCtor([parent1]);
-            var parent3 = new parentCtor([parent2]);
-            var parent4 = new parentCtor([parent3]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node.replace(parent3);
-            }, 'HierarchyRequestError should be thrown if ' + type(node) +
-                ' is replaced by its inclusive ancestor' + parentCtor.name);
-            assert_equals(node.parent, parent1, type(node) + '.replace() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent1.children, [node], type(node) + '.replace() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-            assert_equals(parent3.parent, parent4, type(node) + '.replace() should not change ' +
-                'parent attribute of replacement node before throwing HierarchyRequestError');
-            assert_array_equals(parent4.children, [parent3], type(node) + '.replace() ' +
-                'should not change replacement node parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if the node is replaced by its inclusive ancestor');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var parent1 = new parentCtor([node1]);
-            var parent2 = new parentCtor([parent1]);
-            var parent3 = new parentCtor([parent2]);
-            var parent4 = new parentCtor([parent3]);
-            var node2 = newAnimation(createDiv(test));
-            var parent5 = new parentCtor([node2]);
-
-            assert_throws('HierarchyRequestError', function() {
-                node1.replace(node2, parent3);
-            }, 'HierarchyRequestError should be thrown if ' + type(node1) +
-                ' is replaced by its inclusive ancestor' + parentCtor.name);
-            assert_equals(node1.parent, parent1, type(node1) + '.replace() should not change ' +
-                'parent attribute before throwing HierarchyRequestError');
-            assert_array_equals(parent1.children, [node1], type(node1) + '.replace() ' +
-                'should not change parent children before throwing HierarchyRequestError');
-            assert_equals(parent3.parent, parent4, type(node1) + '.replace() should not change ' +
-                'parent attribute of replacement node before throwing HierarchyRequestError');
-            assert_array_equals(parent4.children, [parent3], type(node1) + '.replace() ' +
-                'should not change replacement node parent children before throwing HierarchyRequestError');
-            assert_equals(node2.parent, parent5, type(node1) + '.replace() should not change ' +
-                'parent attribute of replacement node before throwing HierarchyRequestError');
-            assert_array_equals(parent5.children, [node2], type(node1) + '.replace() ' +
-                'should not change replacement node parent children before throwing HierarchyRequestError');
-        });
-    });
-}, 'HierarchyRequestError is thrown if node is replaced by its inclusive ancestor. ' +
-    'Test several arguments in replace() call');
-
-// Step 3. Let reference child be the next sibling of this animation node not in nodes.
-// Step 4. Remove this animation node from its parent animation group.
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node) {
-            var parent = new parentCtor([node]);
-
-            node.replace();
-
-            assert_array_equals(parent.children, [], type(node) +
-                ' node should be removed from parent ' + parentCtor.name);
-            assert_equals(node.parent, null, type(node) +
-                ' node parent attribute should be updated');
-        });
-    });
-}, 'AnimationNode.replace() without arguments removes the node from the parent ' +
-    'animation group');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-
-            node1.replace(node2);
-
-            assert_array_equals(parent.children, [node2], type(node1) +
-                ' node should be removed its parent group');
-            assert_equals(node1.parent, null, type(node1) +
-                ' node should be removed from its parent group');
-            assert_equals(node1.previousSibling, null, type(node1) +
-                ' node previousSibling attribute should be updated');
-            assert_equals(node1.nextSibling, null, type(node1) +
-                ' node nextSibling attribute should be updated');
-        });
-    });
-}, 'AnimationNode.replace() removes the node from its parent animation group');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2, node3]);
-
-            node2.replace(node3);
-
-            assert_array_equals(parent.children, [node1,node3], type(node2) +
-                ' node should be removed from parent ' + parentCtor.name);
-            assert_equals(node2.parent, null, type(node2) +
-                ' node parent attribute should be updated');
-            assert_equals(node2.nextSibling, null, type(node2) +
-                ' node nextSibling attribute should be updated');
-            assert_equals(node2.previousSibling, null, type(node2) +
-                ' node previousSibling attribute should be updated');
-            assert_equals(node1.nextSibling, node3,
-                'Sibling node nextSibling attribute should be updated');
-            assert_equals(node3.previousSibling, node1,
-                'Sibling node previousSibling attribute should be updated');
-        });
-    });
-}, 'AnimationNode.replace(next sibling) removes the node from its parent ' +
-    'animation group');
-
-// Step 5. Insert nodes before reference child.
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-
-            node1.replace(node2);
-
-            assert_array_equals(parent.children, [node2], type(node1) +
-                ' node should be replaced');
-            assert_equals(node2.parent, parent,
-                'Replacement node should be assigned to a parent group');
-        });
-    });
-}, 'AnimationNode.replace() replaces node in the parent animation group');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node4) {
-            var node1 = newAnimation(createDiv(test));
-            var node2 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3, parent1, node4]);
-
-            node4.replace(node1);
-
-            assert_array_equals(parent1.children, [node2],
-                'Replacement node should be removed from its previous position in the tree');
-            assert_array_equals(parent2.children, [node3, parent1, node1],
-                'Replacement node should be inserted into the new position');
-            assert_equals(node1.parent, parent2, 'Inserted node parent group should be assigned');
-            assert_equals(node1.previousSibling, parent1,
-                'Inserted node previousSibling attribute should be updated');
-            assert_equals(node1.nextSibling, null,
-                'Inserted node nextSibling attribute should be updated');
-
-            assert_equals(node4.parent, null, 'Node should be removed from its parent group');
-            assert_equals(node4.previousSibling, null,
-                'Replaced node previousSibling attribute should be updated');
-            assert_equals(node4.nextSibling, null,
-                'Replaced node nextSibling attribute should be updated');
-        });
-    });
-}, 'Test AnimationNode.replace() replaces given node. The previous position ' +
-    'of the replacement node is deeper in the tree than the current node');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent1 = new parentCtor([node1, node2]);
-            var parent2 = new parentCtor([node3, parent1, node4]);
-
-            node2.replace(node4);
-
-            assert_array_equals(parent1.children, [node1, node4],
-                'Replacement node should be inserted to the new position');
-            assert_array_equals(parent2.children, [node3, parent1],
-                'Replacement node should be removed from its previous position in the tree');
-            assert_equals(node4.parent, parent1, 'Inserted node parent group should be changed');
-            assert_equals(node4.previousSibling, node1,
-                'Inserted node previousSibling attribute should be updated');
-            assert_equals(node1.nextSibling, node4,
-                'Inserted node sibling nextSibling attribute should be updated');
-
-            assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
-            assert_equals(node2.previousSibling, null,
-                'Replaced node previousSibling attribute should be updated');
-            assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
-                'should be updated');
-        });
-    });
-}, 'Test AnimationNode.replace() replaces given node. The previous position ' +
-    'of the replacement node is shallower in the tree than current node, but is not an ancestor');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.replace(node3, node4);
-
-            assert_array_equals(parent.children, [node1, node3, node4], type(node2) + '.replace() ' +
-                'should replace the current node by ones passed in arguments');
-            assert_equals(node1.nextSibling, node3, 'nextSibling attribute should be updated');
-            assert_equals(node3.previousSibling, node1, 'Inserted node previousSibling attribute ' +
-                'should be updated');
-            assert_equals(node3.nextSibling, node4, 'Inserted node nextSibling attribute ' +
-                'should be updated');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node3, 'Inserted node previousSibling attribute ' +
-                'should be updated');
-            assert_equals(node4.nextSibling, null, 'Inserted node nextSibling attribute ' +
-                'should be updated');
-            assert_equals(node4.parent, parent, 'Parent group of the second inserted node ' +
-                'should be changed');
-            assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
-            assert_equals(node2.previousSibling, null,
-                'Replaced node previousSibling attribute should be updated');
-            assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
-                'should be updated');
-        });
-    });
-}, 'Test AnimationNode.replace() replaces given node. Test several arguments');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.replace(node3, node4, node3, node4);
-
-            assert_array_equals(parent.children, [node1, node3, node4], type(node2) + '.replace() ' +
-                'should replace the current node by ones passed in arguments');
-            assert_equals(node1.nextSibling, node3, 'nextSibling attribute should be updated');
-            assert_equals(node3.previousSibling, node1, 'Inserted node previousSibling attribute ' +
-                'should be updated');
-            assert_equals(node3.nextSibling, node4, 'Inserted node nextSibling attribute ' +
-                'should be updated');
-            assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node4.previousSibling, node3, 'Inserted node previousSibling attribute ' +
-                'should be updated');
-            assert_equals(node4.nextSibling, null, 'Inserted node nextSibling attribute ' +
-                'should be updated');
-            assert_equals(node4.parent, parent, 'Parent group of the second inserted node ' +
-                'should be changed');
-            assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
-            assert_equals(node2.previousSibling, null,
-                'Replaced node previousSibling attribute should be updated');
-            assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
-                'should be updated');
-        });
-    });
-}, 'Test AnimationNode.replace() replaces given node by several nodes, duplicate nodes are ignored');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node2) {
-            var node1 = newAnimation(createDiv(test));
-            var node3 = newAnimation(createDiv(test));
-            var node4 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1, node2]);
-
-            node2.replace(node3, node4, node3);
-
-            assert_array_equals(parent.children, [node1, node4, node3], type(node2) + '.replace() ' +
-                'should replace the current node by ones passed in arguments');
-            assert_equals(node1.nextSibling, node4, 'nextSibling attribute should be updated');
-            assert_equals(node4.previousSibling, node1, 'Inserted node previousSibling attribute ' +
-                'should be updated');
-            assert_equals(node4.nextSibling, node3, 'Inserted node nextSibling attribute ' +
-                'should be updated');
-            assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
-            assert_equals(node3.previousSibling, node4, 'Inserted node previousSibling attribute ' +
-                'should be updated');
-            assert_equals(node3.nextSibling, null, 'Inserted node nextSibling attribute ' +
-                'should be updated');
-            assert_equals(node3.parent, parent, 'Parent group of the second inserted node ' +
-                'should be changed');
-            assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
-            assert_equals(node2.previousSibling, null,
-                'Replaced node previousSibling attribute should be updated');
-            assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
-                'should be updated');
-        });
-    });
-}, 'Test AnimationNode.replace() replaces given node by several nodes, check replacement order');
-
-test(function() {
-    var test = this;
-    var parents = [AnimationGroup, AnimationSequence];
-    parents.forEach(function(parentCtor) {
-        var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
-        nodes.forEach(function(node1) {
-            var node2 = newAnimation(createDiv(test));
-            var parent = new parentCtor([node1]);
-            var player = document.timeline.play(node2);
-
-            assert_equals(player.source, node2, 'The node should be associated with its player');
-            node1.replace(node2);
-            assert_equals(player.source, null, 'The node should be disassociated from its player');
-        });
-    });
-}, 'Test AnimationNode.replace() disassociates the inserted node from the player, ' +
-    'if node is directly associated with a player');
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/idlharness.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/idlharness.html
deleted file mode 100644
index d99a105..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation-node/idlharness.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>AnimationNode IDL tests</title>
-<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
-<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../resources/WebIDLParser.js"></script>
-<script src="../../../../resources/idlharness.js"></script>
-<body>
-<div id="log"></div>
-<div id="target"></div>
-<script type="text/plain" id="untested-IDL">
-interface AnimationPlayer {
-};
-
-interface AnimationTiming {
-};
-
-interface ComputedTimingProperties {
-};
-
-interface AnimationGroup {
-};
-</script>
-<script type="text/plain" id="AnimationNode-IDL">
-interface AnimationNode {
-    // Timing
-    readonly attribute AnimationTiming          timing;
-    readonly attribute ComputedTimingProperties computedTiming;
-
-    // Timing hierarchy
-    readonly attribute AnimationGroup?          parent;
-    readonly attribute AnimationNode?           previousSibling;
-    readonly attribute AnimationNode?           nextSibling;
-    void before (AnimationNode... nodes);
-    void after (AnimationNode... nodes);
-    void replace (AnimationNode... nodes);
-    void remove ();
-};
-</script>
-<script>
-'use strict';
-
-var target = document.getElementById('target');
-var node = new Animation(target, [], 5);
-
-var idlArray = new IdlArray();
-idlArray.add_untested_idls(document.getElementById('untested-IDL').textContent);
-idlArray.add_idls(document.getElementById('AnimationNode-IDL').textContent);
-idlArray.add_objects( { AnimationNode: ['node'] } );
-idlArray.test();
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/cancel.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/cancel.html
new file mode 100644
index 0000000..4edba6e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/cancel.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.cancel()</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-cancel">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({transform: ['none', 'translate(100px)']},
+                              100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    assert_not_equals(getComputedStyle(div).transform, 'none',
+                      'transform style is animated before cancelling');
+    animation.cancel();
+    assert_equals(getComputedStyle(div).transform, 'none',
+                  'transform style is no longer animated after cancelling');
+  });
+}, 'Animated style is cleared after calling Animation.cancel()');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({marginLeft: ['0px', '100px']},
+                              100 * MS_PER_SEC);
+  animation.effect.timing.easing = 'linear';
+  animation.cancel();
+  assert_equals(getComputedStyle(div).marginLeft, '0px',
+                'margin-left style is not animated after cancelling');
+
+  animation.currentTime = 50 * MS_PER_SEC;
+  assert_equals(getComputedStyle(div).marginLeft, '50px',
+                'margin-left style is updated when cancelled animation is'
+                + ' seeked');
+}, 'After cancelling an animation, it can still be seeked');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({marginLeft:['100px', '200px']},
+                              100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    animation.cancel();
+    assert_equals(getComputedStyle(div).marginLeft, '0px',
+                  'margin-left style is not animated after cancelling');
+    animation.play();
+    assert_equals(getComputedStyle(div).marginLeft, '100px',
+                  'margin-left style is animated after re-starting animation');
+    return animation.ready;
+  }).then(function() {
+    assert_equals(animation.playState, 'running',
+                  'Animation succeeds in running after being re-started');
+  });
+}, 'After cancelling an animation, it can still be re-used');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/finish-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/finish-expected.txt
new file mode 100644
index 0000000..1bd47f70
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/finish-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS Test exceptions when finishing non-running animation 
+PASS Test exceptions when finishing infinite animation 
+PASS Test finishing of animation 
+FAIL Test finishing of animation with a current time past the effect end animation.effect.getComputedTiming is not a function
+PASS Test finishing of reversed animation 
+PASS Test finishing of reversed animation with a current time less than zero 
+FAIL Test finish() while paused promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'currentTime' of undefined"
+FAIL Test finish() while pause-pending with positive playbackRate Cannot read property 'currentTime' of undefined
+FAIL Test finish() while pause-pending with negative playbackRate Cannot read property 'currentTime' of undefined
+FAIL Test finish() while play-pending Cannot read property 'currentTime' of undefined
+PASS Test finish() during aborted pause 
+PASS Test resetting of computed style 
+PASS Test finish() resolves finished promise synchronously 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/finish.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/finish.html
new file mode 100644
index 0000000..8238b50
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/finish.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.finish()</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finish">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+var gKeyFrames = { 'marginLeft': ['100px', '200px'] };
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.playbackRate = 0;
+
+  assert_throws({name: 'InvalidStateError'}, function() {
+    animation.finish();
+  });
+}, 'Test exceptions when finishing non-running animation');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames,
+                              {duration : 100 * MS_PER_SEC,
+                               iterations : Infinity});
+
+  assert_throws({name: 'InvalidStateError'}, function() {
+    animation.finish();
+  });
+}, 'Test exceptions when finishing infinite animation');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.finish();
+
+  assert_equals(animation.currentTime, 100 * MS_PER_SEC,
+                'After finishing, the currentTime should be set to the end ' +
+                'of the active duration');
+}, 'Test finishing of animation');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+   // 1s past effect end
+  animation.currentTime =
+    animation.effect.getComputedTiming().endTime + 1 * MS_PER_SEC;
+  animation.finish();
+
+  assert_equals(animation.currentTime, 100 * MS_PER_SEC,
+                'After finishing, the currentTime should be set back to the ' +
+                'end of the active duration');
+}, 'Test finishing of animation with a current time past the effect end');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.currentTime = 100 * MS_PER_SEC;
+  return animation.finished.then(function() {
+    animation.playbackRate = -1;
+    animation.finish();
+
+    assert_equals(animation.currentTime, 0,
+                  'After finishing a reversed animation the currentTime ' +
+                  'should be set to zero');
+  });
+}, 'Test finishing of reversed animation');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.currentTime = 100 * MS_PER_SEC;
+  return animation.finished.then(function() {
+    animation.playbackRate = -1;
+    animation.currentTime = -1000;
+    animation.finish();
+
+    assert_equals(animation.currentTime, 0,
+                  'After finishing a reversed animation the currentTime ' +
+                  'should be set back to zero');
+  });
+}, 'Test finishing of reversed animation with a current time less than zero');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.pause();
+  return animation.ready.then(function() {
+    animation.finish();
+
+    assert_equals(animation.playState, 'finished',
+                  'The play state of a paused animation should become ' +
+                  '"finished" after finish() is called');
+    assert_approx_equals(animation.startTime,
+                         animation.timeline.currentTime - 100 * MS_PER_SEC,
+                         0.0001,
+                         'The start time of a paused animation should be set ' +
+                         'after calling finish()');
+  });
+}, 'Test finish() while paused');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.pause();
+  // Update playbackRate so we can test that the calculated startTime
+  // respects it
+  animation.playbackRate = 2;
+  // While animation is still pause-pending call finish()
+  animation.finish();
+
+  assert_equals(animation.playState, 'finished',
+                'The play state of a pause-pending animation should become ' +
+                '"finished" after finish() is called');
+  assert_approx_equals(animation.startTime,
+                       animation.timeline.currentTime - 100 * MS_PER_SEC / 2,
+                       0.0001,
+                       'The start time of a pause-pending animation should ' +
+                       'be set after calling finish()');
+}, 'Test finish() while pause-pending with positive playbackRate');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.pause();
+  animation.playbackRate = -2;
+  animation.finish();
+
+  assert_equals(animation.playState, 'finished',
+                'The play state of a pause-pending animation should become ' +
+                '"finished" after finish() is called');
+  assert_equals(animation.startTime, animation.timeline.currentTime,
+                'The start time of a pause-pending animation should be ' +
+                'set after calling finish()');
+}, 'Test finish() while pause-pending with negative playbackRate');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  animation.playbackRate = 0.5;
+  animation.finish();
+
+  assert_equals(animation.playState, 'finished',
+                'The play state of a play-pending animation should become ' +
+                '"finished" after finish() is called');
+  assert_approx_equals(animation.startTime,
+                       animation.timeline.currentTime - 100 * MS_PER_SEC / 0.5,
+                       0.0001,
+                       'The start time of a play-pending animation should ' +
+                       'be set after calling finish()');
+}, 'Test finish() while play-pending');
+
+// FIXME: Add a test for when we are play-pending without an active timeline.
+// - In that case even after calling finish() we should still be pending but
+//   the current time should be updated
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    animation.pause();
+    animation.play();
+    // We are now in the unusual situation of being play-pending whilst having
+    // a resolved start time. Check that finish() still triggers a transition
+    // to the finished state immediately.
+    animation.finish();
+
+    assert_equals(animation.playState, 'finished',
+                  'After aborting a pause then calling finish() the play ' +
+                  'state of an animation should become "finished" immediately');
+  });
+}, 'Test finish() during aborted pause');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  div.style.marginLeft = '10px';
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    animation.finish();
+    var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
+
+    assert_equals(marginLeft, 10,
+                  'The computed style should be reset when finish() is ' +
+                  'called');
+  });
+}, 'Test resetting of computed style');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+  var resolvedFinished = false;
+  animation.finished.then(function() {
+    resolvedFinished = true;
+  });
+
+  return animation.ready.then(function() {
+    animation.finish();
+  }).then(function() {
+    assert_true(resolvedFinished,
+      'Animation.finished should be resolved soon after ' +
+      'Animation.finish()');
+  });
+}, 'Test finish() resolves finished promise synchronously');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/play.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/play.html
new file mode 100644
index 0000000..e210106
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/play.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.play()</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-play">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({ transform: ['none', 'translate(10px)']},
+                              { duration : 100 * MS_PER_SEC,
+                                iterations : Infinity});
+  return animation.ready.then(function() {
+    // Seek to a time outside the active range so that play() will have to
+    // snap back to the start
+    animation.currentTime = -5 * MS_PER_SEC;
+    animation.playbackRate = -1;
+
+    assert_throws('InvalidStateError',
+                  function () { animation.play(); },
+                  'Expected InvalidStateError exception on calling play() ' +
+                  'with a negative playbackRate and infinite-duration ' +
+                  'animation');
+  });
+}, 'play() throws when seeking an infinite-duration animation played in ' +
+   'reverse');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playState.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playState.html
new file mode 100644
index 0000000..7b2badc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playState.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.playState</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-playstate">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({}, 100 * MS_PER_SEC);
+
+  assert_equals(animation.playState, 'pending');
+  return animation.ready.then(function() {
+    assert_equals(animation.playState, 'running');
+  });
+}, 'Animation.playState reports \'pending\'->\'running\' when initially ' +
+   'played');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({}, 100 * MS_PER_SEC);
+  animation.pause();
+
+  assert_equals(animation.playState, 'pending');
+  return animation.ready.then(function() {
+    assert_equals(animation.playState, 'paused');
+  });
+}, 'Animation.playState reports \'pending\'->\'paused\' when pausing');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({}, 100 * MS_PER_SEC);
+  animation.cancel();
+  assert_equals(animation.playState, 'idle');
+}, 'Animation.playState is \'idle\' when canceled.');
+
+test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({}, 100 * MS_PER_SEC);
+  animation.cancel();
+  animation.currentTime = 50 * MS_PER_SEC;
+  assert_equals(animation.playState, 'paused',
+                'After seeking an idle animation, it is effectively paused');
+}, 'Animation.playState is \'paused\' after cancelling an animation, ' +
+   'seeking it makes it paused');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playbackRate-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playbackRate-expected.txt
new file mode 100644
index 0000000..e742b269
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playbackRate-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS Test the initial effect of setting playbackRate on currentTime 
+FAIL Test the effect of setting playbackRate on currentTime promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'currentTime' of undefined"
+FAIL Test the effect of setting playbackRate while playing animation promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'currentTime' of undefined"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playbackRate.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playbackRate.html
new file mode 100644
index 0000000..7e3712a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/animation/playbackRate.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.playbackRate</title>
+<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-playbackrate">
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="../../../../resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+var keyFrames = { 'marginLeft': ['100px', '200px'] };
+
+function assert_playbackrate(animation,
+                             previousAnimationCurrentTime,
+                             previousTimelineCurrentTime,
+                             description) {
+  var accuracy = 0.001; /* accuracy of DOMHighResTimeStamp */
+  var animationCurrentTimeDifference =
+    animation.currentTime - previousAnimationCurrentTime;
+  var timelineCurrentTimeDifference =
+    animation.timeline.currentTime - previousTimelineCurrentTime;
+
+  assert_approx_equals(animationCurrentTimeDifference,
+                       timelineCurrentTimeDifference * animation.playbackRate,
+                       accuracy,
+                       description);
+}
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({keyFrames}, 100 * MS_PER_SEC);
+  return animation.ready.then(function() {
+    animation.currentTime = 7 * MS_PER_SEC; // ms
+    animation.playbackRate = 0.5;
+
+    assert_equals(animation.currentTime, 7 * MS_PER_SEC,
+      'Reducing Animation.playbackRate should not change the currentTime ' +
+      'of a playing animation');
+    animation.playbackRate = 2;
+    assert_equals(animation.currentTime, 7 * MS_PER_SEC,
+      'Increasing Animation.playbackRate should not change the currentTime ' +
+      'of a playing animation');
+  });
+}, 'Test the initial effect of setting playbackRate on currentTime');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({keyFrames}, 100 * MS_PER_SEC);
+  animation.playbackRate = 2;
+  var previousTimelineCurrentTime;
+  var previousAnimationCurrentTime;
+  return animation.ready.then(function() {
+    previousAnimationCurrentTime = animation.currentTime;
+    previousTimelineCurrentTime = animation.timeline.currentTime;
+    return waitForAnimationFrames(1);
+  }).then(function() {
+    assert_playbackrate(animation,
+      previousAnimationCurrentTime,
+      previousTimelineCurrentTime,
+      'animation.currentTime should be 2 times faster than timeline.');
+  });
+}, 'Test the effect of setting playbackRate on currentTime');
+
+promise_test(function(t) {
+  var div = createDiv(t);
+  var animation = div.animate({keyFrames}, 100 * MS_PER_SEC);
+  animation.playbackRate = 2;
+  var previousTimelineCurrentTime;
+  var previousAnimationCurrentTime;
+  return animation.ready.then(function() {
+    previousAnimationCurrentTime = animation.currentTime;
+    previousTimelineCurrentTime = animation.timeline.currentTime;
+    animation.playbackRate = 1;
+    return waitForAnimationFrames(1);
+  }).then(function() {
+    assert_equals(animation.playbackRate, 1,
+      'sanity check: animation.playbackRate is still 1.');
+    assert_playbackrate(animation,
+      previousAnimationCurrentTime,
+      previousTimelineCurrentTime,
+      'animation.currentTime should be the same speed as timeline now.');
+  });
+}, 'Test the effect of setting playbackRate while playing animation');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor-expected.txt
index ebc9f02..84042d69 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor-expected.txt
@@ -69,6 +69,18 @@
 FAIL a KeyframeEffectReadOnly constructed with a Keyframe sequence where lesser shorthand precedes greater shorthand roundtrips KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly can be constructed with a Keyframe sequence where greater shorthand precedes lesser shorthand KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly constructed with a Keyframe sequence where greater shorthand precedes lesser shorthand roundtrips KeyframeEffectReadOnly is not defined
+FAIL Invalid easing [a blank easing] in KeyframeSequence should be thrown assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target, su..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL Invalid easing [an unrecognized easing] in KeyframeSequence should be thrown assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target, su..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL Invalid easing [an 'initial' easing] in KeyframeSequence should be thrown assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target, su..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL Invalid easing [an 'inherit' easing] in KeyframeSequence should be thrown assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target, su..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL Invalid easing [a variable easing] in KeyframeSequence should be thrown assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target, su..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL Invalid easing [a multi-value easing] in KeyframeSequence should be thrown assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target, su..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
 FAIL a KeyframeEffectReadOnly constructed without any KeyframeEffectOptions object KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly constructed by an empty KeyframeEffectOptions object KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly constructed by a normal KeyframeEffectOptions object KeyframeEffectReadOnly is not defined
@@ -77,9 +89,6 @@
 FAIL a KeyframeEffectReadOnly constructed by an Infinity duration KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly constructed by an auto duration KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly constructed by an Infinity iterations KeyframeEffectReadOnly is not defined
-FAIL a KeyframeEffectReadOnly constructed by a negative Infinity iterations KeyframeEffectReadOnly is not defined
-FAIL a KeyframeEffectReadOnly constructed by a NaN iterations KeyframeEffectReadOnly is not defined
-FAIL a KeyframeEffectReadOnly constructed by a negative iterations KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly constructed by an auto fill KeyframeEffectReadOnly is not defined
 FAIL a KeyframeEffectReadOnly constructed by a forwards fill KeyframeEffectReadOnly is not defined
 FAIL Invalid KeyframeEffectReadOnly option by -Infinity assert_throws: function "function () {
@@ -103,6 +112,33 @@
 FAIL Invalid KeyframeEffectReadOnly option by a string duration assert_throws: function "function () {
       new KeyframeEffectReadOnly(target,
   ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by a negative Infinity iterations assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by a NaN iterations assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by a negative iterations assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by a blank easing assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by an unrecognized easing assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by an 'initial' easing assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by an 'inherit' easing assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by a variable easing assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
+FAIL Invalid KeyframeEffectReadOnly option by a multi-value easing assert_throws: function "function () {
+      new KeyframeEffectReadOnly(target,
+  ..." threw object "ReferenceError: KeyframeEffectReadOnly is not defined" ("ReferenceError") expected object "[object Object]" ("TypeError")
 PASS KeyframeEffect constructor creates an AnimationEffectTiming timing object 
 PASS KeyframeEffect constructor propagates exceptions generated by accessing the options object 
 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor.html
index 142ec337..cc6312d 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/constructor.html
@@ -61,13 +61,8 @@
 
 // [specified easing value, expected easing value]
 var gEasingValueTests = [
-  ["unrecognised", "linear"],
   ["linear", "linear"],
   ["ease-in-out", "ease-in-out"],
-  ["initial", "linear"],
-  ["inherit", "linear"],
-  ["var(--x)", "linear"],
-  ["ease-in-out, ease-out", "linear"],
   ["Ease\\2d in-out", "ease-in-out"],
   ["ease /**/", "ease"],
 ];
@@ -113,56 +108,57 @@
 }, "easing values are parsed correctly when passed to the " +
    "KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
 
-var gGoodCompositeValueTests = [
+var gGoodKeyframeCompositeValueTests = [
+  "replace", "add", "accumulate", undefined
+];
+
+var gGoodOptionsCompositeValueTests = [
   "replace", "add", "accumulate"
 ];
 
 var gBadCompositeValueTests = [
-  "unrecognised", "replace ", "Replace"
+  "unrecognised", "replace ", "Replace", null
 ];
 
 test(function(t) {
-  gGoodCompositeValueTests.forEach(function(composite) {
-    var effect = new KeyframeEffectReadOnly(target, {
-      left: ["10px", "20px"],
-      composite: composite
-    });
+  var getFrame = function(composite) {
+    return { left: [ "10px", "20px" ], composite: composite };
+  };
+  gGoodKeyframeCompositeValueTests.forEach(function(composite) {
+    var effect = new KeyframeEffectReadOnly(target, getFrame(composite));
     assert_equals(effect.getFrames()[0].composite, composite,
                   "resulting composite for '" + composite + "'");
   });
   gBadCompositeValueTests.forEach(function(composite) {
     assert_throws(new TypeError, function() {
-                    new KeyframeEffectReadOnly(target, {
-                      left: ["10px", "20px"],
-                      composite: composite
-                    });
+                    new KeyframeEffectReadOnly(target, getFrame(composite));
                   });
   });
 }, "composite values are parsed correctly when passed to the " +
    "KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes");
 
 test(function(t) {
-  gGoodCompositeValueTests.forEach(function(composite) {
-    var effect = new KeyframeEffectReadOnly(target, [
+  var getFrames = function(composite) {
+    return [
       { offset: 0, left: "10px", composite: composite },
       { offset: 1, left: "20px" }
-    ]);
+    ];
+  };
+  gGoodKeyframeCompositeValueTests.forEach(function(composite) {
+    var effect = new KeyframeEffectReadOnly(target, getFrames(composite));
     assert_equals(effect.getFrames()[0].composite, composite,
                   "resulting composite for '" + composite + "'");
   });
   gBadCompositeValueTests.forEach(function(composite) {
     assert_throws(new TypeError, function() {
-                    new KeyframeEffectReadOnly(target, [
-                      { offset: 0, left: "10px", composite: composite },
-                      { offset: 1, left: "20px" }
-                    ]);
+                    new KeyframeEffectReadOnly(target, getFrames(composite));
                   });
   });
 }, "composite values are parsed correctly when passed to the " +
    "KeyframeEffectReadOnly constructor in Keyframe");
 
 test(function(t) {
-  gGoodCompositeValueTests.forEach(function(composite) {
+  gGoodOptionsCompositeValueTests.forEach(function(composite) {
     var effect = new KeyframeEffectReadOnly(target, {
       left: ["10px", "20px"]
     }, { composite: composite });
@@ -182,77 +178,77 @@
 var gPropertyIndexedKeyframesTests = [
   { desc:   "a one property two value PropertyIndexedKeyframes specification",
     input:  { left: ["10px", "20px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
   { desc:   "a one shorthand property two value PropertyIndexedKeyframes specification",
     input:  { margin: ["10px", "10px 20px 30px 40px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
   { desc:   "a two property (one shorthand and one of its longhand components) two value PropertyIndexedKeyframes specification",
     input:  { marginTop: ["50px", "60px"],
               margin: ["10px", "10px 20px 30px 40px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
   { desc:   "a two property two value PropertyIndexedKeyframes specification",
     input:  { left: ["10px", "20px"],
               top: ["30px", "40px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "30px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
   { desc:   "a two property PropertyIndexedKeyframes specification with different numbers of values",
     input:  { left: ["10px", "20px", "30px"],
               top: ["40px", "50px"] },
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px", top: "40px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "20px" },
-             { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "30px", top: "50px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px", top: "40px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear", left: "30px", top: "50px" }] },
   { desc:   "a PropertyIndexedKeyframes specification with an invalid value",
     input:  { left: ["10px", "20px", "30px", "40px", "50px"],
               top:  ["15px", "25px", "invalid", "45px", "55px"] },
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px", top: "15px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px", top: "25px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px", top: "45px" },
-             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px", top: "55px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "15px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px", top: "25px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px", top: "45px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px", top: "55px" }] },
   { desc:   "a one property two value PropertyIndexedKeyframes specification that needs to stringify its values",
     input:  { opacity: [0, 1] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", opacity: "0" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", opacity: "1" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
+             { offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
   { desc:   "a one property one value PropertyIndexedKeyframes specification",
     input:  { left: ["10px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
   { desc:   "a one property one non-array value PropertyIndexedKeyframes specification",
     input:  { left: "10px" },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
   { desc:   "a one property two value PropertyIndexedKeyframes specification where the first value is invalid",
     input:  { left: ["invalid", "10px"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "10px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
   { desc:   "a one property two value PropertyIndexedKeyframes specification where the second value is invalid",
     input:  { left: ["10px", "invalid"] },
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear" }] },
   { desc:   "a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe",
     input:  [{ offset: 0, left: "10px" },
              { offset: 1, left: "20px", top: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "30px" }] },
   { desc:   "a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe",
     input:  [{ offset: 0, left: "10px", top: "20px" },
              { offset: 1, left: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" , top: "20px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" , top: "20px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "30px" }] },
   { desc:   "a PropertyIndexedKeyframes specification with repeated values at offset 0 with different easings",
     input:  [{ offset: 0.0, left: "100px", easing: "ease" },
              { offset: 0.0, left: "200px", easing: "ease" },
              { offset: 0.5, left: "300px", easing: "linear" },
              { offset: 1.0, left: "400px", easing: "ease-out" },
              { offset: 1.0, left: "500px", easing: "step-end" }],
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",     composite: "replace", left: "100px" },
-             { offset: 0.0, computedOffset: 0.0, easing: "ease",     composite: "replace", left: "200px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear",   composite: "replace", left: "300px" },
-             { offset: 1.0, computedOffset: 1.0, easing: "ease-out", composite: "replace", left: "400px" },
-             { offset: 1.0, computedOffset: 1.0, easing: "linear",   composite: "replace", left: "500px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",     left: "100px" },
+             { offset: 0.0, computedOffset: 0.0, easing: "ease",     left: "200px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear",   left: "300px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "ease-out", left: "400px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear",   left: "500px" }] },
 ];
 
 gPropertyIndexedKeyframesTests.forEach(function(subtest) {
@@ -278,7 +274,7 @@
    { p: "left",       v: "20px" },
    { p: "offset",     v: "0" },
    { p: "easing",     v: "linear" },
-   { p: "composite",  v: null }].forEach(function(e) {
+   { p: "composite",  v: "replace" }].forEach(function(e) {
     Object.defineProperty(kf1, e.p, {
       enumerable: true,
       get: function() { actualOrder.push(e.p); return e.v; }
@@ -293,33 +289,33 @@
   { desc:   "a one property two Keyframe sequence",
     input:  [{ offset: 0, left: "10px" },
              { offset: 1, left: "20px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
   { desc:   "a two property two Keyframe sequence",
     input:  [{ offset: 0, left: "10px", top: "30px" },
              { offset: 1, left: "20px", top: "40px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "30px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "20px", top: "40px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
   { desc:   "a one shorthand property two Keyframe sequence",
     input:  [{ offset: 0, margin: "10px" },
              { offset: 1, margin: "20px 30px 40px 50px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] },
   { desc:   "a two property (a shorthand and one of its component longhands) two Keyframe sequence",
     input:  [{ offset: 0, margin: "10px", marginTop: "20px" },
              { offset: 1, marginTop: "70px", margin: "30px 40px 50px 60px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] },
   { desc:   "a Keyframe sequence with duplicate values for a given interior offset",
     input:  [{ offset: 0.0, left: "10px" },
              { offset: 0.5, left: "20px" },
              { offset: 0.5, left: "30px" },
              { offset: 0.5, left: "40px" },
              { offset: 1.0, left: "50px" }],
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "20px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "40px" },
-             { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear", left: "40px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear", left: "50px" }] },
   { desc:   "a Keyframe sequence with duplicate values for offsets 0 and 1",
     input:  [{ offset: 0, left: "10px" },
              { offset: 0, left: "20px" },
@@ -327,50 +323,50 @@
              { offset: 1, left: "40px" },
              { offset: 1, left: "50px" },
              { offset: 1, left: "60px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "30px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "40px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "60px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
+             { offset: 0, computedOffset: 0, easing: "linear", left: "30px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "40px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "60px" }] },
   { desc:   "a two property four Keyframe sequence",
     input:  [{ offset: 0, left: "10px" },
              { offset: 0, top: "20px" },
              { offset: 1, top: "30px" },
              { offset: 1, left: "40px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", left: "10px", top: "20px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", left: "40px", top: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "20px" },
+             { offset: 1, computedOffset: 1, easing: "linear", left: "40px", top: "30px" }] },
   { desc:   "a one property Keyframe sequence with some omitted offsets",
     input:  [{ offset: 0.00, left: "10px" },
              { offset: 0.25, left: "20px" },
              { left: "30px" },
              { left: "40px" },
              { offset: 1.00, left: "50px" }],
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px" },
-             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
   { desc:   "a two property Keyframe sequence with some omitted offsets",
     input:  [{ offset: 0.00, left: "10px", top: "20px" },
              { offset: 0.25, left: "30px" },
              { left: "40px" },
              { left: "50px", top: "60px" },
              { offset: 1.00, left: "70px", top: "80px" }],
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px", top: "20px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "30px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "40px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "50px", top: "60px" },
-             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "70px", top: "80px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "20px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "30px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "40px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "50px", top: "60px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "70px", top: "80px" }] },
   { desc:   "a one property Keyframe sequence with all omitted offsets",
     input:  [{ left: "10px" },
              { left: "20px" },
              { left: "30px" },
              { left: "40px" },
              { left: "50px" }],
-    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", composite: "replace", left: "10px" },
-             { offset: 0.25, computedOffset: 0.25, easing: "linear", composite: "replace", left: "20px" },
-             { offset: 0.50, computedOffset: 0.50, easing: "linear", composite: "replace", left: "30px" },
-             { offset: 0.75, computedOffset: 0.75, easing: "linear", composite: "replace", left: "40px" },
-             { offset: 1.00, computedOffset: 1.00, easing: "linear", composite: "replace", left: "50px" }] },
+    output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
+             { offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
+             { offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
+             { offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
+             { offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
   { desc:   "a Keyframe sequence with different easing values, but the same easing value for a given offset",
     input:  [{ offset: 0.0, easing: "ease",     left: "10px"},
              { offset: 0.0, easing: "ease",     top: "20px"},
@@ -378,9 +374,12 @@
              { offset: 0.5, easing: "linear",   top: "40px" },
              { offset: 1.0, easing: "step-end", left: "50px" },
              { offset: 1.0, easing: "step-end", top: "60px" }],
-    output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",         composite: "replace", left: "10px", top: "20px" },
-             { offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "replace", left: "30px", top: "40px" },
-             { offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px", top: "60px" }] },
+    output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
+               left: "10px", top: "20px" },
+             { offset: 0.5, computedOffset: 0.5, easing: "linear",
+               left: "30px", top: "40px" },
+             { offset: 1.0, computedOffset: 1.0, easing: "linear",
+               left: "50px", top: "60px" }] },
   { desc:   "a Keyframe sequence with different composite values, but the same composite value for a given offset",
     input:  [{ offset: 0.0, composite: "replace", left: "10px" },
              { offset: 0.0, composite: "replace", top: "20px" },
@@ -394,27 +393,27 @@
   { desc:   "a one property two Keyframe sequence that needs to stringify its values",
     input:  [{ offset: 0, opacity: 0 },
              { offset: 1, opacity: 1 }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", opacity: "0" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", opacity: "1" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
+             { offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
   { desc:   "a Keyframe sequence where shorthand precedes longhand",
     input:  [{ offset: 0, margin: "10px", marginRight: "20px" },
              { offset: 1, margin: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
   { desc:   "a Keyframe sequence where longhand precedes shorthand",
     input:  [{ offset: 0, marginRight: "20px", margin: "10px" },
              { offset: 1, margin: "30px" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
+    output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
+             { offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
   { desc:   "a Keyframe sequence where lesser shorthand precedes greater shorthand",
     input:  [{ offset: 0, borderLeft: "1px solid rgb(1, 2, 3)", border: "2px dotted rgb(4, 5, 6)" },
              { offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
+    output: [{ offset: 0, computedOffset: 0, easing: "linear",
                  borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
                  borderLeftColor:   "rgb(1, 2, 3)", borderLeftWidth:   "1px",
                  borderRightColor:  "rgb(4, 5, 6)", borderRightWidth:  "2px",
                  borderTopColor:    "rgb(4, 5, 6)", borderTopWidth:    "2px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
+             { offset: 1, computedOffset: 1, easing: "linear",
                  borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
                  borderLeftColor:   "rgb(7, 8, 9)", borderLeftWidth:   "3px",
                  borderRightColor:  "rgb(7, 8, 9)", borderRightWidth:  "3px",
@@ -422,12 +421,12 @@
   { desc:   "a Keyframe sequence where greater shorthand precedes lesser shorthand",
     input:  [{ offset: 0, border: "2px dotted rgb(4, 5, 6)", borderLeft: "1px solid rgb(1, 2, 3)" },
              { offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
-    output: [{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
+    output: [{ offset: 0, computedOffset: 0, easing: "linear",
                  borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
                  borderLeftColor:   "rgb(1, 2, 3)", borderLeftWidth:   "1px",
                  borderRightColor:  "rgb(4, 5, 6)", borderRightWidth:  "2px",
                  borderTopColor:    "rgb(4, 5, 6)", borderTopWidth:    "2px" },
-             { offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
+             { offset: 1, computedOffset: 1, easing: "linear",
                  borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
                  borderLeftColor:   "rgb(7, 8, 9)", borderLeftWidth:   "3px",
                  borderRightColor:  "rgb(7, 8, 9)", borderRightWidth:  "3px",
@@ -448,6 +447,29 @@
      " roundtrips");
 });
 
+var gInvalidEasingInKeyframeSequenceTests = [
+  { desc:   "a blank easing",
+    input:  [{ easing: "" }] },
+  { desc:   "an unrecognized easing",
+    input:  [{ easing: "unrecognized" }] },
+  { desc:   "an 'initial' easing",
+    input:  [{ easing: "initial" }] },
+  { desc:   "an 'inherit' easing",
+    input:  [{ easing: "inherit" }] },
+  { desc:   "a variable easing",
+    input:  [{ easing: "var(--x)" }] },
+  { desc:   "a multi-value easing",
+    input:  [{ easing: "ease-in-out, ease-out" }] }
+];
+
+gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) {
+  test(function(t) {
+    assert_throws(new TypeError, function() {
+      new KeyframeEffectReadOnly(target, subtest.input);
+    });
+  }, "Invalid easing [" + subtest.desc + "] in KeyframeSequence " +
+     "should be thrown");
+});
 
 test(function(t) {
   var effect = new KeyframeEffectReadOnly(target,
@@ -501,15 +523,6 @@
   { desc:     "an Infinity iterations",
     input:    { iterations: Infinity },
     expected: { iterations: Infinity } },
-  { desc:     "a negative Infinity iterations",
-    input:    { iterations: -Infinity },
-    expected: { iterations: -Infinity } },
-  { desc:     "a NaN iterations",
-    input:    { iterations: NaN },
-    expected: { iterations: NaN } },
-  { desc:     "a negative iterations",
-    input:    { iterations: -1 },
-    expected: { iterations: -1 } },
   { desc:     "an auto fill",
     input:    { fill: "auto" },
     expected: { fill: "auto" } },
@@ -566,6 +579,33 @@
     expected: { name: "TypeError" } },
   { desc:     "a string duration",
     input:    { duration: "merrychristmas" },
+    expected: { name: "TypeError" } },
+  { desc:     "a negative Infinity iterations",
+    input:    { iterations: -Infinity},
+    expected: { name: "TypeError" } },
+  { desc:     "a NaN iterations",
+    input:    { iterations: NaN },
+    expected: { name: "TypeError" } },
+  { desc:     "a negative iterations",
+    input:    { iterations: -1 },
+    expected: { name: "TypeError" } },
+  { desc:     "a blank easing",
+    input:    { easing: "" },
+    expected: { name: "TypeError" } },
+  { desc:     "an unrecognized easing",
+    input:    { easing: "unrecognised" },
+    expected: { name: "TypeError" } },
+  { desc:     "an 'initial' easing",
+    input:    { easing: "initial" },
+    expected: { name: "TypeError" } },
+  { desc:     "an 'inherit' easing",
+    input:    { easing: "inherit" },
+    expected: { name: "TypeError" } },
+  { desc:     "a variable easing",
+    input:    { easing: "var(--x)" },
+    expected: { name: "TypeError" } },
+  { desc:     "a multi-value easing",
+    input:    { easing: "ease-in-out, ease-out" },
     expected: { name: "TypeError" } }
 ];
 
@@ -573,7 +613,7 @@
   test(function(t) {
     assert_throws(stest.expected, function() {
       new KeyframeEffectReadOnly(target,
-                                 {left: ["10px", "20px"]},
+                                 { left: ["10px", "20px"] },
                                  stest.input);
     });
   }, "Invalid KeyframeEffectReadOnly option by " + stest.desc);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing-expected.txt
index 2f6daba..89474c6e 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing-expected.txt
@@ -20,5 +20,17 @@
 FAIL effect easing which produces values greater than 1 and the tangent on the upper boundary is infinity with keyframe easing producing values greater than 1 Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
 FAIL effect easing produces negative values with keyframe easing producing negative values Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
 FAIL effect easing which produces negative values and the tangent on the lower boundary is infinity with keyframe easing producing negative values Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
+FAIL Test bounds point of step-start easing animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing with compositor animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing with reverse direction animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing with iterationStart not at a transition point animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing with iterationStart and delay animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing with iterationStart and reverse direction animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step(4, start) easing with iterationStart 0.75 and delay animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing with alternate direction animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing with alternate-reverse direction animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-start easing in keyframe animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-end easing with iterationStart and delay animation.effect.getComputedTiming is not a function
+FAIL Test bounds point of step-end easing with iterationStart not at a transition point animation.effect.getComputedTiming is not a function
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing.html
index 9e518efb..76a9bd0 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/effect-easing.html
@@ -434,5 +434,287 @@
    'the lower boundary is infinity with keyframe easing producing ' +
    'negative values');
 
+var gStepTimingFunctionTests = [
+  {
+    description: 'Test bounds point of step-start easing',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0 },
+                  { currentTime: 999,  progress: 0 },
+                  { currentTime: 1000, progress: 0.5 },
+                  { currentTime: 1499, progress: 0.5 },
+                  { currentTime: 1500, progress: 1 },
+                  { currentTime: 2000, progress: 1 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing with compositor',
+    keyframe:   [ { opacity: 0 },
+                  { opacity: 1 } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0 },
+                  { currentTime: 999,  progress: 0 },
+                  { currentTime: 1000, progress: 0.5 },
+                  { currentTime: 1499, progress: 0.5 },
+                  { currentTime: 1500, progress: 1 },
+                  { currentTime: 2000, progress: 1 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing with reverse direction',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                  direction: 'reverse',
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 1 },
+                  { currentTime: 1001, progress: 1 },
+                  { currentTime: 1500, progress: 1 },
+                  { currentTime: 1501, progress: 0.5 },
+                  { currentTime: 2000, progress: 0 },
+                  { currentTime: 2500, progress: 0 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing ' +
+                 'with iterationStart not at a transition point',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                  iterationStart: 0.25,
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0.5 },
+                  { currentTime: 999,  progress: 0.5 },
+                  { currentTime: 1000, progress: 0.5 },
+                  { currentTime: 1249, progress: 0.5 },
+                  { currentTime: 1250, progress: 1 },
+                  { currentTime: 1749, progress: 1 },
+                  { currentTime: 1750, progress: 0.5 },
+                  { currentTime: 2000, progress: 0.5 },
+                  { currentTime: 2500, progress: 0.5 },
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing ' +
+                 'with iterationStart and delay',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                  iterationStart: 0.5,
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0.5 },
+                  { currentTime: 999,  progress: 0.5 },
+                  { currentTime: 1000, progress: 1 },
+                  { currentTime: 1499, progress: 1 },
+                  { currentTime: 1500, progress: 0.5 },
+                  { currentTime: 2000, progress: 1 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing ' +
+                 'with iterationStart and reverse direction',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                  iterationStart: 0.5,
+                  direction: 'reverse',
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 1 },
+                  { currentTime: 1000, progress: 1 },
+                  { currentTime: 1001, progress: 0.5 },
+                  { currentTime: 1499, progress: 0.5 },
+                  { currentTime: 1500, progress: 1 },
+                  { currentTime: 1999, progress: 1 },
+                  { currentTime: 2000, progress: 0.5 },
+                  { currentTime: 2500, progress: 0.5 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step(4, start) easing ' +
+                 'with iterationStart 0.75 and delay',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  duration: 1000,
+                  fill: 'both',
+                  delay: 1000,
+                  iterationStart: 0.75,
+                  easing: 'steps(4, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0.75 },
+                  { currentTime: 999,  progress: 0.75 },
+                  { currentTime: 1000, progress: 1 },
+                  { currentTime: 2000, progress: 1 },
+                  { currentTime: 2500, progress: 1 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing ' +
+                 'with alternate direction',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  duration: 1000,
+                  fill: 'both',
+                  delay: 1000,
+                  iterations: 2,
+                  iterationStart: 1.5,
+                  direction: 'alternate',
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 1 },
+                  { currentTime: 1000, progress: 1 },
+                  { currentTime: 1001, progress: 0.5 },
+                  { currentTime: 2999, progress: 1 },
+                  { currentTime: 3000, progress: 0.5 },
+                  { currentTime: 3500, progress: 0.5 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing ' +
+                 'with alternate-reverse direction',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  duration: 1000,
+                  fill: 'both',
+                  delay: 1000,
+                  iterations: 2,
+                  iterationStart: 0.5,
+                  direction: 'alternate-reverse',
+                  easing: 'steps(2, start)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 1 },
+                  { currentTime: 1000, progress: 1 },
+                  { currentTime: 1001, progress: 0.5 },
+                  { currentTime: 2999, progress: 1 },
+                  { currentTime: 3000, progress: 0.5 },
+                  { currentTime: 3500, progress: 0.5 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-start easing in keyframe',
+    keyframe:   [ { width: '0px', easing: 'steps(2, start)' },
+                  { width: '100px' } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0,     width: '0px' },
+                  { currentTime: 999,  progress: 0,     width: '0px' },
+                  { currentTime: 1000, progress: 0,     width: '50px' },
+                  { currentTime: 1499, progress: 0.499, width: '50px' },
+                  { currentTime: 1500, progress: 0.5,   width: '100px' },
+                  { currentTime: 2000, progress: 1,     width: '100px' },
+                  { currentTime: 2500, progress: 1,     width: '100px' }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-end easing ' +
+                 'with iterationStart and delay',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  duration: 1000,
+                  fill: 'both',
+                  delay: 1000,
+                  iterationStart: 0.5,
+                  easing: 'steps(2, end)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0 },
+                  { currentTime: 999,  progress: 0 },
+                  { currentTime: 1000, progress: 0.5 },
+                  { currentTime: 1499, progress: 0.5 },
+                  { currentTime: 1500, progress: 0 },
+                  { currentTime: 1999, progress: 0 },
+                  { currentTime: 2000, progress: 0.5 },
+                  { currentTime: 2500, progress: 0.5 }
+                ]
+  },
+  {
+    description: 'Test bounds point of step-end easing ' +
+                 'with iterationStart not at a transition point',
+    keyframe:   [ { width: '0px' },
+                  { width: '100px' } ],
+    effect:     {
+                  delay: 1000,
+                  duration: 1000,
+                  fill: 'both',
+                  iterationStart: 0.75,
+                  easing: 'steps(2, end)'
+                },
+    conditions: [
+                  { currentTime: 0,    progress: 0.5 },
+                  { currentTime: 999,  progress: 0.5 },
+                  { currentTime: 1000, progress: 0.5 },
+                  { currentTime: 1249, progress: 0.5 },
+                  { currentTime: 1250, progress: 0 },
+                  { currentTime: 1749, progress: 0 },
+                  { currentTime: 1750, progress: 0.5 },
+                  { currentTime: 2000, progress: 0.5 },
+                  { currentTime: 2500, progress: 0.5 },
+                ]
+  }
+]
+
+gStepTimingFunctionTests.forEach(function(options) {
+  test(function(t) {
+    var target = createDiv(t);
+    var animation = target.animate(options.keyframe, options.effect);
+    options.conditions.forEach(function(condition) {
+      animation.currentTime = condition.currentTime;
+      if (typeof condition.progress !== 'undefined') {
+        assert_equals(animation.effect.getComputedTiming().progress,
+                      condition.progress,
+                      'Progress at ' + animation.currentTime + 'ms');
+      }
+      if (typeof condition.width !== 'undefined') {
+        assert_equals(getComputedStyle(target).width,
+                      condition.width,
+                      'Progress at ' + animation.currentTime + 'ms');
+      }
+    });
+  }, options.description);
+});
+
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming-expected.txt
index 4324d72..e5882c0 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming-expected.txt
@@ -7,9 +7,6 @@
 FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an Infinity duration KeyframeEffectReadOnly is not defined
 FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an auto duration KeyframeEffectReadOnly is not defined
 FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an Infinity iterations KeyframeEffectReadOnly is not defined
-FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by a negative Infinity iterations KeyframeEffectReadOnly is not defined
-FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by a NaN iterations KeyframeEffectReadOnly is not defined
-FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by a negative iterations KeyframeEffectReadOnly is not defined
 FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by an auto fill KeyframeEffectReadOnly is not defined
 FAIL values of getComputedTiming() when a KeyframeEffectReadOnly is constructed by a forwards fill KeyframeEffectReadOnly is not defined
 FAIL getComputedTiming().activeDuration for an empty KeyframeEffectOptions object KeyframeEffectReadOnly is not defined
@@ -27,7 +24,6 @@
 FAIL getComputedTiming().activeDuration for an infinite duration and fractional iteration count KeyframeEffectReadOnly is not defined
 FAIL getComputedTiming().activeDuration for an infinite duration and infinite iteration count KeyframeEffectReadOnly is not defined
 FAIL getComputedTiming().activeDuration for an infinite duration and zero iteration count KeyframeEffectReadOnly is not defined
-FAIL getComputedTiming().activeDuration for a non-zero duration and invalid iteration count KeyframeEffectReadOnly is not defined
 FAIL getComputedTiming().endTime for an empty KeyframeEffectOptions object KeyframeEffectReadOnly is not defined
 FAIL getComputedTiming().endTime for a non-zero duration and default iteration count KeyframeEffectReadOnly is not defined
 FAIL getComputedTiming().endTime for a non-zero duration and non-default iteration count KeyframeEffectReadOnly is not defined
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html
index 5f4c602..5641b20 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/keyframe-effect/getComputedTiming.html
@@ -62,15 +62,6 @@
   { desc:     "an Infinity iterations",
     input:    { iterations: Infinity },
     expected: { iterations: Infinity } },
-  { desc:     "a negative Infinity iterations",
-    input:    { iterations: -Infinity},
-    expected: { iterations: 1 } },
-  { desc:     "a NaN iterations",
-    input:    { iterations: NaN },
-    expected: { iterations: 1 } },
-  { desc:     "a negative iterations",
-    input:    { iterations: -1 },
-    expected: { iterations: 1 } },
   { desc:     "an auto fill",
     input:    { fill: "auto" },
     expected: { fill: "none" } },
@@ -152,10 +143,7 @@
     expected: Infinity },
   { desc:     "an infinite duration and zero iteration count",
     input:    { duration: Infinity, iterations: 0 },
-    expected: 0 },
-  { desc:     "a non-zero duration and invalid iteration count",
-    input:    { duration: 1000, iterations: "cabbage" },
-    expected: 1000 }
+    expected: 0 }
 ];
 
 gActiveDurationTests.forEach(function(stest) {
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/testcommon.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/testcommon.js
index e7179cc1..ab54202f 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/testcommon.js
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/web-animations/testcommon.js
@@ -9,29 +9,7 @@
  */
 
 "use strict";
-
-var ANIMATION_END_TIME = 1000;
-var ANIMATION_TOP_DEFAULT = 300;
-var ANIMATION_TOP_0 = 10;
-var ANIMATION_TOP_0_5 = 100;
-var ANIMATION_TOP_1 = 200;
-
-var KEYFRAMES = [ {
-  top : ANIMATION_TOP_0 + 'px',
-  offset : 0
-}, {
-  top : ANIMATION_TOP_0_5 + 'px',
-  offset : 1 / 2
-}, {
-  top : ANIMATION_TOP_1 + 'px',
-  offset : 1
-} ];
-
-// creates new animation for given target
-function newAnimation(animationTarget) {
-  animationTarget.style.top = ANIMATION_TOP_DEFAULT + 'px';
-  return new Animation(animationTarget, KEYFRAMES, ANIMATION_END_TIME);
-}
+var MS_PER_SEC = 1000;
 
 // creates div element, appends it to the document body and
 // removes the created element during test cleanup
@@ -91,11 +69,6 @@
   return anim.effect.target;
 }
 
-// Returns the type name of given object
-function type(object) {
-  return Object.prototype.toString.call(object).slice(8, -1);
-}
-
 // Convert px unit value to a Number
 function pxToNum(str) {
   return Number(String(str).match(/^(-?[\d.]+)px$/)[1]);
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/event_setattribute.js b/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/event_setattribute.js
index 9d8e328..8070938 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/event_setattribute.js
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/event_setattribute.js
@@ -10,6 +10,9 @@
         function step0(msg)
         {
             iframe.onload = t.step_func(step1);
+            // Null out the existing handler eventTestHarness.js set up;
+            // otherwise this test won't be testing much of anything useful.
+            iframe.contentWindow.onstorage = null;
             iframe.src = "resources/event_setattribute_handler.html";
         }
 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/resources/event_setattribute_handler.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/resources/event_setattribute_handler.html
index f5d6f8a0..b9e2f04 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/resources/event_setattribute_handler.html
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/webstorage/resources/event_setattribute_handler.html
@@ -8,7 +8,7 @@
     window.parent.storageEventList.push(e);
 }
 
-document.body.setAttribute("onstorage", "handleStorageEvent(window.event);");
+document.body.setAttribute("onstorage", "handleStorageEvent(event);");
 
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-change-invalidation-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-change-invalidation-expected.txt
index 0f87c27..bb820d0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-change-invalidation-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-change-invalidation-expected.txt
@@ -12,6 +12,11 @@
           "reason": "bounds change"
         },
         {
+          "object": "LayoutBlockFlow BODY",
+          "rect": [8, 108, 789, 5],
+          "reason": "incremental"
+        },
+        {
           "object": "LayoutBlockFlow A id='link'",
           "rect": [30, 83, 767, 30],
           "reason": "style change"
@@ -22,16 +27,9 @@
           "reason": "bounds change"
         },
         {
-          "object": "InlineBox",
-          "reason": "full"
-        },
-        {
-          "object": "InlineTextBox 'Lorem Ipsum'",
-          "reason": "full"
-        },
-        {
-          "object": "RootInlineBox",
-          "reason": "full"
+          "object": "LayoutBlockFlow BODY",
+          "rect": [792, 16, 5, 97],
+          "reason": "incremental"
         },
         {
           "object": "RootInlineBox",
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-clip-change-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-clip-change-expected.txt
index b9a35c2..ea644b4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-clip-change-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-clip-change-expected.txt
@@ -18,19 +18,11 @@
         },
         {
           "object": "InlineTextBox 'Lorem Ipsum'",
-          "reason": "full"
-        },
-        {
-          "object": "InlineTextBox 'Lorem Ipsum'",
           "reason": "style change"
         },
         {
           "object": "RootInlineBox",
           "reason": "full"
-        },
-        {
-          "object": "RootInlineBox",
-          "reason": "full"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-continuations-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-continuations-expected.png
index 54ffd6b..cc57b61 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-continuations-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/outline-continuations-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp
index 191407e..8d4873a 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/BindingSecurity.cpp
@@ -34,6 +34,7 @@
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrame.h"
+#include "core/frame/Location.h"
 #include "core/frame/Settings.h"
 #include "core/html/HTMLFrameElementBase.h"
 #include "core/workers/MainThreadWorkletGlobalScope.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.cpp b/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.cpp
index cdd62e4..34e9b52 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.cpp
@@ -7,6 +7,7 @@
 #include "bindings/core/v8/ScriptSourceCode.h"
 #include "bindings/core/v8/V8BindingMacros.h"
 #include "bindings/core/v8/V8ScriptRunner.h"
+#include "core/frame/Location.h"
 #include "core/html/parser/HTMLParserThread.h"
 #include "platform/TraceEvent.h"
 #include "wtf/text/StringUTF8Adaptor.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
index 82017481..e34b233 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
@@ -4,10 +4,7 @@
 
 #include "bindings/core/v8/ScriptValueSerializer.h"
 
-#include "bindings/core/v8/Transferable.h"
-#include "bindings/core/v8/TransferableArrayBuffer.h"
-#include "bindings/core/v8/TransferableImageBitmap.h"
-#include "bindings/core/v8/TransferableMessagePort.h"
+#include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/V8ArrayBuffer.h"
 #include "bindings/core/v8/V8ArrayBufferView.h"
 #include "bindings/core/v8/V8Blob.h"
@@ -689,7 +686,7 @@
     return object->InternalFieldCount();
 }
 
-ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer, TransferableArray* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
+ScriptValueSerializer::ScriptValueSerializer(SerializedScriptValueWriter& writer, const Transferables* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
     : m_scriptState(scriptState)
     , m_writer(writer)
     , m_tryCatch(tryCatch)
@@ -700,29 +697,36 @@
     , m_blobDataHandles(blobDataHandles)
 {
     ASSERT(!tryCatch.HasCaught());
+    if (transferables)
+        copyTransferables(*transferables);
+}
+
+void ScriptValueSerializer::copyTransferables(const Transferables& transferables)
+{
     v8::Local<v8::Object> creationContext = m_scriptState->context()->Global();
-    if (!transferables)
-        return;
-    if (auto* messagePorts = TransferableMessagePort::get(*transferables)) {
-        for (size_t i = 0; i < messagePorts->getArray().size(); i++) {
-            v8::Local<v8::Object> v8MessagePort = toV8Object(messagePorts->getArray().at(i).get(), creationContext, isolate());
-            m_transferredMessagePorts.set(v8MessagePort, i);
-        }
+
+    // Also kept in separate ObjectPools, iterate and copy the contents
+    // of each kind of transferable vector.
+
+    const auto& messagePorts = transferables.messagePorts;
+    for (size_t i = 0; i < messagePorts.size(); ++i) {
+        v8::Local<v8::Object> v8MessagePort = toV8Object(messagePorts[i].get(), creationContext, isolate());
+        m_transferredMessagePorts.set(v8MessagePort, i);
     }
-    if (auto* arrayBuffers = TransferableArrayBuffer::get(*transferables)) {
-        for (size_t i = 0; i < arrayBuffers->getArray().size(); i++)  {
-            v8::Local<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->getArray().at(i).get(), creationContext, isolate());
-            // Coalesce multiple occurences of the same buffer to the first index.
-            if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
-                m_transferredArrayBuffers.set(v8ArrayBuffer, i);
-        }
+
+    const auto& arrayBuffers = transferables.arrayBuffers;
+    for (size_t i = 0; i < arrayBuffers.size(); ++i)  {
+        v8::Local<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers[i].get(), creationContext, isolate());
+        // Coalesce multiple occurences of the same buffer to the first index.
+        if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
+            m_transferredArrayBuffers.set(v8ArrayBuffer, i);
     }
-    if (auto* imageBitmaps = TransferableImageBitmap::get(*transferables)) {
-        for (size_t i = 0; i < imageBitmaps->getArray().size(); i++) {
-            v8::Local<v8::Object> v8ImageBitmap = toV8Object(imageBitmaps->getArray().at(i).get(), creationContext, isolate());
-            if (!m_transferredImageBitmaps.contains(v8ImageBitmap))
-                m_transferredImageBitmaps.set(v8ImageBitmap, i);
-        }
+
+    const auto& imageBitmaps = transferables.imageBitmaps;
+    for (size_t i = 0; i < imageBitmaps.size(); ++i) {
+        v8::Local<v8::Object> v8ImageBitmap = toV8Object(imageBitmaps[i].get(), creationContext, isolate());
+        if (!m_transferredImageBitmaps.contains(v8ImageBitmap))
+            m_transferredImageBitmaps.set(v8ImageBitmap, i);
     }
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
index a24cfe8..3540474b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
@@ -208,7 +208,7 @@
         JSException
     };
 
-    ScriptValueSerializer(SerializedScriptValueWriter&, TransferableArray*, WebBlobInfoArray*, BlobDataHandleMap& blobDataHandles, v8::TryCatch&, ScriptState*);
+    ScriptValueSerializer(SerializedScriptValueWriter&, const Transferables*, WebBlobInfoArray*, BlobDataHandleMap& blobDataHandles, v8::TryCatch&, ScriptState*);
     v8::Isolate* isolate() { return m_scriptState->isolate(); }
     v8::Local<v8::Context> context() { return m_scriptState->context(); }
 
@@ -431,6 +431,9 @@
     uint32_t nextObjectReference() const { return m_nextObjectReference; }
 
 private:
+
+    void copyTransferables(const Transferables&);
+
     RefPtr<ScriptState> m_scriptState;
     SerializedScriptValueWriter& m_writer;
     v8::TryCatch& m_tryCatch;
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
index 1d7b043..06080d99 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
@@ -36,14 +36,16 @@
 #include "bindings/core/v8/ScriptState.h"
 #include "bindings/core/v8/ScriptValueSerializer.h"
 #include "bindings/core/v8/SerializedScriptValueFactory.h"
-#include "bindings/core/v8/TransferableArrayBuffer.h"
-#include "bindings/core/v8/TransferableImageBitmap.h"
-#include "bindings/core/v8/TransferableMessagePort.h"
+#include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/V8ArrayBuffer.h"
 #include "bindings/core/v8/V8ImageBitmap.h"
 #include "bindings/core/v8/V8MessagePort.h"
 #include "bindings/core/v8/V8SharedArrayBuffer.h"
+#include "core/dom/DOMArrayBuffer.h"
+#include "core/dom/DOMSharedArrayBuffer.h"
 #include "core/dom/ExceptionCode.h"
+#include "core/dom/MessagePort.h"
+#include "core/frame/ImageBitmap.h"
 #include "platform/SharedBuffer.h"
 #include "platform/blob/BlobData.h"
 #include "platform/heap/Handle.h"
@@ -55,6 +57,22 @@
 
 namespace blink {
 
+SerializedScriptValue::SerializedScriptValue()
+    : m_externallyAllocatedMemory(0)
+{
+}
+
+SerializedScriptValue::~SerializedScriptValue()
+{
+    // If the allocated memory was not registered before, then this class is likely
+    // used in a context other than Worker's onmessage environment and the presence of
+    // current v8 context is not guaranteed. Avoid calling v8 then.
+    if (m_externallyAllocatedMemory) {
+        ASSERT(v8::Isolate::GetCurrent());
+        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
+    }
+}
+
 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
 {
     SerializedScriptValueWriter writer;
@@ -82,11 +100,6 @@
     }
 }
 
-SerializedScriptValue::SerializedScriptValue()
-    : m_externallyAllocatedMemory(0)
-{
-}
-
 static void acculumateArrayBuffersForAllWorlds(v8::Isolate* isolate, DOMArrayBuffer* object, Vector<v8::Local<v8::ArrayBuffer>, 4>& buffers)
 {
     if (isMainThread()) {
@@ -104,62 +117,62 @@
     }
 }
 
-PassOwnPtr<SerializedScriptValue::ImageBitmapContentsArray> SerializedScriptValue::createImageBitmaps(v8::Isolate* isolate, TransferableImageBitmap* transferableImageBitmaps, ExceptionState& exceptionState)
+void SerializedScriptValue::transferImageBitmaps(v8::Isolate* isolate, const ImageBitmapArray& imageBitmaps, ExceptionState& exceptionState)
 {
-    HeapVector<Member<ImageBitmap>, 1> imageBitmaps = transferableImageBitmaps->getArray();
-    ASSERT(imageBitmaps.size());
+    if (!imageBitmaps.size())
+        return;
 
-    for (size_t i = 0; i < imageBitmaps.size(); i++) {
+    for (size_t i = 0; i < imageBitmaps.size(); ++i) {
         if (imageBitmaps[i]->isNeutered()) {
             exceptionState.throwDOMException(DataCloneError, "ImageBitmap at index " + String::number(i) + " is already neutered.");
-            return nullptr;
+            return;
         }
     }
 
     OwnPtr<ImageBitmapContentsArray> contents = adoptPtr(new ImageBitmapContentsArray);
     HeapHashSet<Member<ImageBitmap>> visited;
-    for (size_t i = 0; i < imageBitmaps.size(); i++) {
-        if (visited.contains(imageBitmaps[i].get()))
+    for (size_t i = 0; i < imageBitmaps.size(); ++i) {
+        if (visited.contains(imageBitmaps[i]))
             continue;
-        visited.add(imageBitmaps[i].get());
+        visited.add(imageBitmaps[i]);
         contents->append(imageBitmaps[i]->transfer());
     }
-    return contents.release();
+    m_imageBitmapContentsArray = contents.release();
 }
 
 
-PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::createArrayBuffers(v8::Isolate* isolate, TransferableArrayBuffer* transferableArrayBuffers, ExceptionState& exceptionState)
+void SerializedScriptValue::transferArrayBuffers(v8::Isolate* isolate, const ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState)
 {
-    HeapVector<Member<DOMArrayBufferBase>, 1> arrayBuffers = transferableArrayBuffers->getArray();
-    ASSERT(arrayBuffers.size());
+    if (!arrayBuffers.size())
+        return;
 
-    for (size_t i = 0; i < arrayBuffers.size(); i++) {
+    for (size_t i = 0; i < arrayBuffers.size(); ++i) {
         if (arrayBuffers[i]->isNeutered()) {
             exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered.");
-            return nullptr;
+            return;
         }
     }
 
     OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
 
     HeapHashSet<Member<DOMArrayBufferBase>> visited;
-    for (size_t i = 0; i < arrayBuffers.size(); i++) {
-        if (visited.contains(arrayBuffers[i].get()))
+    for (size_t i = 0; i < arrayBuffers.size(); ++i) {
+        if (visited.contains(arrayBuffers[i]))
             continue;
-        visited.add(arrayBuffers[i].get());
+        visited.add(arrayBuffers[i]);
 
         if (arrayBuffers[i]->isShared()) {
             bool result = arrayBuffers[i]->shareContentsWith(contents->at(i));
             if (!result) {
                 exceptionState.throwDOMException(DataCloneError, "SharedArrayBuffer at index " + String::number(i) + " could not be transferred.");
-                return nullptr;
+                return;
             }
         } else {
             Vector<v8::Local<v8::ArrayBuffer>, 4> bufferHandles;
             v8::HandleScope handleScope(isolate);
             acculumateArrayBuffersForAllWorlds(isolate, static_cast<DOMArrayBuffer*>(arrayBuffers[i].get()), bufferHandles);
             bool isNeuterable = true;
-            for (size_t j = 0; j < bufferHandles.size(); j++)
+            for (size_t j = 0; j < bufferHandles.size(); ++j)
                 isNeuterable &= bufferHandles[j]->IsNeuterable();
 
             DOMArrayBufferBase* toTransfer = arrayBuffers[i];
@@ -168,17 +181,16 @@
             bool result = toTransfer->transfer(contents->at(i));
             if (!result) {
                 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred.");
-                return nullptr;
+                return;
             }
 
             if (isNeuterable)
-                for (size_t j = 0; j < bufferHandles.size(); j++)
+                for (size_t j = 0; j < bufferHandles.size(); ++j)
                     bufferHandles[j]->Neuter();
         }
 
     }
-
-    return contents.release();
+    m_arrayBufferContentsArray = contents.release();
 }
 
 SerializedScriptValue::SerializedScriptValue(const String& wireData)
@@ -197,12 +209,10 @@
     return SerializedScriptValueFactory::instance().deserialize(this, isolate, messagePorts, blobInfo);
 }
 
-bool SerializedScriptValue::extractTransferables(v8::Isolate* isolate, v8::Local<v8::Value> value, int argumentIndex, TransferableArray& transferables, ExceptionState& exceptionState)
+bool SerializedScriptValue::extractTransferables(v8::Isolate* isolate, v8::Local<v8::Value> value, int argumentIndex, Transferables& transferables, ExceptionState& exceptionState)
 {
-    if (isUndefinedOrNull(value)) {
-        transferables.resize(0);
+    if (isUndefinedOrNull(value))
         return true;
-    }
 
     uint32_t length = 0;
     if (value->IsArray()) {
@@ -214,52 +224,48 @@
         return false;
     }
 
-    v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);
+    v8::Local<v8::Object> transferableArray = v8::Local<v8::Object>::Cast(value);
 
-    // Validate the passed array of transferrables.
+    // Validate the passed array of transferables.
     for (unsigned i = 0; i < length; ++i) {
-        v8::Local<v8::Value> transferrable;
-        if (!transferrables->Get(isolate->GetCurrentContext(), i).ToLocal(&transferrable))
+        v8::Local<v8::Value> transferableObject;
+        if (!transferableArray->Get(isolate->GetCurrentContext(), i).ToLocal(&transferableObject))
             return false;
         // Validation of non-null objects, per HTML5 spec 10.3.3.
-        if (isUndefinedOrNull(transferrable)) {
-            exceptionState.throwTypeError("Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value.");
+        if (isUndefinedOrNull(transferableObject)) {
+            exceptionState.throwTypeError("Value at index " + String::number(i) + " is an untransferable " + (transferableObject->IsUndefined() ? "'undefined'" : "'null'") + " value.");
             return false;
         }
         // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
-        if (V8MessagePort::hasInstance(transferrable, isolate)) {
-            MessagePort* port = V8MessagePort::toImpl(v8::Local<v8::Object>::Cast(transferrable));
-            TransferableMessagePort* ports = TransferableMessagePort::ensure(transferables);
+        if (V8MessagePort::hasInstance(transferableObject, isolate)) {
+            MessagePort* port = V8MessagePort::toImpl(v8::Local<v8::Object>::Cast(transferableObject));
             // Check for duplicate MessagePorts.
-            if (ports->contains(port)) {
+            if (transferables.messagePorts.contains(port)) {
                 exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port.");
                 return false;
             }
-            ports->append(port);
-        } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) {
-            DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(v8::Local<v8::Object>::Cast(transferrable));
-            TransferableArrayBuffer* arrayBuffers = TransferableArrayBuffer::ensure(transferables);
-            if (arrayBuffers->contains(arrayBuffer)) {
+            transferables.messagePorts.append(port);
+        } else if (V8ArrayBuffer::hasInstance(transferableObject, isolate)) {
+            DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(v8::Local<v8::Object>::Cast(transferableObject));
+            if (transferables.arrayBuffers.contains(arrayBuffer)) {
                 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer.");
                 return false;
             }
-            arrayBuffers->append(arrayBuffer);
-        } else if (V8SharedArrayBuffer::hasInstance(transferrable, isolate)) {
-            DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(v8::Local<v8::Object>::Cast(transferrable));
-            TransferableArrayBuffer* arrayBuffers = TransferableArrayBuffer::ensure(transferables);
-            if (arrayBuffers->contains(sharedArrayBuffer)) {
+            transferables.arrayBuffers.append(arrayBuffer);
+        } else if (V8SharedArrayBuffer::hasInstance(transferableObject, isolate)) {
+            DOMSharedArrayBuffer* sharedArrayBuffer = V8SharedArrayBuffer::toImpl(v8::Local<v8::Object>::Cast(transferableObject));
+            if (transferables.arrayBuffers.contains(sharedArrayBuffer)) {
                 exceptionState.throwDOMException(DataCloneError, "SharedArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier SharedArrayBuffer.");
                 return false;
             }
-            arrayBuffers->append(sharedArrayBuffer);
-        } else if (V8ImageBitmap::hasInstance(transferrable, isolate)) {
-            ImageBitmap* imageBitmap = V8ImageBitmap::toImpl(v8::Local<v8::Object>::Cast(transferrable));
-            TransferableImageBitmap* imageBitmaps = TransferableImageBitmap::ensure(transferables);
-            if (imageBitmaps->contains(imageBitmap)) {
+            transferables.arrayBuffers.append(sharedArrayBuffer);
+        } else if (V8ImageBitmap::hasInstance(transferableObject, isolate)) {
+            ImageBitmap* imageBitmap = V8ImageBitmap::toImpl(v8::Local<v8::Object>::Cast(transferableObject));
+            if (transferables.imageBitmaps.contains(imageBitmap)) {
                 exceptionState.throwDOMException(DataCloneError, "ImageBitmap at index " + String::number(i) + " is a duplicate of an earlier ImageBitmap.");
                 return false;
             }
-            imageBitmaps->append(imageBitmap);
+            transferables.imageBitmaps.append(imageBitmap);
         } else {
             exceptionState.throwTypeError("Value at index " + String::number(i) + " does not have a transferable type.");
             return false;
@@ -281,25 +287,4 @@
     return m_arrayBufferContentsArray && !m_arrayBufferContentsArray->isEmpty();
 }
 
-SerializedScriptValue::~SerializedScriptValue()
-{
-    // If the allocated memory was not registered before, then this class is likely
-    // used in a context other then Worker's onmessage environment and the presence of
-    // current v8 context is not guaranteed. Avoid calling v8 then.
-    if (m_externallyAllocatedMemory) {
-        ASSERT(v8::Isolate::GetCurrent());
-        v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externallyAllocatedMemory);
-    }
-}
-
-void SerializedScriptValue::transferArrayBuffers(v8::Isolate* isolate, TransferableArrayBuffer* transferableArrayBuffers, ExceptionState& exceptionState)
-{
-    m_arrayBufferContentsArray = createArrayBuffers(isolate, transferableArrayBuffers, exceptionState);
-}
-
-void SerializedScriptValue::transferImageBitmaps(v8::Isolate* isolate, TransferableImageBitmap* transferableImageBitmaps, ExceptionState& exceptionState)
-{
-    m_imageBitmapContentsArray = createImageBitmaps(isolate, transferableImageBitmaps, exceptionState);
-}
-
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
index f3e130d..259a22e 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.h
@@ -32,7 +32,7 @@
 #define SerializedScriptValue_h
 
 #include "bindings/core/v8/ScriptValue.h"
-#include "bindings/core/v8/Transferable.h"
+#include "bindings/core/v8/Transferables.h"
 #include "core/CoreExport.h"
 #include "wtf/HashMap.h"
 #include "wtf/ThreadSafeRefCounted.h"
@@ -47,17 +47,13 @@
 namespace blink {
 
 class BlobDataHandle;
+class Transferables;
 class ExceptionState;
 class StaticBitmapImage;
-class TransferableArrayBuffer;
-class TransferableImageBitmap;
-class MessagePort;
 class WebBlobInfo;
 
-typedef HeapVector<Member<MessagePort>, 1> MessagePortArray;
 typedef HashMap<String, RefPtr<BlobDataHandle>> BlobDataHandleMap;
 typedef Vector<WebBlobInfo> WebBlobInfoArray;
-typedef HeapVector<Member<Transferable>> TransferableArray;
 
 class CORE_EXPORT SerializedScriptValue : public ThreadSafeRefCounted<SerializedScriptValue> {
 public:
@@ -92,7 +88,7 @@
     // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3
     // of the HTML5 spec and generates exceptions as appropriate.
     // Returns true if the array was filled, or false if the passed value was not of an appropriate type.
-    static bool extractTransferables(v8::Isolate*, v8::Local<v8::Value>, int, TransferableArray&, ExceptionState&);
+    static bool extractTransferables(v8::Isolate*, v8::Local<v8::Value>, int, Transferables&, ExceptionState&);
 
     // Informs the V8 about external memory allocated and owned by this object. Large values should contribute
     // to GC counters to eventually trigger a GC, otherwise flood of postMessage() can cause OOM.
@@ -118,14 +114,11 @@
     BlobDataHandleMap& blobDataHandles() { return m_blobDataHandles; }
     String& data() { return m_data; }
     void setData(const String& data) { m_data = data; }
-    void transferArrayBuffers(v8::Isolate*, TransferableArrayBuffer*, ExceptionState&);
-    void transferImageBitmaps(v8::Isolate*, TransferableImageBitmap*, ExceptionState&);
+    void transferArrayBuffers(v8::Isolate*, const ArrayBufferArray&, ExceptionState&);
+    void transferImageBitmaps(v8::Isolate*, const ImageBitmapArray&, ExceptionState&);
     ArrayBufferContentsArray* getArrayBufferContentsArray() { return m_arrayBufferContentsArray.get(); }
     ImageBitmapContentsArray* getImageBitmapContentsArray() { return m_imageBitmapContentsArray.get(); }
 
-    static PassOwnPtr<ArrayBufferContentsArray> createArrayBuffers(v8::Isolate*, TransferableArrayBuffer*, ExceptionState&);
-    static PassOwnPtr<ImageBitmapContentsArray> createImageBitmaps(v8::Isolate*, TransferableImageBitmap*, ExceptionState&);
-
 private:
     String m_data;
     OwnPtr<ArrayBufferContentsArray> m_arrayBufferContentsArray;
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp
index 9c0378f5..a3fd0a55 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp
@@ -6,9 +6,10 @@
 
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/ScriptValueSerializer.h"
-#include "bindings/core/v8/TransferableArrayBuffer.h"
-#include "bindings/core/v8/TransferableImageBitmap.h"
-#include "bindings/core/v8/TransferableMessagePort.h"
+#include "bindings/core/v8/Transferables.h"
+#include "core/dom/DOMArrayBuffer.h"
+#include "core/dom/MessagePort.h"
+#include "core/frame/ImageBitmap.h"
 #include "wtf/ByteOrder.h"
 #include "wtf/text/StringBuffer.h"
 
@@ -16,7 +17,7 @@
 
 SerializedScriptValueFactory* SerializedScriptValueFactory::m_instance = 0;
 
-PassRefPtr<SerializedScriptValue> SerializedScriptValueFactory::create(v8::Isolate* isolate, v8::Local<v8::Value> value, TransferableArray* transferables, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState)
+PassRefPtr<SerializedScriptValue> SerializedScriptValueFactory::create(v8::Isolate* isolate, v8::Local<v8::Value> value, Transferables* transferables, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState)
 {
     RefPtr<SerializedScriptValue> serializedValue = create();
     SerializedScriptValueWriter writer;
@@ -47,7 +48,7 @@
     return serializedValue.release();
 }
 
-PassRefPtr<SerializedScriptValue> SerializedScriptValueFactory::create(v8::Isolate* isolate, v8::Local<v8::Value> value, TransferableArray* transferables, ExceptionState& exceptionState)
+PassRefPtr<SerializedScriptValue> SerializedScriptValueFactory::create(v8::Isolate* isolate, v8::Local<v8::Value> value, Transferables* transferables, ExceptionState& exceptionState)
 {
     return create(isolate, value, transferables, 0, exceptionState);
 }
@@ -102,28 +103,25 @@
     return adoptRef(new SerializedScriptValue());
 }
 
-void SerializedScriptValueFactory::transferData(SerializedScriptValue* serializedValue, SerializedScriptValueWriter& writer, TransferableArray* transferables, ExceptionState& exceptionState, v8::Isolate* isolate)
+void SerializedScriptValueFactory::transferData(SerializedScriptValue* serializedValue, SerializedScriptValueWriter& writer, Transferables* transferables, ExceptionState& exceptionState, v8::Isolate* isolate)
 {
     serializedValue->setData(writer.takeWireString());
     ASSERT(serializedValue->data().impl()->hasOneRef());
     if (!transferables)
         return;
-    if (auto* imageBitmaps = TransferableImageBitmap::get(*transferables)) {
-        if (imageBitmaps->getArray().size())
-            serializedValue->transferImageBitmaps(isolate, imageBitmaps, exceptionState);
-    }
-    if (auto* arrayBuffers = TransferableArrayBuffer::get(*transferables)) {
-        if (arrayBuffers->getArray().size())
-            serializedValue->transferArrayBuffers(isolate, arrayBuffers, exceptionState);
-    }
+
+    serializedValue->transferImageBitmaps(isolate, transferables->imageBitmaps, exceptionState);
+    if (exceptionState.hadException())
+        return;
+    serializedValue->transferArrayBuffers(isolate, transferables->arrayBuffers, exceptionState);
 }
 
-ScriptValueSerializer::Status SerializedScriptValueFactory::doSerialize(v8::Local<v8::Value> value, SerializedScriptValueWriter& writer, TransferableArray* transferables, WebBlobInfoArray* blobInfo, SerializedScriptValue* serializedValue, v8::TryCatch& tryCatch, String& errorMessage, v8::Isolate* isolate)
+ScriptValueSerializer::Status SerializedScriptValueFactory::doSerialize(v8::Local<v8::Value> value, SerializedScriptValueWriter& writer, Transferables* transferables, WebBlobInfoArray* blobInfo, SerializedScriptValue* serializedValue, v8::TryCatch& tryCatch, String& errorMessage, v8::Isolate* isolate)
 {
     return doSerialize(value, writer, transferables, blobInfo, serializedValue->blobDataHandles(), tryCatch, errorMessage, isolate);
 }
 
-ScriptValueSerializer::Status SerializedScriptValueFactory::doSerialize(v8::Local<v8::Value> value, SerializedScriptValueWriter& writer, TransferableArray* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, String& errorMessage, v8::Isolate* isolate)
+ScriptValueSerializer::Status SerializedScriptValueFactory::doSerialize(v8::Local<v8::Value> value, SerializedScriptValueWriter& writer, Transferables* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, String& errorMessage, v8::Isolate* isolate)
 {
     ScriptValueSerializer serializer(writer, transferables, blobInfo, blobDataHandles, tryCatch, ScriptState::current(isolate));
     ScriptValueSerializer::Status status = serializer.serialize(value);
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h
index dfc5f7c..28dd617 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h
@@ -24,8 +24,8 @@
     // be thrown using v8::ThrowException(), and sets |didThrow|. In this case
     // the caller must not invoke any V8 operations until control returns to
     // V8. When serialization is successful, |didThrow| is false.
-    virtual PassRefPtr<SerializedScriptValue> create(v8::Isolate*, v8::Local<v8::Value>, TransferableArray*, WebBlobInfoArray*, ExceptionState&);
-    PassRefPtr<SerializedScriptValue> create(v8::Isolate*, v8::Local<v8::Value>, TransferableArray*, ExceptionState&);
+    virtual PassRefPtr<SerializedScriptValue> create(v8::Isolate*, v8::Local<v8::Value>, Transferables*, WebBlobInfoArray*, ExceptionState&);
+    PassRefPtr<SerializedScriptValue> create(v8::Isolate*, v8::Local<v8::Value>, Transferables*, ExceptionState&);
     PassRefPtr<SerializedScriptValue> createFromWire(const String&);
     PassRefPtr<SerializedScriptValue> createFromWireBytes(const char* data, size_t length);
     PassRefPtr<SerializedScriptValue> create(const String&);
@@ -56,9 +56,9 @@
     }
 
 protected:
-    ScriptValueSerializer::Status doSerialize(v8::Local<v8::Value>, SerializedScriptValueWriter&, TransferableArray*, WebBlobInfoArray*, SerializedScriptValue*, v8::TryCatch&, String& errorMessage, v8::Isolate*);
-    virtual ScriptValueSerializer::Status doSerialize(v8::Local<v8::Value>, SerializedScriptValueWriter&, TransferableArray*, WebBlobInfoArray*, BlobDataHandleMap&, v8::TryCatch&, String& errorMessage, v8::Isolate*);
-    void transferData(SerializedScriptValue*, SerializedScriptValueWriter&, TransferableArray*, ExceptionState&, v8::Isolate*);
+    ScriptValueSerializer::Status doSerialize(v8::Local<v8::Value>, SerializedScriptValueWriter&, Transferables*, WebBlobInfoArray*, SerializedScriptValue*, v8::TryCatch&, String& errorMessage, v8::Isolate*);
+    virtual ScriptValueSerializer::Status doSerialize(v8::Local<v8::Value>, SerializedScriptValueWriter&, Transferables*, WebBlobInfoArray*, BlobDataHandleMap&, v8::TryCatch&, String& errorMessage, v8::Isolate*);
+    void transferData(SerializedScriptValue*, SerializedScriptValueWriter&, Transferables*, ExceptionState&, v8::Isolate*);
 
     virtual v8::Local<v8::Value> deserialize(String& data, BlobDataHandleMap& blobDataHandles, ArrayBufferContentsArray*, ImageBitmapContentsArray*, v8::Isolate*, MessagePortArray* messagePorts, const WebBlobInfoArray*);
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/Transferable.h b/third_party/WebKit/Source/bindings/core/v8/Transferable.h
deleted file mode 100644
index ea111b23..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/Transferable.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 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 Transferable_h
-#define Transferable_h
-
-#include "core/CoreExport.h"
-
-namespace blink {
-
-class CORE_EXPORT Transferable : public GarbageCollectedFinalized<Transferable> {
-public:
-    virtual ~Transferable() { }
-    DEFINE_INLINE_VIRTUAL_TRACE() { }
-
-    enum TransferableType {
-        TransferableArrayBufferType,
-        TransferableImageBitmapType,
-        TransferableMessagePortType
-    };
-};
-
-} // namespace blink
-
-#endif // Transferable_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/TransferableArrayBuffer.h b/third_party/WebKit/Source/bindings/core/v8/TransferableArrayBuffer.h
deleted file mode 100644
index b3755a4..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/TransferableArrayBuffer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 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 TransferableArrayBuffer_h
-#define TransferableArrayBuffer_h
-
-#include "bindings/core/v8/Transferable.h"
-#include "core/CoreExport.h"
-#include "core/dom/DOMArrayBufferBase.h"
-
-namespace blink {
-
-class CORE_EXPORT TransferableArrayBuffer : public Transferable {
-public:
-    ~TransferableArrayBuffer() override { }
-    void append(DOMArrayBufferBase* arrayBuffer)
-    {
-        m_arrayBufferArray.append(arrayBuffer);
-    }
-    bool contains(DOMArrayBufferBase* arrayBuffer)
-    {
-        return m_arrayBufferArray.contains(arrayBuffer);
-    }
-    static TransferableArrayBuffer* ensure(TransferableArray& transferables)
-    {
-        if (transferables.size() <= TransferableArrayBufferType) {
-            transferables.resize(TransferableArrayBufferType + 1);
-            transferables[TransferableArrayBufferType] = new TransferableArrayBuffer();
-        }
-        return static_cast<TransferableArrayBuffer*>(transferables[TransferableArrayBufferType].get());
-    }
-    static TransferableArrayBuffer* get(TransferableArray& transferables)
-    {
-        if (transferables.size() <= TransferableArrayBufferType)
-            return nullptr;
-        return static_cast<TransferableArrayBuffer*>(transferables[TransferableArrayBufferType].get());
-    }
-    HeapVector<Member<DOMArrayBufferBase>, 1>& getArray()
-    {
-        return m_arrayBufferArray;
-    }
-    DEFINE_INLINE_TRACE()
-    {
-        visitor->trace(m_arrayBufferArray);
-        Transferable::trace(visitor);
-    }
-private:
-    HeapVector<Member<DOMArrayBufferBase>, 1> m_arrayBufferArray;
-};
-
-} // namespace blink
-
-#endif // TransferableArrayBuffer_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/TransferableImageBitmap.h b/third_party/WebKit/Source/bindings/core/v8/TransferableImageBitmap.h
deleted file mode 100644
index 5722232..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/TransferableImageBitmap.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 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 TransferableImageBitmap_h
-#define TransferableImageBitmap_h
-
-#include "bindings/core/v8/Transferable.h"
-#include "core/CoreExport.h"
-#include "core/frame/ImageBitmap.h"
-
-namespace blink {
-
-class CORE_EXPORT TransferableImageBitmap : public Transferable {
-public:
-    ~TransferableImageBitmap() override { }
-    void append(ImageBitmap* imageBitmap)
-    {
-        m_imageBitmapArray.append(imageBitmap);
-    }
-    bool contains(ImageBitmap* imageBitmap)
-    {
-        return m_imageBitmapArray.contains(imageBitmap);
-    }
-    static TransferableImageBitmap* ensure(TransferableArray& transferables)
-    {
-        if (transferables.size() <= TransferableImageBitmapType) {
-            transferables.resize(TransferableImageBitmapType + 1);
-            transferables[TransferableImageBitmapType] = new TransferableImageBitmap();
-        }
-        return static_cast<TransferableImageBitmap*>(transferables[TransferableImageBitmapType].get());
-    }
-    static TransferableImageBitmap* get(TransferableArray& transferables)
-    {
-        if (transferables.size() <= TransferableImageBitmapType)
-            return nullptr;
-        return static_cast<TransferableImageBitmap*>(transferables[TransferableImageBitmapType].get());
-    }
-    HeapVector<Member<ImageBitmap>, 1>& getArray()
-    {
-        return m_imageBitmapArray;
-    }
-    DEFINE_INLINE_TRACE()
-    {
-        visitor->trace(m_imageBitmapArray);
-        Transferable::trace(visitor);
-    }
-private:
-    HeapVector<Member<ImageBitmap>, 1> m_imageBitmapArray;
-};
-
-} // namespace blink
-
-#endif // TransferableImageBitmap_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/TransferableMessagePort.h b/third_party/WebKit/Source/bindings/core/v8/TransferableMessagePort.h
deleted file mode 100644
index 2970f16..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/TransferableMessagePort.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 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 TransferableMessagePort_h
-#define TransferableMessagePort_h
-
-#include "bindings/core/v8/Transferable.h"
-#include "core/CoreExport.h"
-#include "core/dom/MessagePort.h"
-
-namespace blink {
-
-class CORE_EXPORT TransferableMessagePort : public Transferable {
-public:
-    ~TransferableMessagePort() override { }
-    void append(MessagePort* messagePort)
-    {
-        m_messagePortArray.append(messagePort);
-    }
-    bool contains(MessagePort* messagePort)
-    {
-        return m_messagePortArray.contains(messagePort);
-    }
-    static TransferableMessagePort* ensure(TransferableArray& transferables)
-    {
-        if (transferables.size() <= TransferableMessagePortType) {
-            transferables.resize(TransferableMessagePortType + 1);
-            transferables[TransferableMessagePortType] = new TransferableMessagePort();
-        }
-        return static_cast<TransferableMessagePort*>(transferables[TransferableMessagePortType].get());
-    }
-    static TransferableMessagePort* get(const TransferableArray& transferables)
-    {
-        if (transferables.size() <= TransferableMessagePortType)
-            return nullptr;
-        return static_cast<TransferableMessagePort*>(transferables[TransferableMessagePortType].get());
-    }
-    HeapVector<Member<MessagePort>, 1>& getArray()
-    {
-        return m_messagePortArray;
-    }
-    DEFINE_INLINE_TRACE()
-    {
-        visitor->trace(m_messagePortArray);
-        Transferable::trace(visitor);
-    }
-private:
-    HeapVector<Member<MessagePort>, 1> m_messagePortArray;
-};
-
-} // namespace blink
-
-#endif // TransferableMessagePort_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/Transferables.h b/third_party/WebKit/Source/bindings/core/v8/Transferables.h
new file mode 100644
index 0000000..bec7fc0
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/Transferables.h
@@ -0,0 +1,42 @@
+// Copyright 2016 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 Transferables_h
+#define Transferables_h
+
+#include "core/CoreExport.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Noncopyable.h"
+
+namespace blink {
+
+class DOMArrayBufferBase;
+class ImageBitmap;
+class MessagePort;
+
+using ArrayBufferArray = HeapVector<Member<DOMArrayBufferBase>>;
+using ImageBitmapArray = HeapVector<Member<ImageBitmap>>;
+using MessagePortArray = HeapVector<Member<MessagePort>>;
+
+class CORE_EXPORT Transferables final {
+    STACK_ALLOCATED();
+    WTF_MAKE_NONCOPYABLE(Transferables);
+public:
+    Transferables()
+    {
+    }
+
+    ArrayBufferArray arrayBuffers;
+    ImageBitmapArray imageBitmaps;
+    MessagePortArray messagePorts;
+};
+
+// Along with extending |Transferables| to hold a new kind of transferable
+// objects, serialization handling code changes are required:
+//   - extend ScriptValueSerializer::copyTransferables()
+//   - alter SerializedScriptValue(Factory) to do the actual transfer.
+
+} // namespace blink
+
+#endif // Transferables_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
index 0acb367..b6f713dd 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -204,15 +204,6 @@
     return (v8CacheDataVersion | kind) + StringHash::hash(cacheHandler->encoding());
 }
 
-// Store a timestamp to the cache as hint.
-void setCacheTimeStamp(CachedMetadataHandler* cacheHandler)
-{
-    double now = WTF::currentTime();
-    unsigned tag = cacheTag(CacheTagTimeStamp, cacheHandler);
-    cacheHandler->clearCachedMetadata(CachedMetadataHandler::CacheLocally);
-    cacheHandler->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(now), CachedMetadataHandler::SendToPlatform);
-}
-
 // Check previously stored timestamp.
 bool isResourceHotForCaching(CachedMetadataHandler* cacheHandler, int hotHours)
 {
@@ -254,7 +245,7 @@
 
     case V8CacheOptionsDefault:
     case V8CacheOptionsCode:
-        setCacheTimeStamp(cacheHandler);
+        V8ScriptRunner::setCacheTimeStamp(cacheHandler);
         break;
 
     case V8CacheOptionsNone:
@@ -312,7 +303,7 @@
         if (codeCache)
             return bind(compileAndConsumeCache, cacheHandler, codeCacheTag, v8::ScriptCompiler::kConsumeCodeCache);
         if (!isResourceHotForCaching(cacheHandler, hotHours)) {
-            setCacheTimeStamp(cacheHandler);
+            V8ScriptRunner::setCacheTimeStamp(cacheHandler);
             return bind(compileWithoutOptions, V8CompileHistogram::Cacheable);
         }
         return bind(compileAndProduceCache, cacheHandler, codeCacheTag, v8::ScriptCompiler::kProduceCodeCache, CachedMetadataHandler::SendToPlatform);
@@ -524,4 +515,13 @@
     return cacheTag(CacheTagCode, cacheHandler);
 }
 
+// Store a timestamp to the cache as hint.
+void V8ScriptRunner::setCacheTimeStamp(CachedMetadataHandler* cacheHandler)
+{
+    double now = WTF::currentTime();
+    unsigned tag = cacheTag(CacheTagTimeStamp, cacheHandler);
+    cacheHandler->clearCachedMetadata(CachedMetadataHandler::CacheLocally);
+    cacheHandler->setCachedMetadata(tag, reinterpret_cast<char*>(&now), sizeof(now), CachedMetadataHandler::SendToPlatform);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h
index 48a1e2ad..93e26552 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.h
@@ -71,6 +71,7 @@
 
     static unsigned tagForParserCache(CachedMetadataHandler*);
     static unsigned tagForCodeCache(CachedMetadataHandler*);
+    static void setCacheTimeStamp(CachedMetadataHandler*);
 
 
     // Utiltiies for calling functions added to the V8 extras binding object.
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunnerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunnerTest.cpp
index 786664e..3fbc070 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunnerTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunnerTest.cpp
@@ -61,6 +61,10 @@
     {
         return V8ScriptRunner::tagForCodeCache(cacheHandler);
     }
+    void setCacheTimeStamp(CachedMetadataHandler* cacheHandler)
+    {
+        V8ScriptRunner::setCacheTimeStamp(cacheHandler);
+    }
 
     bool compileScript(V8CacheOptions cacheOptions)
     {
@@ -125,9 +129,8 @@
 TEST_F(V8ScriptRunnerTest, codeOption)
 {
     setResource();
+    setCacheTimeStamp(cacheHandler());
 
-    // Compile twice, since 'code' has a probation period before it caches.
-    EXPECT_TRUE(compileScript(V8CacheOptionsCode));
     EXPECT_TRUE(compileScript(V8CacheOptionsCode));
 
     EXPECT_FALSE(cacheHandler()->cachedMetadata(tagForParserCache(cacheHandler())));
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
index c75d51b..4bcb14e5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
@@ -37,7 +37,7 @@
 #include "bindings/core/v8/ScriptSourceCode.h"
 #include "bindings/core/v8/SerializedScriptValue.h"
 #include "bindings/core/v8/SerializedScriptValueFactory.h"
-#include "bindings/core/v8/TransferableMessagePort.h"
+#include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8EventListener.h"
 #include "bindings/core/v8/V8EventListenerList.h"
@@ -193,7 +193,7 @@
     //   postMessage(message, targetOrigin, {sequence of transferrables})
     // Legacy non-standard implementations in webkit allowed:
     //   postMessage(message, {sequence of transferrables}, targetOrigin);
-    TransferableArray* transferables = new TransferableArray;
+    Transferables transferables;
     int targetOriginArgIndex = 1;
     if (info.Length() > 2) {
         int transferablesArgIndex = 2;
@@ -202,23 +202,18 @@
             targetOriginArgIndex = 2;
             transferablesArgIndex = 1;
         }
-        if (!SerializedScriptValue::extractTransferables(info.GetIsolate(), info[transferablesArgIndex], transferablesArgIndex, *transferables, exceptionState)) {
+        if (!SerializedScriptValue::extractTransferables(info.GetIsolate(), info[transferablesArgIndex], transferablesArgIndex, transferables, exceptionState)) {
             exceptionState.throwIfNeeded();
             return;
         }
     }
     TOSTRING_VOID(V8StringResource<TreatNullAndUndefinedAsNullString>, targetOrigin, info[targetOriginArgIndex]);
 
-    RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().create(info.GetIsolate(), info[0], transferables, exceptionState);
+    RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().create(info.GetIsolate(), info[0], &transferables, exceptionState);
     if (exceptionState.throwIfNeeded())
         return;
 
-    MessagePortArray* portArray;
-    if (auto* messagePorts = TransferableMessagePort::get(*transferables))
-        portArray = &(messagePorts->getArray());
-    else
-        portArray = new MessagePortArray;
-    window->postMessage(message.release(), portArray, targetOrigin, source, exceptionState);
+    window->postMessage(message.release(), transferables.messagePorts, targetOrigin, source, exceptionState);
     exceptionState.throwIfNeeded();
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/v8.gypi b/third_party/WebKit/Source/bindings/core/v8/v8.gypi
index 8afb8bc..a748fb0 100644
--- a/third_party/WebKit/Source/bindings/core/v8/v8.gypi
+++ b/third_party/WebKit/Source/bindings/core/v8/v8.gypi
@@ -102,10 +102,7 @@
             'SerializedScriptValueFactory.cpp',
             'SerializedScriptValueFactory.h',
             'SharedPersistent.h',
-            'Transferable.h',
-            'TransferableArrayBuffer.h',
-            'TransferableImageBitmap.h',
-            'TransferableMessagePort.h',
+            'Transferables.h',
             'ToV8.cpp',
             'ToV8.h',
             'V8AbstractEventListener.cpp',
diff --git a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
index b34914c..50182cd 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
@@ -73,7 +73,7 @@
 };
 
 
-ScriptValueSerializerForModules::ScriptValueSerializerForModules(SerializedScriptValueWriter& writer, TransferableArray* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
+ScriptValueSerializerForModules::ScriptValueSerializerForModules(SerializedScriptValueWriter& writer, const Transferables* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
     : ScriptValueSerializer(writer, transferables, blobInfo, blobDataHandles, tryCatch, scriptState)
 {
 }
diff --git a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h
index 81719052..4d929db 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h
+++ b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h
@@ -70,7 +70,7 @@
     STACK_ALLOCATED();
     WTF_MAKE_NONCOPYABLE(ScriptValueSerializerForModules);
 public:
-    ScriptValueSerializerForModules(SerializedScriptValueWriter&, TransferableArray* transferables, WebBlobInfoArray*, BlobDataHandleMap& blobDataHandles, v8::TryCatch&, ScriptState*);
+    ScriptValueSerializerForModules(SerializedScriptValueWriter&, const Transferables*, WebBlobInfoArray*, BlobDataHandleMap&, v8::TryCatch&, ScriptState*);
 
 private:
     ScriptValueSerializer::StateBase* doSerializeValue(v8::Local<v8::Value>, ScriptValueSerializer::StateBase* next) override;
diff --git a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp
index 50941eb..bafa2c9 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp
@@ -11,7 +11,7 @@
 
 namespace blink {
 
-PassRefPtr<SerializedScriptValue> SerializedScriptValueForModulesFactory::create(v8::Isolate* isolate, v8::Local<v8::Value> value, TransferableArray* transferables, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState)
+PassRefPtr<SerializedScriptValue> SerializedScriptValueForModulesFactory::create(v8::Isolate* isolate, v8::Local<v8::Value> value, Transferables* transferables, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState)
 {
     RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValueFactory::create();
     SerializedScriptValueWriterForModules writer;
@@ -50,7 +50,7 @@
     return createFromWire(wireData);
 }
 
-ScriptValueSerializer::Status SerializedScriptValueForModulesFactory::doSerialize(v8::Local<v8::Value> value, SerializedScriptValueWriter& writer, TransferableArray* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, String& errorMessage, v8::Isolate* isolate)
+ScriptValueSerializer::Status SerializedScriptValueForModulesFactory::doSerialize(v8::Local<v8::Value> value, SerializedScriptValueWriter& writer, Transferables* transferables, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, String& errorMessage, v8::Isolate* isolate)
 {
     ScriptValueSerializerForModules serializer(writer, transferables, blobInfo, blobDataHandles, tryCatch, ScriptState::current(isolate));
     ScriptValueSerializer::Status status = serializer.serialize(value);
diff --git a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.h b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.h
index a3754e4..b133793 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.h
+++ b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.h
@@ -16,11 +16,11 @@
 public:
     SerializedScriptValueForModulesFactory() : SerializedScriptValueFactory() { }
 
-    PassRefPtr<SerializedScriptValue> create(v8::Isolate*, v8::Local<v8::Value>, TransferableArray*, WebBlobInfoArray*, ExceptionState&) override;
+    PassRefPtr<SerializedScriptValue> create(v8::Isolate*, v8::Local<v8::Value>, Transferables*, WebBlobInfoArray*, ExceptionState&) override;
     PassRefPtr<SerializedScriptValue> create(v8::Isolate*, const String&) override;
 
 protected:
-    ScriptValueSerializer::Status doSerialize(v8::Local<v8::Value>, SerializedScriptValueWriter&, TransferableArray*, WebBlobInfoArray*, BlobDataHandleMap&, v8::TryCatch&, String& errorMessage, v8::Isolate*) override;
+    ScriptValueSerializer::Status doSerialize(v8::Local<v8::Value>, SerializedScriptValueWriter&, Transferables*, WebBlobInfoArray*, BlobDataHandleMap&, v8::TryCatch&, String& errorMessage, v8::Isolate*) override;
 
     v8::Local<v8::Value> deserialize(String& data, BlobDataHandleMap& blobDataHandles, ArrayBufferContentsArray*, ImageBitmapContentsArray*, v8::Isolate*, MessagePortArray* messagePorts, const WebBlobInfoArray*) override;
 };
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_methods.py b/third_party/WebKit/Source/bindings/scripts/v8_methods.py
index ee3a078..4952049 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_methods.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_methods.py
@@ -110,10 +110,10 @@
     is_post_message = 'PostMessage' in extended_attributes
     if is_post_message:
         includes.add('bindings/core/v8/SerializedScriptValueFactory.h')
+        includes.add('bindings/core/v8/Transferables.h')
         includes.add('core/dom/DOMArrayBuffer.h')
         includes.add('core/dom/MessagePort.h')
         includes.add('core/frame/ImageBitmap.h')
-        includes.add('bindings/core/v8/TransferableMessagePort.h')
 
     if 'LenientThis' in extended_attributes:
         raise Exception('[LenientThis] is not supported for operations.')
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp b/third_party/WebKit/Source/bindings/templates/methods.cpp
index b959650..cac64f07 100644
--- a/third_party/WebKit/Source/bindings/templates/methods.cpp
+++ b/third_party/WebKit/Source/bindings/templates/methods.cpp
@@ -464,25 +464,20 @@
         exceptionState.throwIfNeeded();
         return;
     }
-    TransferableArray* transferables = new TransferableArray;
+    Transferables transferables;
     if (info.Length() > 1) {
         const int transferablesArgIndex = 1;
-        if (!SerializedScriptValue::extractTransferables(info.GetIsolate(), info[transferablesArgIndex], transferablesArgIndex, *transferables, exceptionState)) {
+        if (!SerializedScriptValue::extractTransferables(info.GetIsolate(), info[transferablesArgIndex], transferablesArgIndex, transferables, exceptionState)) {
             exceptionState.throwIfNeeded();
             return;
         }
     }
-    RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().create(info.GetIsolate(), info[0], transferables, exceptionState);
+    RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().create(info.GetIsolate(), info[0], &transferables, exceptionState);
     if (exceptionState.throwIfNeeded())
         return;
     // FIXME: Only pass context/exceptionState if instance really requires it.
     ExecutionContext* context = currentExecutionContext(info.GetIsolate());
-    MessagePortArray* ports;
-    if (auto* messagePorts = TransferableMessagePort::get(*transferables))
-        ports = &(messagePorts->getArray());
-    else
-        ports = new MessagePortArray;
-    instance->postMessage(context, message.release(), ports, exceptionState);
+    instance->postMessage(context, message.release(), transferables.messagePorts, exceptionState);
     exceptionState.throwIfNeeded();
 }
 {% endmacro %}
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index e4ef2552..1b62e08 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -16,7 +16,7 @@
 #include "bindings/core/v8/ScriptValue.h"
 #include "bindings/core/v8/SerializedScriptValue.h"
 #include "bindings/core/v8/SerializedScriptValueFactory.h"
-#include "bindings/core/v8/TransferableMessagePort.h"
+#include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/UnionTypesCore.h"
 #include "bindings/core/v8/V8AbstractEventListener.h"
 #include "bindings/core/v8/V8ArrayBuffer.h"
@@ -10154,25 +10154,20 @@
         exceptionState.throwIfNeeded();
         return;
     }
-    TransferableArray* transferables = new TransferableArray;
+    Transferables transferables;
     if (info.Length() > 1) {
         const int transferablesArgIndex = 1;
-        if (!SerializedScriptValue::extractTransferables(info.GetIsolate(), info[transferablesArgIndex], transferablesArgIndex, *transferables, exceptionState)) {
+        if (!SerializedScriptValue::extractTransferables(info.GetIsolate(), info[transferablesArgIndex], transferablesArgIndex, transferables, exceptionState)) {
             exceptionState.throwIfNeeded();
             return;
         }
     }
-    RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().create(info.GetIsolate(), info[0], transferables, exceptionState);
+    RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().create(info.GetIsolate(), info[0], &transferables, exceptionState);
     if (exceptionState.throwIfNeeded())
         return;
     // FIXME: Only pass context/exceptionState if instance really requires it.
     ExecutionContext* context = currentExecutionContext(info.GetIsolate());
-    MessagePortArray* ports;
-    if (auto* messagePorts = TransferableMessagePort::get(*transferables))
-        ports = &(messagePorts->getArray());
-    else
-        ports = new MessagePortArray;
-    instance->postMessage(context, message.release(), ports, exceptionState);
+    instance->postMessage(context, message.release(), transferables.messagePorts, exceptionState);
     exceptionState.throwIfNeeded();
 }
 
diff --git a/third_party/WebKit/Source/core/css/MediaValuesCached.cpp b/third_party/WebKit/Source/core/css/MediaValuesCached.cpp
index 5879bf1ee7..effe6c7 100644
--- a/third_party/WebKit/Source/core/css/MediaValuesCached.cpp
+++ b/third_party/WebKit/Source/core/css/MediaValuesCached.cpp
@@ -8,6 +8,7 @@
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
 #include "core/layout/LayoutObject.h"
+#include "core/layout/api/LayoutViewItem.h"
 
 namespace blink {
 
@@ -19,7 +20,7 @@
     // TODO(hiroshige): Clean up |frame->view()| conditions.
     ASSERT(!frame || frame->view());
     if (frame && frame->view()) {
-        ASSERT(frame->document() && frame->document()->layoutView());
+        ASSERT(frame->document() && !frame->document()->layoutViewItem().isNull());
 
         // In case that frame is missing (e.g. for images that their document does not have a frame)
         // We simply leave the MediaValues object with the default MediaValuesCachedData values.
diff --git a/third_party/WebKit/Source/core/css/MediaValuesDynamic.cpp b/third_party/WebKit/Source/core/css/MediaValuesDynamic.cpp
index 24f3aec..3dd5f10 100644
--- a/third_party/WebKit/Source/core/css/MediaValuesDynamic.cpp
+++ b/third_party/WebKit/Source/core/css/MediaValuesDynamic.cpp
@@ -10,6 +10,7 @@
 #include "core/css/MediaValuesCached.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
+#include "core/layout/api/LayoutViewItem.h"
 
 namespace blink {
 
@@ -20,7 +21,7 @@
 
 MediaValues* MediaValuesDynamic::create(LocalFrame* frame)
 {
-    if (!frame || !frame->view() || !frame->document() || !frame->document()->layoutView())
+    if (!frame || !frame->view() || !frame->document() || frame->document()->layoutViewItem().isNull())
         return MediaValuesCached::create();
     return new MediaValuesDynamic(frame);
 }
diff --git a/third_party/WebKit/Source/core/dom/MessagePort.cpp b/third_party/WebKit/Source/core/dom/MessagePort.cpp
index 56ba478..92769bee 100644
--- a/third_party/WebKit/Source/core/dom/MessagePort.cpp
+++ b/third_party/WebKit/Source/core/dom/MessagePort.cpp
@@ -66,7 +66,7 @@
         m_scriptStateForConversion->disposePerContextData();
 }
 
-void MessagePort::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState)
+void MessagePort::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, ExceptionState& exceptionState)
 {
     if (!isEntangled())
         return;
@@ -75,18 +75,15 @@
 
     OwnPtr<MessagePortChannelArray> channels;
     // Make sure we aren't connected to any of the passed-in ports.
-    if (ports) {
-        for (unsigned i = 0; i < ports->size(); ++i) {
-            MessagePort* dataPort = (*ports)[i];
-            if (dataPort == this) {
-                exceptionState.throwDOMException(DataCloneError, "Port at index " + String::number(i) + " contains the source port.");
-                return;
-            }
-        }
-        channels = MessagePort::disentanglePorts(context, ports, exceptionState);
-        if (exceptionState.hadException())
+    for (unsigned i = 0; i < ports.size(); ++i) {
+        if (ports[i] == this) {
+            exceptionState.throwDOMException(DataCloneError, "Port at index " + String::number(i) + " contains the source port.");
             return;
+        }
     }
+    channels = MessagePort::disentanglePorts(context, ports, exceptionState);
+    if (exceptionState.hadException())
+        return;
 
     if (message->containsTransferableArrayBuffer())
         getExecutionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "MessagePort cannot send an ArrayBuffer as a transferable object yet. See http://crbug.com/334408"));
@@ -223,18 +220,17 @@
     return m_started && isEntangled();
 }
 
-PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(ExecutionContext* context, const MessagePortArray* ports, ExceptionState& exceptionState)
+PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(ExecutionContext* context, const MessagePortArray& ports, ExceptionState& exceptionState)
 {
-    if (!ports || !ports->size())
+    if (!ports.size())
         return nullptr;
 
-    // HeapHashSet used to efficiently check for duplicates in the passed-in array.
-    HeapHashSet<Member<MessagePort>> portSet;
+    HeapHashSet<Member<MessagePort>> visited;
 
     // Walk the incoming array - if there are any duplicate ports, or null ports or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec).
-    for (unsigned i = 0; i < ports->size(); ++i) {
-        MessagePort* port = (*ports)[i];
-        if (!port || port->isNeutered() || portSet.contains(port)) {
+    for (unsigned i = 0; i < ports.size(); ++i) {
+        MessagePort* port = ports[i];
+        if (!port || port->isNeutered() || visited.contains(port)) {
             String type;
             if (!port)
                 type = "null";
@@ -245,15 +241,15 @@
             exceptionState.throwDOMException(DataCloneError, "Port at index "  + String::number(i) + " is " + type + ".");
             return nullptr;
         }
-        portSet.add(port);
+        visited.add(port);
     }
 
     UseCounter::count(context, UseCounter::MessagePortsTransferred);
 
     // Passed-in ports passed validity checks, so we can disentangle them.
-    OwnPtr<MessagePortChannelArray> portArray = adoptPtr(new MessagePortChannelArray(ports->size()));
-    for (unsigned i = 0; i < ports->size(); ++i)
-        (*portArray)[i] = (*ports)[i]->disentangle();
+    OwnPtr<MessagePortChannelArray> portArray = adoptPtr(new MessagePortChannelArray(ports.size()));
+    for (unsigned i = 0; i < ports.size(); ++i)
+        (*portArray)[i] = ports[i]->disentangle();
     return portArray.release();
 }
 
diff --git a/third_party/WebKit/Source/core/dom/MessagePort.h b/third_party/WebKit/Source/core/dom/MessagePort.h
index 75b7653e..aca2815 100644
--- a/third_party/WebKit/Source/core/dom/MessagePort.h
+++ b/third_party/WebKit/Source/core/dom/MessagePort.h
@@ -28,6 +28,7 @@
 #define MessagePort_h
 
 #include "bindings/core/v8/ActiveScriptWrappable.h"
+#include "bindings/core/v8/SerializedScriptValue.h"
 #include "core/CoreExport.h"
 #include "core/dom/ActiveDOMObject.h"
 #include "core/events/EventListener.h"
@@ -49,9 +50,6 @@
 class ScriptState;
 class SerializedScriptValue;
 
-// The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
-typedef HeapVector<Member<MessagePort>, 1> MessagePortArray;
-
 // Not to be confused with WebMessagePortChannelArray; this one uses Vector and OwnPtr instead of WebVector and raw pointers.
 typedef Vector<OwnPtr<WebMessagePortChannel>, 1> MessagePortChannelArray;
 
@@ -66,7 +64,7 @@
     static MessagePort* create(ExecutionContext&);
     ~MessagePort() override;
 
-    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionState&);
+    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray&, ExceptionState&);
 
     void start();
     void close();
@@ -81,7 +79,7 @@
     static MessagePortArray* toMessagePortArray(ExecutionContext*, const WebMessagePortChannelArray&);
 
     // Returns nullptr if there is an exception, or if the passed-in array is nullptr/empty.
-    static PassOwnPtr<MessagePortChannelArray> disentanglePorts(ExecutionContext*, const MessagePortArray*, ExceptionState&);
+    static PassOwnPtr<MessagePortChannelArray> disentanglePorts(ExecutionContext*, const MessagePortArray&, ExceptionState&);
 
     // Returns an empty array if the passed array is nullptr/empty.
     static MessagePortArray* entanglePorts(ExecutionContext&, PassOwnPtr<MessagePortChannelArray>);
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index 0bd6a11c..5f523d02 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -59,6 +59,7 @@
 class HTMLQualifiedName;
 class HTMLSlotElement;
 class IntRect;
+class EventDispatchHandlingState;
 class KeyboardEvent;
 class NSResolver;
 class NameNodeList;
@@ -615,8 +616,8 @@
 
     // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event
     // has been dispatched.  The data pointer is handed back by the preDispatch and passed to postDispatch.
-    virtual void* preDispatchEventHandler(Event*) { return nullptr; }
-    virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { }
+    virtual EventDispatchHandlingState* preDispatchEventHandler(Event*) { return nullptr; }
+    virtual void postDispatchEventHandler(Event*, EventDispatchHandlingState*) { }
 
     void dispatchScopedEvent(Event*);
 
diff --git a/third_party/WebKit/Source/core/dom/TreeScope.cpp b/third_party/WebKit/Source/core/dom/TreeScope.cpp
index 7b0fe0a..377a865 100644
--- a/third_party/WebKit/Source/core/dom/TreeScope.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeScope.cpp
@@ -47,7 +47,7 @@
 #include "core/html/HTMLLabelElement.h"
 #include "core/html/HTMLMapElement.h"
 #include "core/layout/HitTestResult.h"
-#include "core/layout/LayoutView.h"
+#include "core/layout/api/LayoutViewItem.h"
 #include "core/page/FocusController.h"
 #include "core/page/Page.h"
 #include "wtf/Vector.h"
@@ -230,7 +230,7 @@
         return HitTestResult();
 
     HitTestResult result(request, hitPoint);
-    document->layoutView()->hitTest(result);
+    document->layoutViewItem().hitTest(result);
     return result;
 }
 
@@ -298,7 +298,7 @@
 
     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased | HitTestRequest::PenetratingList);
     HitTestResult result(request, hitPoint);
-    document.layoutView()->hitTest(result);
+    document.layoutViewItem().hitTest(result);
 
     return elementsFromHitTestResult(result);
 }
diff --git a/third_party/WebKit/Source/core/editing/DragCaretController.cpp b/third_party/WebKit/Source/core/editing/DragCaretController.cpp
index c132acb..ae43f46 100644
--- a/third_party/WebKit/Source/core/editing/DragCaretController.cpp
+++ b/third_party/WebKit/Source/core/editing/DragCaretController.cpp
@@ -26,7 +26,7 @@
 #include "core/editing/DragCaretController.h"
 
 #include "core/editing/EditingUtilities.h"
-#include "core/layout/LayoutView.h"
+#include "core/layout/api/LayoutViewItem.h"
 #include "core/paint/PaintLayer.h"
 
 namespace blink {
@@ -92,7 +92,7 @@
     if (!removingNodeRemovesPosition(node, m_position.deepEquivalent()))
         return;
 
-    m_position.deepEquivalent().document()->layoutView()->clearSelection();
+    m_position.deepEquivalent().document()->layoutViewItem().clearSelection();
     clear();
 }
 
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index a0a816f..5017bc2 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -454,7 +454,7 @@
     if (m_selectionState != SelectionState::ExtendedSelection) {
         HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
         HitTestResult result(request, mouseDownPos);
-        m_frame->document()->layoutView()->hitTest(result);
+        m_frame->document()->layoutViewItem().hitTest(result);
 
         updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKnownMousePosition);
     }
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index dd704fa..55153214 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -56,6 +56,7 @@
 #include "core/layout/LayoutTextFragment.h"
 #include "core/layout/LayoutView.h"
 #include "core/layout/api/LayoutItem.h"
+#include "core/layout/api/LayoutViewItem.h"
 #include "core/layout/api/LineLayoutAPIShim.h"
 #include "core/layout/api/LineLayoutItem.h"
 #include "core/layout/line/InlineIterator.h"
@@ -2178,7 +2179,7 @@
 {
     HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping;
     HitTestResult result(request, contentsPoint);
-    frame->document()->layoutView()->hitTest(result);
+    frame->document()->layoutViewItem().hitTest(result);
 
     if (Node* node = result.innerNode())
         return frame->selection().selection().visiblePositionRespectingEditingBoundary(result.localPoint(), node);
diff --git a/third_party/WebKit/Source/core/events/EventDispatcher.cpp b/third_party/WebKit/Source/core/events/EventDispatcher.cpp
index 974d135..c97cc0e4 100644
--- a/third_party/WebKit/Source/core/events/EventDispatcher.cpp
+++ b/third_party/WebKit/Source/core/events/EventDispatcher.cpp
@@ -119,7 +119,7 @@
     ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
     ASSERT(m_event->target());
     TRACE_EVENT1("devtools.timeline", "EventDispatch", "data", InspectorEventDispatchEvent::data(*m_event));
-    void* preDispatchEventHandlerResult;
+    EventDispatchHandlingState* preDispatchEventHandlerResult = nullptr;
     if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching) {
         if (dispatchEventAtCapturing() == ContinueDispatching) {
             if (dispatchEventAtTarget() == ContinueDispatching)
@@ -137,7 +137,7 @@
     return EventTarget::dispatchEventResult(*m_event);
 }
 
-inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(void*& preDispatchEventHandlerResult)
+inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(EventDispatchHandlingState*& preDispatchEventHandlerResult)
 {
     // Give the target node a chance to do some work before DOM event handlers get a crack.
     preDispatchEventHandlerResult = m_node->preDispatchEventHandler(m_event.get());
@@ -193,7 +193,7 @@
     }
 }
 
-inline void EventDispatcher::dispatchEventPostProcess(void* preDispatchEventHandlerResult)
+inline void EventDispatcher::dispatchEventPostProcess(EventDispatchHandlingState* preDispatchEventHandlerResult)
 {
     m_event->setTarget(EventPath::eventTargetRespectingTargetRules(*m_node));
     m_event->setCurrentTarget(nullptr);
diff --git a/third_party/WebKit/Source/core/events/EventDispatcher.h b/third_party/WebKit/Source/core/events/EventDispatcher.h
index fc6368ab..678d14ee 100644
--- a/third_party/WebKit/Source/core/events/EventDispatcher.h
+++ b/third_party/WebKit/Source/core/events/EventDispatcher.h
@@ -37,10 +37,16 @@
 class Event;
 class EventDispatchMediator;
 class FrameView;
+class EventDispatchHandlingState;
 class Node;
 class NodeEventContext;
 class WindowEventContext;
 
+class EventDispatchHandlingState : public GarbageCollected<EventDispatchHandlingState> {
+public:
+    DEFINE_INLINE_VIRTUAL_TRACE() { }
+};
+
 enum EventDispatchContinuation {
     ContinueDispatching,
     DoneDispatching
@@ -61,11 +67,11 @@
 private:
     EventDispatcher(Node&, Event*);
 
-    EventDispatchContinuation dispatchEventPreProcess(void*& preDispatchEventHandlerResult);
+    EventDispatchContinuation dispatchEventPreProcess(EventDispatchHandlingState*&);
     EventDispatchContinuation dispatchEventAtCapturing();
     EventDispatchContinuation dispatchEventAtTarget();
     void dispatchEventAtBubbling();
-    void dispatchEventPostProcess(void* preDispatchEventHandlerResult);
+    void dispatchEventPostProcess(EventDispatchHandlingState*);
 
     Member<Node> m_node;
     Member<Event> m_event;
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
index a02e3cc..bf9669f 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -168,7 +168,7 @@
     return document()->isSecureContext(ExecutionContext::StandardSecureContextCheck);
 }
 
-void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, LocalDOMWindow* source, ExceptionState& exceptionState)
+void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, const String& targetOrigin, LocalDOMWindow* source, ExceptionState& exceptionState)
 {
     if (!isCurrentlyDisplayedInFrame())
         return;
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.h b/third_party/WebKit/Source/core/frame/DOMWindow.h
index bb4f489..5876e091 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.h
@@ -5,10 +5,10 @@
 #ifndef DOMWindow_h
 #define DOMWindow_h
 
+#include "bindings/core/v8/Transferables.h"
 #include "core/CoreExport.h"
 #include "core/events/EventTarget.h"
 #include "core/frame/DOMWindowBase64.h"
-#include "core/frame/Location.h"
 #include "platform/heap/Handle.h"
 #include "platform/scroll/ScrollableArea.h"
 
@@ -31,6 +31,7 @@
 class History;
 class IdleRequestCallback;
 class IdleRequestOptions;
+class Location;
 class LocalDOMWindow;
 class MediaQueryList;
 class Navigator;
@@ -40,8 +41,6 @@
 class Storage;
 class StyleMedia;
 
-typedef HeapVector<Member<MessagePort>, 1> MessagePortArray;
-
 class CORE_EXPORT DOMWindow : public EventTargetWithInlineData, public DOMWindowBase64 {
     DEFINE_WRAPPERTYPEINFO();
 public:
@@ -185,7 +184,7 @@
     // window[index]...
     DOMWindow* anonymousIndexedGetter(uint32_t) const;
 
-    void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, LocalDOMWindow* source, ExceptionState&);
+    void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray&, const String& targetOrigin, LocalDOMWindow* source, ExceptionState&);
 
     String sanitizedCrossDomainAccessErrorMessage(const LocalDOMWindow* callingWindow) const;
     String crossDomainAccessErrorMessage(const LocalDOMWindow* callingWindow) const;
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index e92b336a..7c82141 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -40,6 +40,7 @@
 #include "core/fetch/ResourceFetcher.h"
 #include "core/frame/FrameHost.h"
 #include "core/frame/LocalFrame.h"
+#include "core/frame/Location.h"
 #include "core/frame/PageScaleConstraintsSet.h"
 #include "core/frame/Settings.h"
 #include "core/frame/TopControls.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
index a31dece..01432ce 100644
--- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
@@ -1156,8 +1156,7 @@
     setAutofilled(false);
 }
 
-// TODO(Oilpan): It's nasty to return a void* pointer. Return ClickHandlingState* instead.
-void* HTMLInputElement::preDispatchEventHandler(Event* event)
+EventDispatchHandlingState* HTMLInputElement::preDispatchEventHandler(Event* event)
 {
     if (event->type() == EventTypeNames::textInput && m_inputTypeView->shouldSubmitImplicitly(event)) {
         event->stopPropagation();
@@ -1170,12 +1169,11 @@
     return m_inputTypeView->willDispatchClick();
 }
 
-void HTMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch)
+void HTMLInputElement::postDispatchEventHandler(Event* event, EventDispatchHandlingState* state)
 {
-    ClickHandlingState* state = static_cast<ClickHandlingState*>(dataFromPreDispatch);
     if (!state)
         return;
-    m_inputTypeView->didDispatchClick(event, *state);
+    m_inputTypeView->didDispatchClick(event, *static_cast<ClickHandlingState*>(state));
 }
 
 void HTMLInputElement::defaultEventHandler(Event* evt)
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.h b/third_party/WebKit/Source/core/html/HTMLInputElement.h
index 91ec0727..a81485a 100644
--- a/third_party/WebKit/Source/core/html/HTMLInputElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLInputElement.h
@@ -328,8 +328,8 @@
     void resetImpl() final;
     bool supportsAutofocus() const final;
 
-    void* preDispatchEventHandler(Event*) final;
-    void postDispatchEventHandler(Event*, void* dataFromPreDispatch) final;
+    EventDispatchHandlingState* preDispatchEventHandler(Event*) final;
+    void postDispatchEventHandler(Event*, EventDispatchHandlingState*) final;
 
     bool isURLAttribute(const Attribute&) const final;
     bool hasLegalLinkAttribute(const QualifiedName&) const final;
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index 54959cd..5d9fc80c 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -3510,7 +3510,7 @@
     updateTextTrackDisplay();
 }
 
-void* HTMLMediaElement::preDispatchEventHandler(Event* event)
+EventDispatchHandlingState* HTMLMediaElement::preDispatchEventHandler(Event* event)
 {
     if (event && event->type() == EventTypeNames::webkitfullscreenchange)
         configureMediaControls();
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
index 0bbb5fd..da7f4f96 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -419,7 +419,7 @@
 
     TextTrackContainer& ensureTextTrackContainer();
 
-    void* preDispatchEventHandler(Event*) final;
+    EventDispatchHandlingState* preDispatchEventHandler(Event*) final;
 
     void changeNetworkStateFromLoadingToIdle();
 
diff --git a/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp b/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp
index 9cc2cc25..00fe77a8 100644
--- a/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp
+++ b/third_party/WebKit/Source/core/html/forms/InputTypeView.cpp
@@ -229,6 +229,7 @@
 DEFINE_TRACE(ClickHandlingState)
 {
     visitor->trace(checkedRadioButton);
+    EventDispatchHandlingState::trace(visitor);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/InputTypeView.h b/third_party/WebKit/Source/core/html/forms/InputTypeView.h
index a6749aeb..51dbd87 100644
--- a/third_party/WebKit/Source/core/html/forms/InputTypeView.h
+++ b/third_party/WebKit/Source/core/html/forms/InputTypeView.h
@@ -34,6 +34,7 @@
 #define InputTypeView_h
 
 #include "core/CoreExport.h"
+#include "core/events/EventDispatcher.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/WebFocusType.h"
 #include "wtf/Allocator.h"
@@ -54,9 +55,9 @@
 class ComputedStyle;
 class TouchEvent;
 
-struct ClickHandlingState final : public GarbageCollected<ClickHandlingState> {
+class ClickHandlingState final : public EventDispatchHandlingState {
 public:
-    DECLARE_TRACE();
+    DECLARE_VIRTUAL_TRACE();
 
     bool checked;
     bool indeterminate;
diff --git a/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp b/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp
index 4419ad9..f231c08 100644
--- a/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp
@@ -68,7 +68,7 @@
         return new LayoutDetailsMarker(this);
     }
 
-    void* preDispatchEventHandler(Event* event) override
+    EventDispatchHandlingState* preDispatchEventHandler(Event* event) override
     {
         // Chromium opens autofill popup in a mousedown event listener
         // associated to the document. We don't want to open it in this case
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
index 21949b93..c1696c9 100644
--- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
@@ -225,7 +225,7 @@
     return enclosure;
 }
 
-void* MediaControlOverlayEnclosureElement::preDispatchEventHandler(Event* event)
+EventDispatchHandlingState* MediaControlOverlayEnclosureElement::preDispatchEventHandler(Event* event)
 {
     // When the media element is clicked or touched we want to make the overlay cast button visible
     // (if the other requirements are right) even if JavaScript is doing its own handling of the event.
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
index 6c90525..9afa7f1a 100644
--- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
+++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.h
@@ -80,7 +80,7 @@
 
 private:
     explicit MediaControlOverlayEnclosureElement(MediaControls&);
-    void* preDispatchEventHandler(Event*) override;
+    EventDispatchHandlingState* preDispatchEventHandler(Event*) override;
 };
 
 // ----------------------------
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp
index 290979ea..4a88d459 100644
--- a/third_party/WebKit/Source/core/input/EventHandler.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -70,6 +70,7 @@
 #include "core/layout/LayoutPart.h"
 #include "core/layout/LayoutTextControlSingleLine.h"
 #include "core/layout/LayoutView.h"
+#include "core/layout/api/LayoutViewItem.h"
 #include "core/loader/DocumentLoader.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderClient.h"
@@ -1902,7 +1903,7 @@
 {
     Document* doc = m_frame->document();
 
-    if (!doc->layoutView())
+    if (doc->layoutViewItem().isNull())
         return WebInputEventResult::NotHandled;
 
     FrameView* view = m_frame->view();
@@ -1913,7 +1914,7 @@
 
     HitTestRequest request(HitTestRequest::ReadOnly);
     HitTestResult result(request, vPoint);
-    doc->layoutView()->hitTest(result);
+    doc->layoutViewItem().hitTest(result);
 
     Node* node = result.innerNode();
     // Wheel events should not dispatch to text nodes.
@@ -2136,14 +2137,14 @@
 
     if (!eventTarget) {
         Document* document = m_frame->document();
-        if (!document->layoutView())
+        if (document->layoutViewItem().isNull())
             return WebInputEventResult::NotHandled;
 
         FrameView* view = m_frame->view();
         LayoutPoint viewPoint = view->rootFrameToContents(gestureEvent.position());
         HitTestRequest request(HitTestRequest::ReadOnly);
         HitTestResult result(request, viewPoint);
-        document->layoutView()->hitTest(result);
+        document->layoutViewItem().hitTest(result);
 
         eventTarget = result.innerNode();
 
@@ -2424,7 +2425,7 @@
 WebInputEventResult EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent)
 {
     Document* document = m_frame->document();
-    if (!document->layoutView())
+    if (document->layoutViewItem().isNull())
         return WebInputEventResult::NotHandled;
 
     FrameView* view = m_frame->view();
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.h b/third_party/WebKit/Source/core/layout/LayoutBlock.h
index b6dc09146..073fa932 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.h
@@ -269,7 +269,7 @@
 protected:
     bool recalcNormalFlowChildOverflowIfNeeded(LayoutObject*);
 public:
-    bool recalcChildOverflowAfterStyleChange();
+    virtual bool recalcChildOverflowAfterStyleChange();
     bool recalcOverflowAfterStyleChange();
 
     // An example explaining layout tree structure about first-line style:
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index b50666e..c0aad303 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1893,10 +1893,16 @@
         setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::StyleChange);
 }
 
-void LayoutObject::markContainingBlocksForOverflowRecalc()
+void LayoutObject::markAncestorsForOverflowRecalcIfNeeded()
 {
-    for (LayoutBlock* container = containingBlock(); container && !container->childNeedsOverflowRecalcAfterStyleChange(); container = container->containingBlock())
-        container->setChildNeedsOverflowRecalcAfterStyleChange();
+    LayoutObject* object = this;
+    do {
+        // Cell and row need to propagate the flag to their containing section and row as their containing block is the table wrapper.
+        // This enables us to only recompute overflow the modified sections / rows.
+        object = object->isTableCell() || object->isTableRow() ? object->parent() : object->containingBlock();
+        if (object)
+            object->setChildNeedsOverflowRecalcAfterStyleChange();
+    } while (object);
 }
 
 void LayoutObject::setNeedsOverflowRecalcAfterStyleChange()
@@ -1904,7 +1910,7 @@
     bool neededRecalc = needsOverflowRecalcAfterStyleChange();
     setSelfNeedsOverflowRecalcAfterStyleChange();
     if (!neededRecalc)
-        markContainingBlocksForOverflowRecalc();
+        markAncestorsForOverflowRecalcIfNeeded();
 }
 
 void LayoutObject::setStyle(PassRefPtr<ComputedStyle> style)
@@ -1974,6 +1980,14 @@
             container->setNeedsOverflowRecalcAfterStyleChange();
     }
 
+    if (diff.needsRecomputeOverflow() && !needsLayout()) {
+        // TODO(rhogan): Make inlines capable of recomputing overflow too.
+        if (isLayoutBlock())
+            setNeedsOverflowRecalcAfterStyleChange();
+        else
+            setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::StyleChange);
+    }
+
     if (diff.needsPaintInvalidationLayer() || updatedDiff.needsPaintInvalidationLayer())
         setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
     else if (diff.needsPaintInvalidationObject() || updatedDiff.needsPaintInvalidationObject())
@@ -2084,7 +2098,7 @@
 
         // Ditto.
         if (needsOverflowRecalcAfterStyleChange() && oldStyle->position() != m_style->position())
-            markContainingBlocksForOverflowRecalc();
+            markAncestorsForOverflowRecalcIfNeeded();
 
         setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::StyleChange);
     } else if (diff.needsPositionedMovementLayout()) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index 4eff15d..69bd973 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -1396,6 +1396,8 @@
     // Clears the IsScrollAnchorObject bit, unless any ScrollAnchor still refers to us.
     void maybeClearIsScrollAnchorObject();
 
+    void clearChildNeedsOverflowRecalcAfterStyleChange() { m_bitfields.setChildNeedsOverflowRecalcAfterStyleChange(false); }
+
 protected:
     enum LayoutObjectType {
         LayoutObjectBr,
@@ -1568,7 +1570,6 @@
     void setIsBackgroundAttachmentFixedObject(bool);
 
     void clearSelfNeedsOverflowRecalcAfterStyleChange() { m_bitfields.setSelfNeedsOverflowRecalcAfterStyleChange(false); }
-    void clearChildNeedsOverflowRecalcAfterStyleChange() { m_bitfields.setChildNeedsOverflowRecalcAfterStyleChange(false); }
     void setShouldInvalidateOverflowForPaint() { m_bitfields.setShouldInvalidateOverflowForPaint(true); }
     void setEverHadLayout() { m_bitfields.setEverHadLayout(true); }
 
@@ -1610,7 +1611,7 @@
 
     // FIXME: This should be 'markContaingBoxChainForOverflowRecalc when we make LayoutBox
     // recomputeOverflow-capable. crbug.com/437012 and crbug.com/434700.
-    inline void markContainingBlocksForOverflowRecalc();
+    inline void markAncestorsForOverflowRecalcIfNeeded();
 
     inline void markAncestorsForPaintInvalidation();
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
index 6d1bffb..a9babf6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
@@ -414,6 +414,19 @@
     }
 }
 
+bool LayoutTable::recalcChildOverflowAfterStyleChange()
+{
+    ASSERT(childNeedsOverflowRecalcAfterStyleChange());
+    clearChildNeedsOverflowRecalcAfterStyleChange();
+    bool childrenOverflowChanged = false;
+    for (LayoutTableSection* section = topSection(); section; section = sectionBelow(section)) {
+        if (!section->childNeedsOverflowRecalcAfterStyleChange())
+            continue;
+        childrenOverflowChanged |= section->recalcChildOverflowAfterStyleChange();
+    }
+    return childrenOverflowChanged;
+}
+
 void LayoutTable::layout()
 {
     ASSERT(needsLayout());
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.h b/third_party/WebKit/Source/core/layout/LayoutTable.h
index f34d128..850d5f78 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.h
@@ -401,6 +401,7 @@
 protected:
     void styleDidChange(StyleDifference, const ComputedStyle* oldStyle) override;
     void simplifiedNormalFlowLayout() override;
+    bool recalcChildOverflowAfterStyleChange() override;
     PaintInvalidationReason invalidatePaintIfNeeded(const PaintInvalidationState&) override;
     void invalidatePaintOfSubtreesIfNeeded(const PaintInvalidationState&) override;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
index 149d4f7..3f7335a2 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
@@ -237,9 +237,18 @@
     return newRow;
 }
 
+void LayoutTableRow::computeOverflow()
+{
+    clearAllOverflows();
+    addVisualEffectOverflow();
+    for (LayoutTableCell* cell = firstCell(); cell; cell = cell->nextCell())
+        addOverflowFromCell(cell);
+}
+
 void LayoutTableRow::addOverflowFromCell(const LayoutTableCell* cell)
 {
     // Non-row-spanning-cells don't create overflow (they are fully contained within this row).
+    // TODO(crbug.com/603993): This seems incorrect because cell may have visual effect overflow that should be included in this row.
     if (cell->rowSpan() == 1)
         return;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.h b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
index 9f7d6694..4bbd5609 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRow.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
@@ -122,7 +122,7 @@
 
     bool nodeAtPoint(HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
 
-    void addOverflowFromCell(const LayoutTableCell*);
+    void computeOverflow();
 
     const char* name() const override { return "LayoutTableRow"; }
 
@@ -133,6 +133,7 @@
     bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const override { return false; }
 
 private:
+    void addOverflowFromCell(const LayoutTableCell*);
     LayoutObjectChildList* virtualChildren() override { return children(); }
     const LayoutObjectChildList* virtualChildren() const override { return children(); }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index 2ac553a..40ca5ea3 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -953,9 +953,6 @@
 
     // Set the width of our section now.  The rows will also be this width.
     setLogicalWidth(table()->contentLogicalWidth());
-    m_overflow.clear();
-    m_overflowingCells.clear();
-    m_forceSlowPaintPathWithOverflowingCell = false;
 
     int vspacing = table()->vBorderSpacing();
     unsigned nEffCols = table()->numEffectiveColumns();
@@ -970,8 +967,6 @@
             rowLayoutObject->setLogicalWidth(logicalWidth());
             rowLayoutObject->setLogicalHeight(LayoutUnit(m_rowPos[r + 1] - m_rowPos[r] - vspacing));
             rowLayoutObject->updateLayerTransformAfterLayout();
-            rowLayoutObject->clearAllOverflows();
-            rowLayoutObject->addVisualEffectOverflow();
         }
 
         int rowHeightIncreaseForPagination = 0;
@@ -1062,9 +1057,6 @@
                 cell->computeOverflow(oldLogicalHeight, false);
             }
 
-            if (rowLayoutObject)
-                rowLayoutObject->addOverflowFromCell(cell);
-
             LayoutSize childOffset(cell->location() - oldCellRect.location());
             if (childOffset.width() || childOffset.height()) {
                 // If the child moved, we have to issue paint invalidations to it as well as any floating/positioned
@@ -1086,6 +1078,8 @@
                 }
             }
         }
+        if (rowLayoutObject)
+            rowLayoutObject->computeOverflow();
     }
 
     ASSERT(!needsLayout());
@@ -1107,6 +1101,9 @@
     unsigned totalCellsCount = nEffCols * totalRows;
     unsigned maxAllowedOverflowingCellsCount = totalCellsCount < gMinTableSizeToUseFastPaintPathWithOverflowingCell ? 0 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount;
 
+    m_overflow.clear();
+    m_overflowingCells.clear();
+    m_forceSlowPaintPathWithOverflowingCell = false;
 #if ENABLE(ASSERT)
     bool hasOverflowingCell = false;
 #endif
@@ -1138,6 +1135,36 @@
     ASSERT(hasOverflowingCell == this->hasOverflowingCell());
 }
 
+bool LayoutTableSection::recalcChildOverflowAfterStyleChange()
+{
+    ASSERT(childNeedsOverflowRecalcAfterStyleChange());
+    clearChildNeedsOverflowRecalcAfterStyleChange();
+    unsigned totalRows = m_grid.size();
+    unsigned numEffCols = table()->numEffectiveColumns();
+    bool childrenOverflowChanged = false;
+    for (unsigned r = 0; r < totalRows; r++) {
+        LayoutTableRow* rowLayouter = rowLayoutObjectAt(r);
+        if (!rowLayouter || !rowLayouter->childNeedsOverflowRecalcAfterStyleChange())
+            continue;
+        rowLayouter->clearChildNeedsOverflowRecalcAfterStyleChange();
+        bool rowChildrenOverflowChanged = false;
+        for (unsigned c = 0; c < numEffCols; c++) {
+            CellStruct& cs = cellAt(r, c);
+            LayoutTableCell* cell = cs.primaryCell();
+            if (!cell || cs.inColSpan || !cell->needsOverflowRecalcAfterStyleChange())
+                continue;
+            rowChildrenOverflowChanged |= cell->recalcOverflowAfterStyleChange();
+        }
+        if (rowChildrenOverflowChanged)
+            rowLayouter->computeOverflow();
+        childrenOverflowChanged |= rowChildrenOverflowChanged;
+    }
+    // TODO(crbug.com/604136): Add visual overflow from rows too.
+    if (childrenOverflowChanged)
+        computeOverflowFromCells(totalRows, numEffCols);
+    return childrenOverflowChanged;
+}
+
 int LayoutTableSection::calcBlockDirectionOuterBorder(BlockBorderSide side) const
 {
     unsigned totalCols = table()->numEffectiveColumns();
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.h b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
index bc28e97..2239b3f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
@@ -123,6 +123,7 @@
     int calcRowLogicalHeight();
     void layoutRows();
     void computeOverflowFromCells();
+    bool recalcChildOverflowAfterStyleChange();
 
     LayoutTable* table() const { return toLayoutTable(parent()); }
 
diff --git a/third_party/WebKit/Source/core/layout/api/LayoutItem.h b/third_party/WebKit/Source/core/layout/api/LayoutItem.h
index add6e58..5e12be4 100644
--- a/third_party/WebKit/Source/core/layout/api/LayoutItem.h
+++ b/third_party/WebKit/Source/core/layout/api/LayoutItem.h
@@ -179,6 +179,11 @@
         m_layoutObject->setNeedsLayoutAndPrefWidthsRecalc(reason);
     }
 
+    void computeLayerHitTestRects(LayerHitTestRects& layerRects) const
+    {
+        m_layoutObject->computeLayerHitTestRects(layerRects);
+    }
+
 protected:
     LayoutObject* layoutObject() { return m_layoutObject; }
     const LayoutObject* layoutObject() const { return m_layoutObject; }
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
index 352d0af..1adf1d0 100644
--- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
@@ -659,8 +659,8 @@
 
     HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(layoutObject->node());
     if (Document* contentDocument = element->contentDocument()) {
-        if (LayoutView* view = contentDocument->layoutView())
-            return view->compositor();
+        if (LayoutViewItem view = contentDocument->layoutViewItem())
+            return view.compositor();
     }
     return nullptr;
 }
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index 9686188..65f09ba 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -36,6 +36,7 @@
 #include "core/layout/LayoutGeometryMap.h"
 #include "core/layout/LayoutPart.h"
 #include "core/layout/LayoutView.h"
+#include "core/layout/api/LayoutViewItem.h"
 #include "core/layout/compositing/CompositedLayerMapping.h"
 #include "core/layout/compositing/PaintLayerCompositor.h"
 #include "core/page/ChromeClient.h"
@@ -786,13 +787,13 @@
     // Fullscreen HTML5 video when OverlayFullscreenVideo is enabled is implemented by replacing the
     // root cc::layer with the video layer so doing this optimization causes the compositor to think
     // that there are no handlers, therefore skip it.
-    if (!document->layoutView()->compositor()->inOverlayFullscreenVideo()) {
+    if (!document->layoutViewItem().compositor()->inOverlayFullscreenVideo()) {
         for (const auto& eventTarget : *targets) {
             EventTarget* target = eventTarget.key;
             Node* node = target->toNode();
             if (target->toDOMWindow() || node == document || node == document->documentElement() || node == document->body()) {
-                if (LayoutView* layoutView = document->layoutView()) {
-                    layoutView->computeLayerHitTestRects(rects);
+                if (LayoutViewItem layoutView = document->layoutViewItem()) {
+                    layoutView.computeLayerHitTestRects(rects);
                 }
                 return;
             }
diff --git a/third_party/WebKit/Source/core/style/BorderData.h b/third_party/WebKit/Source/core/style/BorderData.h
index 72d28e1..eedc12a8 100644
--- a/third_party/WebKit/Source/core/style/BorderData.h
+++ b/third_party/WebKit/Source/core/style/BorderData.h
@@ -114,6 +114,11 @@
             && m_bottomRight == o.m_bottomRight;
     }
 
+    bool visualOverflowEqual(const BorderData& o) const
+    {
+        return m_image.outset() == o.m_image.outset();
+    }
+
     bool operator!=(const BorderData& o) const
     {
         return !(*this == o);
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 05085ff..f1f2647 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -535,10 +535,6 @@
             && *rareNonInheritedData->m_flexibleBox.get() != *other.rareNonInheritedData->m_flexibleBox.get())
             return true;
 
-        // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
-        if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get()))
-            return true;
-
         if (!rareNonInheritedData->reflectionDataEquivalent(*other.rareNonInheritedData.get()))
             return true;
 
@@ -659,11 +655,6 @@
     if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE))
         return true;
 
-    if (!m_background->outline().visuallyEqual(other.m_background->outline())) {
-        // FIXME: We only really need to recompute the overflow but we don't have an optimized layout for it.
-        return true;
-    }
-
     if (hasPseudoStyle(PseudoIdScrollbar) != other.hasPseudoStyle(PseudoIdScrollbar))
         return true;
 
@@ -732,6 +723,9 @@
 
 bool ComputedStyle::diffNeedsPaintInvalidationObject(const ComputedStyle& other) const
 {
+    if (!m_background->outline().visuallyEqual(other.m_background->outline()))
+        return true;
+
     if (inherited_flags._visibility != other.inherited_flags._visibility
         || inherited_flags.m_printColorAdjust != other.inherited_flags.m_printColorAdjust
         || inherited_flags._insideLink != other.inherited_flags._insideLink
@@ -750,6 +744,7 @@
         if (rareNonInheritedData->userDrag != other.rareNonInheritedData->userDrag
             || rareNonInheritedData->m_objectFit != other.rareNonInheritedData->m_objectFit
             || rareNonInheritedData->m_objectPosition != other.rareNonInheritedData->m_objectPosition
+            || !rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get())
             || !rareNonInheritedData->shapeOutsideDataEquivalent(*other.rareNonInheritedData.get())
             || !rareNonInheritedData->clipPathDataEquivalent(*other.rareNonInheritedData.get())
             || (visitedLinkBorderLeftColor() != other.visitedLinkBorderLeftColor() && borderLeftWidth())
@@ -783,6 +778,9 @@
         if (rareNonInheritedData->m_filter != other.rareNonInheritedData->m_filter)
             diff.setFilterChanged();
 
+        if (!rareNonInheritedData->shadowDataEquivalent(*other.rareNonInheritedData.get()))
+            diff.setNeedsRecomputeOverflow();
+
         if (rareNonInheritedData->m_backdropFilter != other.rareNonInheritedData->m_backdropFilter)
             diff.setBackdropFilterChanged();
 
@@ -790,6 +788,9 @@
             diff.setFilterChanged();
     }
 
+    if (!m_background->outline().visuallyEqual(other.m_background->outline()) || !surround->border.visualOverflowEqual(other.surround->border))
+        diff.setNeedsRecomputeOverflow();
+
     if (!diff.needsPaintInvalidation()) {
         if (inherited->color != other.inherited->color
             || inherited->visitedLinkColor != other.inherited->visitedLinkColor
diff --git a/third_party/WebKit/Source/core/style/StyleDifference.h b/third_party/WebKit/Source/core/style/StyleDifference.h
index 360642f..e5adf27 100644
--- a/third_party/WebKit/Source/core/style/StyleDifference.h
+++ b/third_party/WebKit/Source/core/style/StyleDifference.h
@@ -27,6 +27,7 @@
     StyleDifference()
         : m_paintInvalidationType(NoPaintInvalidation)
         , m_layoutType(NoLayout)
+        , m_recomputeOverflow(false)
         , m_propertySpecificDifferences(0)
     { }
 
@@ -66,6 +67,9 @@
     bool needsFullLayout() const { return m_layoutType == FullLayout; }
     void setNeedsFullLayout() { m_layoutType = FullLayout; }
 
+    bool needsRecomputeOverflow() const { return m_recomputeOverflow; }
+    void setNeedsRecomputeOverflow() { m_recomputeOverflow = true; }
+
     bool transformChanged() const { return m_propertySpecificDifferences & TransformChanged; }
     void setTransformChanged() { m_propertySpecificDifferences |= TransformChanged; }
 
@@ -98,7 +102,7 @@
         FullLayout
     };
     unsigned m_layoutType : 2;
-
+    unsigned m_recomputeOverflow : 1;
     unsigned m_propertySpecificDifferences : 6;
 };
 
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
index aa5e74e..ceaf184d 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
@@ -66,7 +66,7 @@
     return EventTargetNames::DedicatedWorkerGlobalScope;
 }
 
-void DedicatedWorkerGlobalScope::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState)
+void DedicatedWorkerGlobalScope::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, ExceptionState& exceptionState)
 {
     // Disentangle the port in preparation for sending it to the remote context.
     OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(context, ports, exceptionState);
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h
index 85a87c0..a4e0780 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h
@@ -56,7 +56,7 @@
     // EventTarget
     const AtomicString& interfaceName() const override;
 
-    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue>, const MessagePortArray*, ExceptionState&);
+    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue>, const MessagePortArray&, ExceptionState&);
 
     DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
 
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
index e52c8f7..51c02e75 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.cpp
@@ -32,7 +32,7 @@
     m_contextProxy->workerObjectDestroyed();
 }
 
-void InProcessWorkerBase::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState)
+void InProcessWorkerBase::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, ExceptionState& exceptionState)
 {
     ASSERT(m_contextProxy);
     // Disentangle the port in preparation for sending it to the remote context.
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h
index da0adb99..96e29ad 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerBase.h
@@ -31,7 +31,7 @@
 public:
     ~InProcessWorkerBase() override;
 
-    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionState&);
+    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray&, ExceptionState&);
     void terminate();
 
     // ActiveDOMObject
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp
index 9d7c10f..9389cb2 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp
@@ -43,7 +43,7 @@
     return EventTargetNames::CompositorWorkerGlobalScope;
 }
 
-void CompositorWorkerGlobalScope::postMessage(ExecutionContext* executionContext, PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState)
+void CompositorWorkerGlobalScope::postMessage(ExecutionContext* executionContext, PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, ExceptionState& exceptionState)
 {
     // Disentangle the port in preparation for sending it to the remote context.
     OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(executionContext, ports, exceptionState);
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.h b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.h
index b21147e..b7e1d00 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.h
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.h
@@ -23,7 +23,7 @@
     // EventTarget
     const AtomicString& interfaceName() const override;
 
-    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue>, const MessagePortArray*, ExceptionState&);
+    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue>, const MessagePortArray&, ExceptionState&);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
 
     int requestAnimationFrame(FrameRequestCallback*);
diff --git a/third_party/WebKit/Source/modules/compositorworker/OWNERS b/third_party/WebKit/Source/modules/compositorworker/OWNERS
new file mode 100644
index 0000000..ab4484b
--- /dev/null
+++ b/third_party/WebKit/Source/modules/compositorworker/OWNERS
@@ -0,0 +1,2 @@
+# for Worker related changes
+kinuko@chromium.org
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
index 8c1a971..aa39db2 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
@@ -49,7 +49,7 @@
     return EventTargetNames::ServiceWorker;
 }
 
-void ServiceWorker::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState)
+void ServiceWorker::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, ExceptionState& exceptionState)
 {
     ServiceWorkerContainerClient* client = ServiceWorkerContainerClient::from(getExecutionContext());
     if (!client || !client->provider()) {
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h
index 7b37c77e..7ceddc35 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.h
@@ -59,7 +59,7 @@
     // Override 'operator new' to enforce allocation of eagerly finalized object.
     DECLARE_EAGER_FINALIZATION_OPERATOR_NEW();
 
-    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionState&);
+    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray&, ExceptionState&);
 
     String scriptURL() const;
     String state() const;
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
index faeda840..107ce6c5 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
@@ -67,7 +67,7 @@
     return String();
 }
 
-void ServiceWorkerClient::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionState& exceptionState)
+void ServiceWorkerClient::postMessage(ExecutionContext* context, PassRefPtr<SerializedScriptValue> message, const MessagePortArray& ports, ExceptionState& exceptionState)
 {
     // Disentangle the port in preparation for sending it to the remote context.
     OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(context, ports, exceptionState);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h
index 4bed79f..4a2419d 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h
@@ -34,7 +34,7 @@
     String url() const { return m_url; }
     String frameType() const;
     String id() const { return m_uuid; }
-    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionState&);
+    void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray&, ExceptionState&);
 
     DEFINE_INLINE_VIRTUAL_TRACE() { }
 
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
index c12eb4a..bd7aeb5 100644
--- a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
@@ -52,6 +52,7 @@
 #include "platform/Logging.h"
 #include "platform/blob/BlobData.h"
 #include "platform/heap/Handle.h"
+#include "platform/weborigin/KnownPorts.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/Platform.h"
 #include "wtf/Assertions.h"
@@ -307,7 +308,7 @@
         return;
     }
 
-    if (!Platform::current()->portAllowed(m_url)) {
+    if (!isPortAllowedForScheme(m_url)) {
         m_state = CLOSED;
         exceptionState.throwSecurityError("The port " + String::number(m_url.port()) + " is not allowed.");
         return;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index ee871dd..4e2079a 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -326,6 +326,7 @@
     "//cc",
     "//gpu/command_buffer/client:gles2_c_lib",
     "//gpu/command_buffer/client:gles2_interface",
+    "//net",
     "//skia",
     "//third_party:jpeg",
     "//third_party/WebKit/Source/wtf",
diff --git a/third_party/WebKit/Source/platform/blink_platform.gyp b/third_party/WebKit/Source/platform/blink_platform.gyp
index 204eaa1..746cb69 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gyp
+++ b/third_party/WebKit/Source/platform/blink_platform.gyp
@@ -137,6 +137,7 @@
       '<(DEPTH)/mojo/mojo_edk.gyp:mojo_system_impl',
       '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings',
       '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support',
+      '<(DEPTH)/net/net.gyp:net',
       '<(DEPTH)/skia/skia.gyp:skia',
       '<(DEPTH)/third_party/harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng',
       '<(DEPTH)/third_party/iccjpeg/iccjpeg.gyp:iccjpeg',
diff --git a/third_party/WebKit/Source/platform/weborigin/DEPS b/third_party/WebKit/Source/platform/weborigin/DEPS
new file mode 100644
index 0000000..41871a2
--- /dev/null
+++ b/third_party/WebKit/Source/platform/weborigin/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+    # net/ includes should be allowed only in a limited set of directories,
+    # so we have separate DEPS from platform's one.
+    "+net/base",
+]
diff --git a/third_party/WebKit/Source/platform/weborigin/KnownPorts.cpp b/third_party/WebKit/Source/platform/weborigin/KnownPorts.cpp
index 3612c7fc..4e68645 100644
--- a/third_party/WebKit/Source/platform/weborigin/KnownPorts.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/KnownPorts.cpp
@@ -26,6 +26,11 @@
 
 #include "platform/weborigin/KnownPorts.h"
 
+#include "net/base/port_util.h"
+#include "platform/weborigin/KURL.h"
+#include "wtf/text/StringUTF8Adaptor.h"
+#include "wtf/text/WTFString.h"
+
 namespace blink {
 
 bool isDefaultPortForProtocol(unsigned short port, const WTF::String& protocol)
@@ -60,4 +65,18 @@
     return 0;
 }
 
+bool isPortAllowedForScheme(const KURL& url)
+{
+    // Returns true for URLs without a port specified. This is needed to let
+    // through non-network schemes that don't go over the network.
+    if (!url.hasPort())
+        return true;
+    String protocol = url.protocol().isNull() ? "" : url.protocol().lower();
+    unsigned short effectivePort = url.port();
+    if (!effectivePort)
+        effectivePort = defaultPortForProtocol(protocol);
+    StringUTF8Adaptor utf8(protocol);
+    return net::IsPortAllowedForScheme(effectivePort, std::string(utf8.data(), utf8.length()));
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/weborigin/KnownPorts.h b/third_party/WebKit/Source/platform/weborigin/KnownPorts.h
index c347a2f..0bb16fe 100644
--- a/third_party/WebKit/Source/platform/weborigin/KnownPorts.h
+++ b/third_party/WebKit/Source/platform/weborigin/KnownPorts.h
@@ -39,6 +39,9 @@
 // Returns 0 for unknown protocols. |protocol| must be lower case.
 PLATFORM_EXPORT unsigned short defaultPortForProtocol(const WTF::String& protocol);
 
+// Returns true if the port of the |url| is allowed for the scheme of the |url|.
+PLATFORM_EXPORT bool isPortAllowedForScheme(const KURL&);
+
 } // namespace blink
 
 #endif // KnownPorts_h
diff --git a/third_party/WebKit/Source/platform/weborigin/KnownPortsTest.cpp b/third_party/WebKit/Source/platform/weborigin/KnownPortsTest.cpp
index 78035dc3..60c6b62 100644
--- a/third_party/WebKit/Source/platform/weborigin/KnownPortsTest.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/KnownPortsTest.cpp
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "platform/weborigin/KURL.h"
 #include "platform/weborigin/KnownPorts.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
@@ -66,5 +67,27 @@
         EXPECT_EQ(test.port, defaultPortForProtocol(test.protocol));
 }
 
+TEST(KnownPortsTest, IsPortAllowedForScheme)
+{
+    struct TestCase {
+        const char* url;
+        const bool isAllowed;
+    } inputs[] = {
+        // Allowed ones.
+        { "http://example.com", true },
+        { "file://example.com", true },
+        { "file://example.com:87", true },
+        { "ftp://example.com:21", true },
+        { "http://example.com:80", true },
+        { "http://example.com:8889", true },
+
+        // Disallowed ones.
+        { "ftp://example.com:87", false },
+        { "ws://example.com:21", false },
+    };
+
+    for (const TestCase& test : inputs)
+        EXPECT_EQ(test.isAllowed, isPortAllowedForScheme(KURL(ParsedURLString, test.url)));
+}
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 3a6e5fc3..fe584f14 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -842,7 +842,8 @@
 
     LocalFrame* frame = toLocalFrame(webViewHelper.webViewImpl()->page()->mainFrame());
     NonThrowableExceptionState exceptionState;
-    frame->domWindow()->postMessage(SerializedScriptValueFactory::instance().create("message"), 0, "*", frame->localDOMWindow(), exceptionState);
+    MessagePortArray messagePorts;
+    frame->domWindow()->postMessage(SerializedScriptValueFactory::instance().create("message"), messagePorts, "*", frame->localDOMWindow(), exceptionState);
     webViewHelper.reset();
     EXPECT_FALSE(exceptionState.hadException());
 
diff --git a/third_party/WebKit/public/platform/Platform.h b/third_party/WebKit/public/platform/Platform.h
index b8fb380..c7791e6 100644
--- a/third_party/WebKit/public/platform/Platform.h
+++ b/third_party/WebKit/public/platform/Platform.h
@@ -317,8 +317,6 @@
 
     virtual bool isReservedIPAddress(const WebString& host) const { return false; }
 
-    virtual bool portAllowed(const WebURL&) const { return false; }
-
     // Returns true and stores the position of the end of the headers to |*end|
     // if the headers part ends in |bytes[0..size]|. Returns false otherwise.
     virtual bool parseMultipartHeadersFromBody(const char* bytes, size_t /* size */, WebURLResponse*, size_t* end) const { return false; }
diff --git a/tools/android/loading/gce/google_storage_accessor.py b/tools/android/loading/gce/google_storage_accessor.py
new file mode 100644
index 0000000..59c47da
--- /dev/null
+++ b/tools/android/loading/gce/google_storage_accessor.py
@@ -0,0 +1,60 @@
+# Copyright 2016 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.
+
+from gcloud import storage
+from oauth2client.client import GoogleCredentials
+
+
+class GoogleStorageAccessor(object):
+  """Utility class providing helpers for Google Cloud Storage.
+  """
+  def __init__(self, project_name, bucket_name):
+    """project_name is the name of the Google Cloud project.
+    bucket_name is the name of the bucket that is used for Cloud Storage calls.
+    """
+    self._credentials = GoogleCredentials.get_application_default()
+    self._project_name = project_name
+    self._bucket_name = bucket_name
+
+  def _GetStorageClient(self):
+    """Returns the storage client associated with the project"""
+    return storage.Client(project = self._project_name,
+                          credentials = self._credentials)
+
+  def _GetStorageBucket(self, storage_client):
+    return storage_client.get_bucket(self._bucket_name)
+
+  def UploadFile(self, filename_src, filename_dest):
+    """Uploads a file to Google Cloud Storage
+
+    Args:
+      filename_src: name of the local file
+      filename_dest: name of the file in Google Cloud Storage
+
+    Returns:
+      The URL of the file in Google Cloud Storage.
+    """
+    client = self._GetStorageClient()
+    bucket = self._GetStorageBucket(client)
+    blob = bucket.blob(filename_dest)
+    with open(filename_src) as file_src:
+      blob.upload_from_file(file_src)
+    return blob.public_url
+
+  def UploadString(self, data_string, filename_dest):
+    """Uploads a string to Google Cloud Storage
+
+    Args:
+      data_string: the contents of the file to be uploaded
+      filename_dest: name of the file in Google Cloud Storage
+
+    Returns:
+      The URL of the file in Google Cloud Storage.
+    """
+    client = self._GetStorageClient()
+    bucket = self._GetStorageBucket(client)
+    blob = bucket.blob(filename_dest)
+    blob.upload_from_string(data_string)
+    return blob.public_url
+
diff --git a/tools/android/loading/gce/main.py b/tools/android/loading/gce/main.py
index 2988113..0ef2caec 100644
--- a/tools/android/loading/gce/main.py
+++ b/tools/android/loading/gce/main.py
@@ -10,19 +10,16 @@
 import subprocess
 import sys
 
-from gcloud import storage
-from gcloud.exceptions import NotFound
-from oauth2client.client import GoogleCredentials
-
 # NOTE: The parent directory needs to be first in sys.path to avoid conflicts
 # with catapult modules that have colliding names, as catapult inserts itself
 # into the path as the second element. This is an ugly and fragile hack.
 sys.path.insert(0,
     os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
 import controller
+from google_storage_accessor import GoogleStorageAccessor
 import loading_trace
-import options
 from loading_trace_database import LoadingTraceDatabase
+import options
 
 
 class ServerApp(object):
@@ -40,12 +37,9 @@
     self._tasks_lock = threading.Lock()  # Protects _tasks and _failed_tasks.
     self._initial_task_count = -1
     self._start_time = None
-    print 'Initializing credentials'
-    self._credentials = GoogleCredentials.get_application_default()
     print 'Reading configuration'
     with open(configuration_file) as config_json:
        config = json.load(config_json)
-       self._project_name = config['project_name']
 
        # Separate the cloud storage path into the bucket and the base path under
        # the bucket.
@@ -58,6 +52,8 @@
            self._base_path_in_bucket += '/'
 
        self._src_path = config['src_path']
+       self._google_storage_accessor = GoogleStorageAccessor(
+           project_name=config['project_name'], bucket_name=self._bucket_name)
 
     # Initialize the global options that will be used during trace generation.
     options.OPTIONS.ParseArgs([])
@@ -67,46 +63,6 @@
     """Returns True if the application is currently processing tasks."""
     return self._thread is not None and self._thread.is_alive()
 
-  def _GetStorageClient(self):
-    return storage.Client(project = self._project_name,
-                          credentials = self._credentials)
-
-  def _GetStorageBucket(self, storage_client):
-    return storage_client.get_bucket(self._bucket_name)
-
-  def _UploadFile(self, filename_src, filename_dest):
-    """Uploads a file to Google Cloud Storage
-
-    Args:
-      filename_src: name of the local file
-      filename_dest: name of the file in Google Cloud Storage
-
-    Returns:
-      The URL of the file in Google Cloud Storage.
-    """
-    client = self._GetStorageClient()
-    bucket = self._GetStorageBucket(client)
-    blob = bucket.blob(filename_dest)
-    with open(filename_src) as file_src:
-      blob.upload_from_file(file_src)
-    return blob.public_url
-
-  def _UploadString(self, data_string, filename_dest):
-    """Uploads a string to Google Cloud Storage
-
-    Args:
-      data_string: the contents of the file to be uploaded
-      filename_dest: name of the file in Google Cloud Storage
-
-    Returns:
-      The URL of the file in Google Cloud Storage.
-    """
-    client = self._GetStorageClient()
-    bucket = self._GetStorageBucket(client)
-    blob = bucket.blob(filename_dest)
-    blob.upload_from_string(data_string)
-    return blob.public_url
-
   def _GenerateTrace(self, url, emulate_device, emulate_network, filename,
                      log_filename):
     """ Generates a trace on _thread.
@@ -210,7 +166,8 @@
         if trace_metadata['succeeded']:
           print 'Uploading: %s' % remote_filename
           remote_trace_location = traces_dir + remote_filename
-          self._UploadFile(local_filename, remote_trace_location)
+          self._google_storage_accessor.UploadFile(local_filename,
+                                           remote_trace_location)
           full_cloud_storage_path = ('gs://' + self._bucket_name + '/' +
               remote_trace_location)
           trace_database.AddTrace(full_cloud_storage_path, trace_metadata)
@@ -220,21 +177,25 @@
           self._failed_tasks.append({ "url": url, "repeat": repeat})
           self._tasks_lock.release()
           if os.path.isfile(local_filename):
-            self._UploadFile(local_filename, failures_dir + remote_filename)
+            self._google_storage_accessor.UploadFile(local_filename,
+                                            failures_dir + remote_filename)
         print 'Uploading log'
-        self._UploadFile(log_filename, logs_dir + remote_filename)
+        self._google_storage_accessor.UploadFile(log_filename,
+                                         logs_dir + remote_filename)
       # Pop once task is finished, for accurate status tracking.
       self._tasks_lock.acquire()
       url = self._tasks.pop()
       self._tasks_lock.release()
 
-    self._UploadString(json.dumps(trace_database.ToJsonDict(), indent=2),
-                       traces_dir + 'trace_database.json')
+    self._google_storage_accessor.UploadString(
+        json.dumps(trace_database.ToJsonDict(), indent=2),
+        traces_dir + 'trace_database.json')
 
     if len(self._failed_tasks) > 0:
       print 'Uploading failing URLs'
-      self._UploadString(json.dumps(self._failed_tasks, indent=2),
-                         failures_dir + 'failures.json')
+      self._google_storage_accessor.UploadString(
+          json.dumps(self._failed_tasks, indent=2),
+          failures_dir + 'failures.json')
 
   def _SetTaskList(self, http_body):
     """Sets the list of tasks and starts processing them
diff --git a/tools/gn/args.cc b/tools/gn/args.cc
index 60ee7b2..1034ea1 100644
--- a/tools/gn/args.cc
+++ b/tools/gn/args.cc
@@ -245,6 +245,7 @@
   static const char kX86[] = "x86";
   static const char kX64[] = "x64";
   static const char kArm[] = "arm";
+  static const char kMips[] = "mipsel";
   const char* arch = nullptr;
 
   // Set the host CPU architecture based on the underlying OS, not
@@ -256,6 +257,8 @@
     arch = kX64;
   else if (os_arch.substr(3) == "arm")
     arch = kArm;
+  else if (os_arch == "mips")
+    arch = kMips;
   else
     CHECK(false) << "OS architecture not handled.";
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 78174653..5d280b6 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -19726,6 +19726,15 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Audio.InputRestartAttemptsMac">
+  <owner>henrika@chromium.org</owner>
+  <summary>
+    Counts the total number of times an attempt to restart input audio has been
+    done. The value is stored once when a stream is closed and updated when it
+    has been detected that input audio callbacks are not generated as expected.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.InputStartupSuccessMac" enum="BooleanSuccess">
   <owner>henrika@chromium.org</owner>
   <summary>
@@ -35110,6 +35119,12 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.ExportedPasswordsPerUserInCSV">
+  <owner>xunlu@chromium.org</owner>
+  <owner>vabr@chromium.org</owner>
+  <summary>The number of passwords exported in CSV format per user.</summary>
+</histogram>
+
 <histogram name="PasswordManager.FilledCredentialWasFromAndroidApp"
     enum="PasswordManagerFilledAndroidCredentials">
   <owner>msramek@chromium.org</owner>
@@ -35151,6 +35166,22 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.ImportedPasswordsPerUserInCSV">
+  <owner>xunlu@chromium.org</owner>
+  <owner>vabr@chromium.org</owner>
+  <summary>The number of passwords imported in CSV format per user</summary>
+</histogram>
+
+<histogram name="PasswordManager.ImportPasswordFromCSVResult"
+    enum="PasswordImportFromCSVResult">
+  <owner>xunlu@chromium.org</owner>
+  <owner>vabr@chromium.org</owner>
+  <summary>
+    The response code of successful or failed password import attempt from a CSV
+    file.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.InfoBarResponse" enum="InfoBarResponse">
   <owner>vabr@chromium.org</owner>
   <obsolete>
@@ -35382,6 +35413,16 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.StorePasswordImportedFromCSVResult"
+    enum="BooleanSuccess">
+  <owner>xunlu@chromium.org</owner>
+  <owner>vabr@chromium.org</owner>
+  <summary>
+    Whether password manager stored passwords imported from CSV file
+    successfully.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.StoreReadyWhenWiping" enum="Boolean">
   <owner>vabr@chromium.org</owner>
   <summary>
@@ -79183,6 +79224,14 @@
   <int value="12" label="Generation triggered by autocomplete attributes"/>
 </enum>
 
+<enum name="PasswordImportFromCSVResult" type="int">
+  <int value="0" label="Password import succeeded"/>
+  <int value="1" label="Password import failed due to IO error"/>
+  <int value="2" label="Password import failed due to malformed CSV"/>
+  <int value="3" label="Password import failed due to missing content"/>
+  <int value="4" label="Boundary value"/>
+</enum>
+
 <enum name="PasswordManagerActionsTaken" type="int">
   <obsolete>
     Deprecated as of Chrome 32. See PasswordManagerActionsTakenWithPsl