diff --git a/AUTHORS b/AUTHORS
index 76a383b..cab91e8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -464,6 +464,7 @@
 Matthew Turk <matthewturk@gmail.com>
 Matthew Willis <appamatto@gmail.com>
 Matthias Reitinger <reimarvin@gmail.com>
+Matthieu Rigolot <matthieu.rigolot@gmail.com>
 Max Perepelitsyn <pph34r@gmail.com>
 Max Vujovic <mvujovic@adobe.com>
 Mayank Gupta <mayank.g1@samsung.com>
diff --git a/DEPS b/DEPS
index 86d7f0e..dc0c3266 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '77a7a1b57c16c97f056c1e50c03bdc954947778c',
+  'skia_revision': 'b37cb236c3a698b45a7d0deca0df32bb70bbaaa6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '88cea110a5d3182c65c680f702b5c24005423de8',
+  'v8_revision': '37fd9c202d53958f1a6d3c7b1bdedddb57771c62',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '071d78690a4e2becffaeeb32fe210ee58ab3e532',
+  'pdfium_revision': 'ac2e04797b258115b2dc768a56377d7e78038f42',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'f20052d2acdba42cef9fb6e300d573dbcb2898b1',
+  'catapult_revision': '5c71aaccc396cfbd0383a2e09d832aa198e5ae0d',
   # 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/PRESUBMIT.py b/PRESUBMIT.py
index 686ae51..34fb5e6 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -2315,6 +2315,8 @@
   results.extend(_CommonChecks(input_api, output_api))
   results.extend(_CheckValidHostsInDEPS(input_api, output_api))
   results.extend(
+      input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
+  results.extend(
       input_api.canned_checks.CheckGNFormatted(input_api, output_api))
   results.extend(_CheckUmaHistogramChanges(input_api, output_api))
   results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
@@ -2369,6 +2371,8 @@
       output_api,
       json_url='http://chromium-status.appspot.com/current?format=json'))
 
+  results.extend(
+      input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
   results.extend(input_api.canned_checks.CheckChangeHasBugField(
       input_api, output_api))
   results.extend(input_api.canned_checks.CheckChangeHasDescription(
diff --git a/WATCHLISTS b/WATCHLISTS
index ddac364b..2d4fa4b 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1212,8 +1212,7 @@
     },
     'blink_device_orientation': {
       'filepath': 'third_party/WebKit/Source/modules/device_orientation/' \
-                  '|third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/' \
-                  '|third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/' \
+                  '|third_party/WebKit/LayoutTests/device_orientation/' \
                   '|third_party/WebKit/Source/core/frame/PlatformEvent(Controller|Dispatcher)' \
                   '|third_party/WebKit/Source/core/frame/DeviceSingleWindowEventController'
     },
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentViewClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentViewClient.java
index ff33c778..c258f92 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentViewClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentViewClient.java
@@ -4,15 +4,10 @@
 
 package org.chromium.android_webview;
 
-import android.content.Context;
-import android.content.Intent;
 import android.view.KeyEvent;
 
-import org.chromium.base.Log;
 import org.chromium.content.browser.ContentViewClient;
 
-import java.net.URISyntaxException;
-
 /**
  * ContentViewClient implementation for WebView
  */
@@ -22,40 +17,12 @@
     private final AwContentsClient mAwContentsClient;
     private final AwSettings mAwSettings;
     private final AwContents mAwContents;
-    private final Context mContext;
 
     public AwContentViewClient(AwContentsClient awContentsClient, AwSettings awSettings,
-            AwContents awContents, Context context) {
+            AwContents awContents) {
         mAwContentsClient = awContentsClient;
         mAwSettings = awSettings;
         mAwContents = awContents;
-        mContext = context;
-    }
-
-    @Override
-    public void onBackgroundColorChanged(int color) {
-        mAwContentsClient.onBackgroundColorChanged(color);
-    }
-
-    @Override
-    public void onStartContentIntent(Context context, String contentUrl, boolean isMainFrame) {
-        // Make sure that this URL is a valid scheme for this callback if interpreted as an intent,
-        // even though we don't dispatch it as an intent here, because many WebView apps will once
-        // it reaches them.
-        String scheme = null;
-        try {
-            Intent intent = Intent.parseUri(contentUrl, Intent.URI_INTENT_SCHEME);
-            scheme = intent.getScheme();
-        } catch (URISyntaxException e) {
-            // Just don't set the scheme, it will be rejected.
-        }
-        if (!isAcceptableContentIntentScheme(scheme)) {
-            Log.w(TAG, "Invalid scheme for URI %s", contentUrl);
-            return;
-        }
-        // Comes from WebViewImpl::detectContentOnTouch in Blink, so must be user-initiated, and
-        // isn't a redirect.
-        mAwContentsClient.shouldIgnoreNavigation(context, contentUrl, isMainFrame, true, false);
     }
 
     @Override
@@ -63,7 +30,7 @@
         if (mAwContentsClient.hasWebViewClient()) {
             // The check below is reflecting Chrome's behavior and is a workaround for
             // http://b/7697782.
-            if (!ContentViewClient.shouldPropagateKey(event.getKeyCode())) return true;
+            if (!shouldPropagateKey(event.getKeyCode())) return true;
             return mAwContentsClient.shouldOverrideKeyEvent(event);
         }
 
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 83b9150..7c8df9f 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -762,7 +762,7 @@
         mAwViewMethods = new AwViewMethodsImpl();
         mFullScreenTransitionsState = new FullScreenTransitionsState(
                 mContainerView, mInternalAccessAdapter, mAwViewMethods);
-        mContentViewClient = new AwContentViewClient(contentsClient, settings, this, mContext);
+        mContentViewClient = new AwContentViewClient(contentsClient, settings, this);
         mLayoutSizer = dependencyFactory.createLayoutSizer();
         mSettings = settings;
         mLayoutSizer.setDelegate(new AwLayoutSizerDelegate());
@@ -1056,7 +1056,7 @@
         mWindowAndroid = getWindowAndroid(mContext);
         mContentViewCore = new ContentViewCore(mContext, PRODUCT_VERSION);
         mViewAndroidDelegate = new AwViewAndroidDelegate(mContainerView,
-                mContentViewCore.getRenderCoordinates());
+                mContentsClient, mContentViewCore.getRenderCoordinates());
         initializeContentViewCore(mContentViewCore, mContext, mViewAndroidDelegate,
                 mInternalAccessAdapter, webContents, new AwGestureStateListener(),
                 mContentViewClient, mWindowAndroid.getWindowAndroid());
diff --git a/android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java b/android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java
index 80753a42..d2f26ef6 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java
@@ -4,6 +4,7 @@
 
 package org.chromium.android_webview;
 
+import android.content.Intent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -21,6 +22,9 @@
  * Implementation of the abstract class {@link ViewAndroidDelegate} for WebView.
  */
 public class AwViewAndroidDelegate extends ViewAndroidDelegate {
+    /** Used for logging. */
+    private static final String TAG = "AwVAD";
+
     /**
      * The current container view. This view can be updated with
      * {@link #updateCurrentContainerView()}.
@@ -33,6 +37,7 @@
      */
     private final Map<View, Position> mAnchorViews = new LinkedHashMap<>();
 
+    private final AwContentsClient mContentsClient;
     private final RenderCoordinates mRenderCoordinates;
 
     /**
@@ -59,8 +64,10 @@
     }
 
     @VisibleForTesting
-    public AwViewAndroidDelegate(ViewGroup containerView, RenderCoordinates renderCoordinates) {
+    public AwViewAndroidDelegate(ViewGroup containerView, AwContentsClient contentsClient,
+            RenderCoordinates renderCoordinates) {
         mContainerView = containerView;
+        mContentsClient = contentsClient;
         mRenderCoordinates = renderCoordinates;
     }
 
@@ -137,6 +144,24 @@
     }
 
     @Override
+    public void onBackgroundColorChanged(int color) {
+        mContentsClient.onBackgroundColorChanged(color);
+    }
+
+    @Override
+    public void startContentIntent(Intent intent, String contentUrl, boolean isMainFrame) {
+        // Make sure that this URL is a valid scheme for this callback if interpreted as an intent,
+        // even though we don't dispatch it as an intent here, because many WebView apps will once
+        // it reaches them.
+        assert intent != null;
+
+        // Comes from WebViewImpl::detectContentOnTouch in Blink, so must be user-initiated, and
+        // isn't a redirect.
+        mContentsClient.shouldIgnoreNavigation(mContainerView.getContext(), contentUrl,
+                isMainFrame, true, false);
+    }
+
+    @Override
     public ViewGroup getContainerView() {
         return mContainerView;
     }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsAnchorViewTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsAnchorViewTest.java
index ea1578e..237eaa565 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsAnchorViewTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsAnchorViewTest.java
@@ -27,7 +27,7 @@
     public void setUp() throws Exception {
         super.setUp();
         mContainerView = new FrameLayout(getActivity());
-        mViewDelegate = new AwViewAndroidDelegate(mContainerView, new RenderCoordinates());
+        mViewDelegate = new AwViewAndroidDelegate(mContainerView, null, new RenderCoordinates());
     }
 
     @Feature({"AndroidWebView"})
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/crash/MinidumpUploaderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/crash/MinidumpUploaderTest.java
index 1ff8dc96..a95fea5a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/crash/MinidumpUploaderTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/crash/MinidumpUploaderTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.android_webview.crash.test;
+package org.chromium.android_webview.test.crash;
 
 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
 
diff --git a/apps/PRESUBMIT.py b/apps/PRESUBMIT.py
deleted file mode 100644
index 627f282..0000000
--- a/apps/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2014 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.
-
-"""Presubmit script for extensions and apps.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/ash/PRESUBMIT.py b/ash/PRESUBMIT.py
deleted file mode 100644
index f39f299b..0000000
--- a/ash/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for ash.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 9e6d3f3f..aec86f7 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -38,6 +38,10 @@
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
+#include "ui/base/ime/chromeos/fake_ime_keyboard.h"
+#include "ui/base/ime/chromeos/ime_keyboard.h"
+#include "ui/base/ime/chromeos/input_method_manager.h"
+#include "ui/base/ime/chromeos/mock_input_method_manager.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/events/event.h"
@@ -1121,6 +1125,85 @@
 
 namespace {
 
+class TestInputMethodManager
+    : public chromeos::input_method::MockInputMethodManager {
+ public:
+  TestInputMethodManager() = default;
+  ~TestInputMethodManager() override = default;
+
+  // MockInputMethodManager:
+  chromeos::input_method::ImeKeyboard* GetImeKeyboard() override {
+    return &keyboard_;
+  }
+
+ private:
+  chromeos::input_method::FakeImeKeyboard keyboard_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestInputMethodManager);
+};
+
+class ToggleCapsLockTest : public AcceleratorControllerTest {
+ public:
+  ToggleCapsLockTest() = default;
+  ~ToggleCapsLockTest() override = default;
+
+  void SetUp() override {
+    AcceleratorControllerTest::SetUp();
+    chromeos::input_method::InputMethodManager::Initialize(
+        new TestInputMethodManager);
+  }
+
+  void TearDown() override {
+    chromeos::input_method::InputMethodManager::Shutdown();
+    AcceleratorControllerTest::TearDown();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ToggleCapsLockTest);
+};
+
+// Tests the four combinations of the TOGGLE_CAPS_LOCK accelerator.
+TEST_F(ToggleCapsLockTest, ToggleCapsLockAccelerators) {
+  chromeos::input_method::InputMethodManager* input_method_manager =
+      chromeos::input_method::InputMethodManager::Get();
+  ASSERT_TRUE(input_method_manager);
+  EXPECT_FALSE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
+
+  // 1. Press Alt, Press Search, Release Search, Release Alt.
+  // Note when you press Alt then press search, the key_code at this point is
+  // VKEY_LWIN (for search) and Alt is the modifier.
+  const ui::Accelerator press_alt_then_search(ui::VKEY_LWIN, ui::EF_ALT_DOWN);
+  EXPECT_FALSE(ProcessInController(press_alt_then_search));
+  // When you release Search before Alt, the key_code is still VKEY_LWIN and
+  // Alt is still the modifier.
+  const ReleaseAccelerator release_search_before_alt(ui::VKEY_LWIN,
+                                                     ui::EF_ALT_DOWN);
+  EXPECT_TRUE(ProcessInController(release_search_before_alt));
+  EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
+  input_method_manager->GetImeKeyboard()->SetCapsLockEnabled(false);
+
+  // 2. Press Search, Press Alt, Release Search, Release Alt.
+  const ui::Accelerator press_search_then_alt(ui::VKEY_MENU,
+                                              ui::EF_COMMAND_DOWN);
+  EXPECT_FALSE(ProcessInController(press_search_then_alt));
+  EXPECT_TRUE(ProcessInController(release_search_before_alt));
+  EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
+  input_method_manager->GetImeKeyboard()->SetCapsLockEnabled(false);
+
+  // 3. Press Alt, Press Search, Release Alt, Release Search.
+  EXPECT_FALSE(ProcessInController(press_alt_then_search));
+  const ReleaseAccelerator release_alt_before_search(ui::VKEY_MENU,
+                                                     ui::EF_COMMAND_DOWN);
+  EXPECT_TRUE(ProcessInController(release_alt_before_search));
+  EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
+  input_method_manager->GetImeKeyboard()->SetCapsLockEnabled(false);
+
+  // 4. Press Search, Press Alt, Release Alt, Release Search.
+  EXPECT_FALSE(ProcessInController(press_search_then_alt));
+  EXPECT_TRUE(ProcessInController(release_alt_before_search));
+  EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
+}
+
 class PreferredReservedAcceleratorsTest : public test::AshTestBase {
  public:
   PreferredReservedAcceleratorsTest() {}
diff --git a/ash/common/accelerators/accelerator_controller.cc b/ash/common/accelerators/accelerator_controller.cc
index 28a4958..17fd8591 100644
--- a/ash/common/accelerators/accelerator_controller.cc
+++ b/ash/common/accelerators/accelerator_controller.cc
@@ -434,18 +434,37 @@
 
 bool CanHandleToggleCapsLock(const ui::Accelerator& accelerator,
                              const ui::Accelerator& previous_accelerator) {
-  if (accelerator.key_code() == ui::VKEY_LWIN) {
-    // If something else was pressed between the Search key (LWIN)
-    // being pressed and released, then ignore the release of the
-    // Search key.
-    // TODO(danakj): Releasing Alt first breaks this: crbug.com/166495
-    if (previous_accelerator.type() == ui::ET_KEY_RELEASED ||
-        previous_accelerator.key_code() != ui::VKEY_LWIN)
-      return false;
-  }
   chromeos::input_method::InputMethodManager* ime =
       chromeos::input_method::InputMethodManager::Get();
-  return ime && ime->GetImeKeyboard();
+
+  // This shortcust is set to be trigger on release. Either the current
+  // accelerator is a Search release or Alt release.
+  if (accelerator.key_code() == ui::VKEY_LWIN &&
+      accelerator.type() == ui::ET_KEY_RELEASED) {
+    // The previous must be either an Alt press or Search press:
+    // 1. Press Alt, Press Search, Release Search, Release Alt.
+    // 2. Press Search, Press Alt, Release Search, Release Alt.
+    if (previous_accelerator.type() == ui::ET_KEY_PRESSED &&
+        (previous_accelerator.key_code() == ui::VKEY_LWIN ||
+         previous_accelerator.key_code() == ui::VKEY_MENU)) {
+      return ime && ime->GetImeKeyboard();
+    }
+  }
+
+  // Alt release.
+  if (accelerator.key_code() == ui::VKEY_MENU &&
+      accelerator.type() == ui::ET_KEY_RELEASED) {
+    // The previous must be either an Alt press or Search press:
+    // 3. Press Alt, Press Search, Release Alt, Release Search.
+    // 4. Press Search, Press Alt, Release Alt, Release Search.
+    if (previous_accelerator.type() == ui::ET_KEY_PRESSED &&
+        (previous_accelerator.key_code() == ui::VKEY_LWIN ||
+         previous_accelerator.key_code() == ui::VKEY_MENU)) {
+      return ime && ime->GetImeKeyboard();
+    }
+  }
+
+  return false;
 }
 
 void HandleToggleCapsLock() {
diff --git a/ash/common/accelerators/accelerator_table.cc b/ash/common/accelerators/accelerator_table.cc
index 602a3249..b82bb51 100644
--- a/ash/common/accelerators/accelerator_table.cc
+++ b/ash/common/accelerators/accelerator_table.cc
@@ -84,7 +84,14 @@
     {false, ui::VKEY_LSHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
     {false, ui::VKEY_SHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
     {false, ui::VKEY_RSHIFT, ui::EF_NONE, DISABLE_CAPS_LOCK},
+    // Accelerators to toggle Caps Lock.
+    // The following is triggered when Search is released while Alt is still
+    // down. The key_code here is LWIN (for search) and Alt is a modifier.
     {false, ui::VKEY_LWIN, ui::EF_ALT_DOWN, TOGGLE_CAPS_LOCK},
+    // The following is triggered when Alt is released while search is still
+    // down. The key_code here is MENU (for Alt) and Search is a modifier
+    // (EF_COMMAND_DOWN is used for Search as a modifier).
+    {false, ui::VKEY_MENU, ui::EF_COMMAND_DOWN, TOGGLE_CAPS_LOCK},
     {true, ui::VKEY_VOLUME_MUTE, ui::EF_NONE, VOLUME_MUTE},
     {true, ui::VKEY_VOLUME_DOWN, ui::EF_NONE, VOLUME_DOWN},
     {true, ui::VKEY_VOLUME_UP, ui::EF_NONE, VOLUME_UP},
diff --git a/ash/common/shelf/overflow_bubble_view.cc b/ash/common/shelf/overflow_bubble_view.cc
index 25b0ef67..a198d09 100644
--- a/ash/common/shelf/overflow_bubble_view.cc
+++ b/ash/common/shelf/overflow_bubble_view.cc
@@ -52,8 +52,7 @@
   set_background(NULL);
   SkColor color = MaterialDesignController::IsShelfMaterial()
                       ? kShelfBaseColor
-                      : SkColorSetA(kShelfBaseColor,
-                                    GetShelfConstant(SHELF_BACKGROUND_ALPHA));
+                      : SkColorSetA(kShelfBaseColor, kShelfTranslucentAlpha);
   set_color(color);
   set_margins(gfx::Insets(kPadding, kPadding, kPadding, kPadding));
   // Overflow bubble should not get focus. If it get focus when it is shown,
diff --git a/ash/common/shelf/shelf_background_animator.cc b/ash/common/shelf/shelf_background_animator.cc
index ce9628f4..9a3d08b 100644
--- a/ash/common/shelf/shelf_background_animator.cc
+++ b/ash/common/shelf/shelf_background_animator.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/shelf/shelf_background_animator_observer.h"
 #include "ash/common/shelf/shelf_constants.h"
 #include "ash/common/shelf/wm_shelf.h"
@@ -15,7 +14,7 @@
 
 namespace {
 // The total number of animators that will call BackgroundAnimationEnded().
-const int kNumAnimators = 3;
+const int kNumAnimators = 2;
 
 const int kMaxAlpha = 255;
 }  // namespace
@@ -50,7 +49,6 @@
 void ShelfBackgroundAnimator::Initialize(
     ShelfBackgroundAnimatorObserver* observer) const {
   observer->UpdateShelfOpaqueBackground(opaque_background_animator_->alpha());
-  observer->UpdateShelfAssetBackground(asset_background_animator_->alpha());
   observer->UpdateShelfItemBackground(item_background_animator_->alpha());
 }
 
@@ -90,9 +88,6 @@
   if (animator == opaque_background_animator_.get()) {
     for (auto& observer : observers_)
       observer.UpdateShelfOpaqueBackground(alpha);
-  } else if (animator == asset_background_animator_.get()) {
-    for (auto& observer : observers_)
-      observer.UpdateShelfAssetBackground(alpha);
   } else if (animator == item_background_animator_.get()) {
     for (auto& observer : observers_)
       observer.UpdateShelfItemBackground(alpha);
@@ -113,8 +108,6 @@
   bool show_background = true;
   if (can_reuse_animators_ && previous_background_type_ == background_type) {
     DCHECK_EQ(opaque_background_animator_->paints_background(),
-              asset_background_animator_->paints_background());
-    DCHECK_EQ(asset_background_animator_->paints_background(),
               item_background_animator_->paints_background());
 
     show_background = !opaque_background_animator_->paints_background();
@@ -132,7 +125,6 @@
 
   opaque_background_animator_->SetPaintsBackground(show_background,
                                                    change_type);
-  asset_background_animator_->SetPaintsBackground(show_background, change_type);
   item_background_animator_->SetPaintsBackground(show_background, change_type);
 
   if (target_background_type_ != background_type) {
@@ -146,59 +138,42 @@
     BackgroundAnimatorChangeType change_type) {
   const int opaque_background_alpha =
       opaque_background_animator_ ? opaque_background_animator_->alpha() : 0;
-  const int asset_background_alpha =
-      asset_background_animator_ ? asset_background_animator_->alpha() : 0;
   const int item_background_alpha =
       item_background_animator_ ? item_background_animator_->alpha() : 0;
 
-  const bool is_material = MaterialDesignController::IsShelfMaterial();
   int duration_ms = 0;
 
   switch (background_type) {
     case SHELF_BACKGROUND_DEFAULT:
-      duration_ms = is_material ? 500 : 1000;
+      duration_ms = 500;
       opaque_background_animator_.reset(
           new BackgroundAnimator(this, opaque_background_alpha, 0));
-      asset_background_animator_.reset(
-          new BackgroundAnimator(this, asset_background_alpha, 0));
-      item_background_animator_.reset(
-          new BackgroundAnimator(this, item_background_alpha,
-                                 GetShelfConstant(SHELF_BACKGROUND_ALPHA)));
+      item_background_animator_.reset(new BackgroundAnimator(
+          this, item_background_alpha, kShelfTranslucentAlpha));
       break;
     case SHELF_BACKGROUND_OVERLAP:
-      duration_ms = is_material ? 500 : 1000;
+      duration_ms = 500;
       opaque_background_animator_.reset(new BackgroundAnimator(
-          this, opaque_background_alpha,
-          is_material ? GetShelfConstant(SHELF_BACKGROUND_ALPHA) : 0));
-      asset_background_animator_.reset(new BackgroundAnimator(
-          this, asset_background_alpha,
-          is_material ? 0 : GetShelfConstant(SHELF_BACKGROUND_ALPHA)));
-      item_background_animator_.reset(new BackgroundAnimator(
-          this, item_background_alpha,
-          is_material ? 0 : GetShelfConstant(SHELF_BACKGROUND_ALPHA)));
+          this, opaque_background_alpha, kShelfTranslucentAlpha));
+      item_background_animator_.reset(
+          new BackgroundAnimator(this, item_background_alpha, 0));
       break;
     case SHELF_BACKGROUND_MAXIMIZED:
-      duration_ms = is_material ? 250 : 1000;
+      duration_ms = 250;
       opaque_background_animator_.reset(
           new BackgroundAnimator(this, opaque_background_alpha, kMaxAlpha));
-      asset_background_animator_.reset(new BackgroundAnimator(
-          this, asset_background_alpha,
-          is_material ? 0 : GetShelfConstant(SHELF_BACKGROUND_ALPHA)));
-      item_background_animator_.reset(new BackgroundAnimator(
-          this, item_background_alpha, is_material ? 0 : kMaxAlpha));
+      item_background_animator_.reset(
+          new BackgroundAnimator(this, item_background_alpha, 0));
       break;
   }
 
   opaque_background_animator_->SetDuration(duration_ms);
-  asset_background_animator_->SetDuration(duration_ms);
   item_background_animator_->SetDuration(duration_ms);
 }
 
 void ShelfBackgroundAnimator::StopAnimators() {
   if (opaque_background_animator_)
     opaque_background_animator_->Stop();
-  if (asset_background_animator_)
-    asset_background_animator_->Stop();
   if (item_background_animator_)
     item_background_animator_->Stop();
 }
diff --git a/ash/common/shelf/shelf_background_animator.h b/ash/common/shelf/shelf_background_animator.h
index 5b2068f..fcc95dd2 100644
--- a/ash/common/shelf/shelf_background_animator.h
+++ b/ash/common/shelf/shelf_background_animator.h
@@ -5,6 +5,7 @@
 #ifndef ASH_COMMON_SHELF_SHELF_BACKGROUND_ANIMATOR_H_
 #define ASH_COMMON_SHELF_SHELF_BACKGROUND_ANIMATOR_H_
 
+#include <memory>
 #include <vector>
 
 #include "ash/ash_export.h"
@@ -25,12 +26,8 @@
 // The ShelfBackgroundAnimator is capable of observing a WmShelf instance for
 // background type changes or clients can call PaintBackground() directly.
 //
-// The Shelf uses 3 surfaces for the animations:
+// The Shelf uses 2 surfaces for the animations:
 //
-//  Non-Material Design:
-//    1. Shelf button backgrounds
-//    2. Opaque overlay for the SHELF_BACKGROUND_MAXIMIZED state.
-//    3. Shelf and Dock assets for the SHELF_BACKGROUND_OVERLAP state.
 //  Material Design:
 //    1. Shelf button backgrounds
 //    2. Opaque overlay for the SHELF_BACKGROUND_OVERLAP and
@@ -108,10 +105,6 @@
   // gfx::SlideAnimation.
   std::unique_ptr<BackgroundAnimator> opaque_background_animator_;
 
-  // Animates the asset/image based background of the Shelf.
-  // TODO(bruthig): Remove when non-md is no longer needed (crbug.com/614453).
-  std::unique_ptr<BackgroundAnimator> asset_background_animator_;
-
   // Animates the backgrounds of Shelf child Views.
   std::unique_ptr<BackgroundAnimator> item_background_animator_;
 
diff --git a/ash/common/shelf/shelf_background_animator_observer.h b/ash/common/shelf/shelf_background_animator_observer.h
index b90e8814..a90b308 100644
--- a/ash/common/shelf/shelf_background_animator_observer.h
+++ b/ash/common/shelf/shelf_background_animator_observer.h
@@ -15,10 +15,6 @@
   // Called when the Shelf's opaque background should be updated.
   virtual void UpdateShelfOpaqueBackground(int alpha) {}
 
-  // Called when the Shelf's asset based background should be updated.
-  // TODO(bruthig): Remove when non-md is no longer needed (crbug.com/614453).
-  virtual void UpdateShelfAssetBackground(int alpha) {}
-
   // Called when the Shelf item (aka button) backgrounds should be updated.
   virtual void UpdateShelfItemBackground(int alpha) {}
 
diff --git a/ash/common/shelf/shelf_background_animator_unittest.cc b/ash/common/shelf/shelf_background_animator_unittest.cc
index 9c40483b2..21b1342 100644
--- a/ash/common/shelf/shelf_background_animator_unittest.cc
+++ b/ash/common/shelf/shelf_background_animator_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "ash/common/shelf/shelf_background_animator_observer.h"
 #include "ash/common/shelf/shelf_constants.h"
-#include "ash/common/test/material_design_controller_test_api.h"
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/test/test_mock_time_task_runner.h"
@@ -16,9 +15,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
-
-using test::MaterialDesignControllerTestAPI;
-
 namespace {
 
 const int kMaxAlpha = 255;
@@ -37,17 +33,13 @@
 
   int item_background_alpha() const { return item_background_alpha_; }
 
-  int asset_background_alpha() const { return asset_background_alpha_; }
-
   // ShelfBackgroundObserver:
   void UpdateShelfOpaqueBackground(int alpha) override;
-  void UpdateShelfAssetBackground(int alpha) override;
   void UpdateShelfItemBackground(int alpha) override;
 
  private:
   int opaque_background_alpha_ = 0;
   int item_background_alpha_ = 0;
-  int asset_background_alpha_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(TestShelfBackgroundObserver);
 };
@@ -56,10 +48,6 @@
   opaque_background_alpha_ = alpha;
 }
 
-void TestShelfBackgroundObserver::UpdateShelfAssetBackground(int alpha) {
-  asset_background_alpha_ = alpha;
-}
-
 void TestShelfBackgroundObserver::UpdateShelfItemBackground(int alpha) {
   item_background_alpha_ = alpha;
 }
@@ -82,10 +70,6 @@
     return animator_->opaque_background_animator_.get();
   }
 
-  BackgroundAnimator* asset_background_animator() const {
-    return animator_->asset_background_animator_.get();
-  }
-
   BackgroundAnimator* item_background_animator() const {
     return animator_->item_background_animator_.get();
   }
@@ -99,17 +83,10 @@
   DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorTestApi);
 };
 
-// Note: this is not a parameterized test (like other MD tests) because the
-// behavior is so different and not all tests need to be run for both MD and
-// non-MD variants.
-class ShelfBackgroundAnimatorTestBase : public testing::Test {
+class ShelfBackgroundAnimatorTest : public testing::Test {
  public:
-  ShelfBackgroundAnimatorTestBase() {}
-  ~ShelfBackgroundAnimatorTestBase() override {}
-
-  virtual MaterialDesignController::Mode GetMaterialDesignMode() = 0;
-
-  int expected_translucent_alpha() const { return expected_translucent_alpha_; }
+  ShelfBackgroundAnimatorTest() {}
+  ~ShelfBackgroundAnimatorTest() override {}
 
   // testing::Test:
   void SetUp() override;
@@ -139,108 +116,37 @@
  private:
   std::unique_ptr<base::ThreadTaskRunnerHandle> task_runner_handle_;
 
-  std::unique_ptr<MaterialDesignControllerTestAPI> material_mode_test_api_;
-
-  // The expected alpha value for translucent items.  Cannot be a constant
-  // because it is different for material design and non-material.
-  int expected_translucent_alpha_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorTestBase);
+  DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorTest);
 };
 
-void ShelfBackgroundAnimatorTestBase::SetUp() {
+void ShelfBackgroundAnimatorTest::SetUp() {
   task_runner_ = new base::TestMockTimeTaskRunner();
   task_runner_handle_.reset(new base::ThreadTaskRunnerHandle(task_runner_));
 
-  material_mode_test_api_.reset(
-      new MaterialDesignControllerTestAPI(GetMaterialDesignMode()));
   animator_.reset(
       new ShelfBackgroundAnimator(SHELF_BACKGROUND_DEFAULT, nullptr));
   animator_->AddObserver(&observer_);
 
   test_api_.reset(new ShelfBackgroundAnimatorTestApi(animator_.get()));
-
-  // Initialized after the Material Design mode because GetShelfConstant()
-  // depends on the mode.
-  expected_translucent_alpha_ = GetShelfConstant(SHELF_BACKGROUND_ALPHA);
 }
 
-void ShelfBackgroundAnimatorTestBase::PaintBackground(
+void ShelfBackgroundAnimatorTest::PaintBackground(
     ShelfBackgroundType background_type) {
   animator_->PaintBackground(background_type, BACKGROUND_CHANGE_IMMEDIATE);
 }
 
-void ShelfBackgroundAnimatorTestBase::SetAlphaValuesOnObserver(int alpha) {
+void ShelfBackgroundAnimatorTest::SetAlphaValuesOnObserver(int alpha) {
   observer_.UpdateShelfOpaqueBackground(alpha);
-  observer_.UpdateShelfAssetBackground(alpha);
   observer_.UpdateShelfItemBackground(alpha);
 }
 
-void ShelfBackgroundAnimatorTestBase::CompleteAnimations() {
+void ShelfBackgroundAnimatorTest::CompleteAnimations() {
   task_runner_->FastForwardUntilNoTasksRemain();
 }
 
-class ShelfBackgroundAnimatorNonMDTest
-    : public ShelfBackgroundAnimatorTestBase {
- public:
-  ShelfBackgroundAnimatorNonMDTest() {}
-  ~ShelfBackgroundAnimatorNonMDTest() override {}
-
-  MaterialDesignController::Mode GetMaterialDesignMode() override {
-    return MaterialDesignController::NON_MATERIAL;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorNonMDTest);
-};
-
-// Verify the alpha values for the SHELF_BACKGROUND_DEFAULT state.
-TEST_F(ShelfBackgroundAnimatorNonMDTest, DefaultBackground) {
-  PaintBackground(SHELF_BACKGROUND_DEFAULT);
-
-  EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type());
-  EXPECT_EQ(0, observer_.opaque_background_alpha());
-  EXPECT_EQ(0, observer_.asset_background_alpha());
-  EXPECT_EQ(expected_translucent_alpha(), observer_.item_background_alpha());
-}
-
-// Verify the alpha values for the SHELF_BACKGROUND_OVERLAP state.
-TEST_F(ShelfBackgroundAnimatorNonMDTest, OverlapBackground) {
-  PaintBackground(SHELF_BACKGROUND_OVERLAP);
-
-  EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, animator_->target_background_type());
-  EXPECT_EQ(0, observer_.opaque_background_alpha());
-  EXPECT_EQ(expected_translucent_alpha(), observer_.asset_background_alpha());
-  EXPECT_EQ(expected_translucent_alpha(), observer_.item_background_alpha());
-}
-
-// Verify the alpha values for the SHELF_BACKGROUND_MAXIMIZED state.
-TEST_F(ShelfBackgroundAnimatorNonMDTest, MaximizedBackground) {
-  PaintBackground(SHELF_BACKGROUND_MAXIMIZED);
-
-  EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, animator_->target_background_type());
-  EXPECT_EQ(kMaxAlpha, observer_.opaque_background_alpha());
-  EXPECT_EQ(expected_translucent_alpha(), observer_.asset_background_alpha());
-  EXPECT_EQ(kMaxAlpha, observer_.item_background_alpha());
-}
-
-class ShelfBackgroundAnimatorMDTest : public ShelfBackgroundAnimatorTestBase {
- public:
-  ShelfBackgroundAnimatorMDTest() {}
-  ~ShelfBackgroundAnimatorMDTest() override {}
-
-  MaterialDesignController::Mode GetMaterialDesignMode() override {
-    return MaterialDesignController::MATERIAL_EXPERIMENTAL;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorMDTest);
-};
-
 // Verify the |previous_background_type_| and |target_background_type_| values
 // when animating to the same target type multiple times.
-TEST_F(ShelfBackgroundAnimatorMDTest,
-       BackgroundTypesWhenAnimatingToSameTarget) {
+TEST_F(ShelfBackgroundAnimatorTest, BackgroundTypesWhenAnimatingToSameTarget) {
   PaintBackground(SHELF_BACKGROUND_MAXIMIZED);
   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, animator_->target_background_type());
 
@@ -255,7 +161,7 @@
 
 // Verify subsequent calls to PaintBackground() using the
 // BACKGROUND_CHANGE_ANIMATE change type are ignored.
-TEST_F(ShelfBackgroundAnimatorMDTest,
+TEST_F(ShelfBackgroundAnimatorTest,
        MultipleAnimateCallsToSameTargetAreIgnored) {
   PaintBackground(SHELF_BACKGROUND_MAXIMIZED);
   SetAlphaValuesOnObserver(kDummyAlpha);
@@ -276,70 +182,63 @@
 }
 
 // Verify observers are updated with the current values when they are added.
-TEST_F(ShelfBackgroundAnimatorMDTest, ObserversUpdatedWhenAdded) {
+TEST_F(ShelfBackgroundAnimatorTest, ObserversUpdatedWhenAdded) {
   animator_->RemoveObserver(&observer_);
   SetAlphaValuesOnObserver(kDummyAlpha);
 
   animator_->AddObserver(&observer_);
 
   EXPECT_NE(observer_.opaque_background_alpha(), kDummyAlpha);
-  EXPECT_NE(observer_.asset_background_alpha(), kDummyAlpha);
   EXPECT_NE(observer_.item_background_alpha(), kDummyAlpha);
 }
 
 // Verify the alpha values for the SHELF_BACKGROUND_DEFAULT state.
-TEST_F(ShelfBackgroundAnimatorMDTest, DefaultBackground) {
+TEST_F(ShelfBackgroundAnimatorTest, DefaultBackground) {
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
 
   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type());
   EXPECT_EQ(0, observer_.opaque_background_alpha());
-  EXPECT_EQ(0, observer_.asset_background_alpha());
-  EXPECT_EQ(expected_translucent_alpha(), observer_.item_background_alpha());
+  EXPECT_EQ(kShelfTranslucentAlpha, observer_.item_background_alpha());
 }
 
 // Verify the alpha values for the SHELF_BACKGROUND_OVERLAP state.
-TEST_F(ShelfBackgroundAnimatorMDTest, OverlapBackground) {
+TEST_F(ShelfBackgroundAnimatorTest, OverlapBackground) {
   PaintBackground(SHELF_BACKGROUND_OVERLAP);
 
   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, animator_->target_background_type());
-  EXPECT_EQ(expected_translucent_alpha(), observer_.opaque_background_alpha());
-  EXPECT_EQ(0, observer_.asset_background_alpha());
+  EXPECT_EQ(kShelfTranslucentAlpha, observer_.opaque_background_alpha());
   EXPECT_EQ(0, observer_.item_background_alpha());
 }
 
 // Verify the alpha values for the SHELF_BACKGROUND_MAXIMIZED state.
-TEST_F(ShelfBackgroundAnimatorMDTest, MaximizedBackground) {
+TEST_F(ShelfBackgroundAnimatorTest, MaximizedBackground) {
   PaintBackground(SHELF_BACKGROUND_MAXIMIZED);
 
   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, animator_->target_background_type());
   EXPECT_EQ(kMaxAlpha, observer_.opaque_background_alpha());
-  EXPECT_EQ(0, observer_.asset_background_alpha());
   EXPECT_EQ(0, observer_.item_background_alpha());
 }
 
 // Verify that existing animators are used when animating to the previous state.
-TEST_F(ShelfBackgroundAnimatorMDTest, ExistingAnimatorsAreReused) {
+TEST_F(ShelfBackgroundAnimatorTest, ExistingAnimatorsAreReused) {
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
   PaintBackground(SHELF_BACKGROUND_MAXIMIZED);
   EXPECT_TRUE(test_api_->can_reuse_animators());
 
   const BackgroundAnimator* opaque_animator =
       test_api_->opaque_background_animator();
-  const BackgroundAnimator* asset_animator =
-      test_api_->asset_background_animator();
   const BackgroundAnimator* item_animator =
       test_api_->item_background_animator();
 
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
 
   EXPECT_EQ(opaque_animator, test_api_->opaque_background_animator());
-  EXPECT_EQ(asset_animator, test_api_->asset_background_animator());
   EXPECT_EQ(item_animator, test_api_->item_background_animator());
 }
 
 // Verify that existing animators are not re-used when the previous animation
 // didn't complete.
-TEST_F(ShelfBackgroundAnimatorMDTest,
+TEST_F(ShelfBackgroundAnimatorTest,
        ExistingAnimatorsNotReusedWhenPreviousAnimationsDontComplete) {
   EXPECT_NE(SHELF_BACKGROUND_OVERLAP, test_api_->previous_background_type());
   animator_->PaintBackground(SHELF_BACKGROUND_OVERLAP,
@@ -350,8 +249,6 @@
 
   const BackgroundAnimator* opaque_animator =
       test_api_->opaque_background_animator();
-  const BackgroundAnimator* asset_animator =
-      test_api_->asset_background_animator();
   const BackgroundAnimator* item_animator =
       test_api_->item_background_animator();
 
@@ -360,13 +257,12 @@
                              BACKGROUND_CHANGE_ANIMATE);
 
   EXPECT_NE(opaque_animator, test_api_->opaque_background_animator());
-  EXPECT_NE(asset_animator, test_api_->asset_background_animator());
   EXPECT_NE(item_animator, test_api_->item_background_animator());
 }
 
 // Verify that existing animators are not re-used when the target background
 // isn't the same as the previous background.
-TEST_F(ShelfBackgroundAnimatorMDTest,
+TEST_F(ShelfBackgroundAnimatorTest,
        ExistingAnimatorsNotReusedWhenTargetBackgroundNotPreviousBackground) {
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
   PaintBackground(SHELF_BACKGROUND_MAXIMIZED);
@@ -374,8 +270,6 @@
 
   const BackgroundAnimator* opaque_animator =
       test_api_->opaque_background_animator();
-  const BackgroundAnimator* asset_animator =
-      test_api_->asset_background_animator();
   const BackgroundAnimator* item_animator =
       test_api_->item_background_animator();
 
@@ -383,12 +277,11 @@
   PaintBackground(SHELF_BACKGROUND_OVERLAP);
 
   EXPECT_NE(opaque_animator, test_api_->opaque_background_animator());
-  EXPECT_NE(asset_animator, test_api_->asset_background_animator());
   EXPECT_NE(item_animator, test_api_->item_background_animator());
 }
 
 // Verify animators are not re-used after snapping to the same background type.
-TEST_F(ShelfBackgroundAnimatorMDTest,
+TEST_F(ShelfBackgroundAnimatorTest,
        ExistingAnimatorsNotUsedWhenSnappingToSameTargetBackground) {
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
@@ -397,14 +290,13 @@
 }
 
 // Verify observers are always notified, even when alpha values don't change.
-TEST_F(ShelfBackgroundAnimatorMDTest,
+TEST_F(ShelfBackgroundAnimatorTest,
        ObserversAreNotifiedWhenSnappingToSameTargetBackground) {
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
   SetAlphaValuesOnObserver(kDummyAlpha);
   PaintBackground(SHELF_BACKGROUND_DEFAULT);
 
   EXPECT_NE(observer_.opaque_background_alpha(), kDummyAlpha);
-  EXPECT_NE(observer_.asset_background_alpha(), kDummyAlpha);
   EXPECT_NE(observer_.item_background_alpha(), kDummyAlpha);
 }
 
diff --git a/ash/common/shelf/shelf_constants.cc b/ash/common/shelf/shelf_constants.cc
index b9a573d..c3377bb 100644
--- a/ash/common/shelf/shelf_constants.cc
+++ b/ash/common/shelf/shelf_constants.cc
@@ -21,12 +21,12 @@
 const SkColor kShelfInkDropBaseColor = SK_ColorWHITE;
 const float kShelfInkDropVisibleOpacity = 0.2f;
 const SkColor kShelfIconColor = SK_ColorWHITE;
+const int kShelfTranslucentAlpha = 153;
 const int kOverflowButtonSize = 32;
 const int kOverflowButtonCornerRadius = 2;
 const int kAppListButtonRadius = kOverflowButtonSize / 2;
 
 int GetShelfConstant(ShelfConstant shelf_constant) {
-  const int kShelfBackgroundAlpha[] = {204, 153, 153};
   const int kShelfSize[] = {47, 48, 48};
   const int kShelfButtonSpacing[] = {10, 16, 16};
   const int kShelfButtonSize[] = {44, 48, 48};
@@ -37,8 +37,6 @@
          mode <= MaterialDesignController::MATERIAL_EXPERIMENTAL);
 
   switch (shelf_constant) {
-    case SHELF_BACKGROUND_ALPHA:
-      return kShelfBackgroundAlpha[mode];
     case SHELF_SIZE:
       return kShelfSize[mode];
     case SHELF_BUTTON_SPACING:
diff --git a/ash/common/shelf/shelf_constants.h b/ash/common/shelf/shelf_constants.h
index dc584eb..f875900 100644
--- a/ash/common/shelf/shelf_constants.h
+++ b/ash/common/shelf/shelf_constants.h
@@ -11,9 +11,6 @@
 namespace ash {
 
 enum ShelfConstant {
-  // The alpha value for the shelf background when a window is overlapping.
-  SHELF_BACKGROUND_ALPHA,
-
   // Size of the shelf when visible (height when the shelf is horizontal and
   // width when the shelf is vertical).
   SHELF_SIZE,
@@ -65,6 +62,9 @@
 // notifications, etc).
 ASH_EXPORT extern const SkColor kShelfIconColor;
 
+// The alpha value for the shelf background when a window is overlapping.
+ASH_EXPORT extern const int kShelfTranslucentAlpha;
+
 // The width and height of the material design overflow button.
 // TODO(tdanderson): Refactor constants which are common between the shelf
 // and the tray. See crbug.com/623987.
diff --git a/ash/common/shelf/shelf_widget.cc b/ash/common/shelf/shelf_widget.cc
index 192cb8ac..d82d543 100644
--- a/ash/common/shelf/shelf_widget.cc
+++ b/ash/common/shelf/shelf_widget.cc
@@ -5,7 +5,6 @@
 #include "ash/common/shelf/shelf_widget.h"
 
 #include "ash/common/focus_cycler.h"
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/shelf/app_list_button.h"
 #include "ash/common/shelf/shelf_background_animator_observer.h"
@@ -23,13 +22,8 @@
 #include "ash/common/wm_window_property.h"
 #include "ash/root_window_controller.h"
 #include "base/memory/ptr_util.h"
-#include "grit/ash_resources.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/skbitmap_operations.h"
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/layout/fill_layout.h"
@@ -38,20 +32,13 @@
 
 namespace ash {
 
-namespace {
-
-// Size of black border at bottom (or side) of shelf.
-const int kNumBlackPixels = 3;
-
-}  // namespace
-
 // The contents view of the Shelf. This view contains ShelfView and
 // sizes it to the width of the shelf minus the size of the status area.
 class ShelfWidget::DelegateView : public views::WidgetDelegate,
                                   public views::AccessiblePaneView,
                                   public ShelfBackgroundAnimatorObserver {
  public:
-  DelegateView(WmShelf* wm_shelf, ShelfWidget* shelf);
+  explicit DelegateView(ShelfWidget* shelf);
   ~DelegateView() override;
 
   void set_focus_cycler(FocusCycler* focus_cycler) {
@@ -64,9 +51,6 @@
 
   void SetParentLayer(ui::Layer* layer);
 
-  // views::View overrides:
-  void OnPaintBackground(gfx::Canvas* canvas) override;
-
   // views::WidgetDelegateView overrides:
   views::Widget* GetWidget() override { return View::GetWidget(); }
   const views::Widget* GetWidget() const override { return View::GetWidget(); }
@@ -78,13 +62,10 @@
 
   // ShelfBackgroundAnimatorObserver:
   void UpdateShelfOpaqueBackground(int alpha) override;
-  void UpdateShelfAssetBackground(int alpha) override;
 
  private:
-  WmShelf* wm_shelf_;
   ShelfWidget* shelf_widget_;
   FocusCycler* focus_cycler_;
-  int asset_background_alpha_;
   // TODO(bruthig): Remove opaque_background_ (see https://crbug.com/621551).
   // A black background layer which is shown when a maximized window is visible.
   ui::Layer opaque_background_;
@@ -96,15 +77,11 @@
   DISALLOW_COPY_AND_ASSIGN(DelegateView);
 };
 
-ShelfWidget::DelegateView::DelegateView(WmShelf* wm_shelf,
-                                        ShelfWidget* shelf_widget)
-    : wm_shelf_(wm_shelf),
-      shelf_widget_(shelf_widget),
+ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf_widget)
+    : shelf_widget_(shelf_widget),
       focus_cycler_(nullptr),
-      asset_background_alpha_(0),
       opaque_background_(ui::LAYER_SOLID_COLOR),
       opaque_foreground_(ui::LAYER_SOLID_COLOR) {
-  DCHECK(wm_shelf_);
   DCHECK(shelf_widget_);
   SetLayoutManager(new views::FillLayout());
   set_allow_deactivate_on_esc(true);
@@ -124,63 +101,6 @@
   ReorderLayers();
 }
 
-void ShelfWidget::DelegateView::OnPaintBackground(gfx::Canvas* canvas) {
-  if (MaterialDesignController::IsShelfMaterial())
-    return;
-
-  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
-  gfx::ImageSkia shelf_background =
-      *rb->GetImageSkiaNamed(IDR_ASH_SHELF_BACKGROUND);
-  const bool horizontal = wm_shelf_->IsHorizontalAlignment();
-  if (!horizontal) {
-    shelf_background = gfx::ImageSkiaOperations::CreateRotatedImage(
-        shelf_background, wm_shelf_->GetAlignment() == SHELF_ALIGNMENT_LEFT
-                              ? SkBitmapOperations::ROTATION_90_CW
-                              : SkBitmapOperations::ROTATION_270_CW);
-  }
-  const gfx::Rect dock_bounds(
-      shelf_widget_->shelf_layout_manager()->dock_bounds());
-  cc::PaintFlags flags;
-  flags.setAlpha(asset_background_alpha_);
-  canvas->DrawImageInt(
-      shelf_background, 0, 0, shelf_background.width(),
-      shelf_background.height(),
-      (horizontal && dock_bounds.x() == 0 && dock_bounds.width() > 0)
-          ? dock_bounds.width()
-          : 0,
-      0, horizontal ? width() - dock_bounds.width() : width(), height(), false,
-      flags);
-  if (horizontal && dock_bounds.width() > 0) {
-    // The part of the shelf background that is in the corner below the docked
-    // windows close to the work area is an arched gradient that blends
-    // vertically oriented docked background and horizontal shelf.
-    gfx::ImageSkia shelf_corner = *rb->GetImageSkiaNamed(IDR_ASH_SHELF_CORNER);
-    if (dock_bounds.x() == 0) {
-      shelf_corner = gfx::ImageSkiaOperations::CreateRotatedImage(
-          shelf_corner, SkBitmapOperations::ROTATION_90_CW);
-    }
-    canvas->DrawImageInt(
-        shelf_corner, 0, 0, shelf_corner.width(), shelf_corner.height(),
-        dock_bounds.x() > 0 ? dock_bounds.x() : dock_bounds.width() - height(),
-        0, height(), height(), false, flags);
-    // The part of the shelf background that is just below the docked windows
-    // is drawn using the last (lowest) 1-pixel tall strip of the image asset.
-    // This avoids showing the border 3D shadow between the shelf and the
-    // dock.
-    canvas->DrawImageInt(shelf_background, 0, shelf_background.height() - 1,
-                         shelf_background.width(), 1,
-                         dock_bounds.x() > 0 ? dock_bounds.x() + height() : 0,
-                         0, dock_bounds.width() - height(), height(), false,
-                         flags);
-  }
-  gfx::Rect black_rect =
-      shelf_widget_->shelf_layout_manager()->SelectValueForShelfAlignment(
-          gfx::Rect(0, height() - kNumBlackPixels, width(), kNumBlackPixels),
-          gfx::Rect(0, 0, kNumBlackPixels, height()),
-          gfx::Rect(width() - kNumBlackPixels, 0, kNumBlackPixels, height()));
-  canvas->FillRect(black_rect, SK_ColorBLACK);
-}
-
 bool ShelfWidget::DelegateView::CanActivate() const {
   // Allow to activate as fallback.
   if (shelf_widget_->activating_as_fallback_)
@@ -208,15 +128,10 @@
   opaque_background_.SetOpacity(alpha / kMaxAlpha);
 }
 
-void ShelfWidget::DelegateView::UpdateShelfAssetBackground(int alpha) {
-  asset_background_alpha_ = alpha;
-  SchedulePaint();
-}
-
 ShelfWidget::ShelfWidget(WmWindow* shelf_container, WmShelf* wm_shelf)
     : wm_shelf_(wm_shelf),
       status_area_widget_(nullptr),
-      delegate_view_(new DelegateView(wm_shelf, this)),
+      delegate_view_(new DelegateView(this)),
       shelf_view_(nullptr),
       background_animator_(SHELF_BACKGROUND_DEFAULT, wm_shelf_),
       activating_as_fallback_(false) {
diff --git a/ash/common/system/tray/tray_details_view_unittest.cc b/ash/common/system/tray/tray_details_view_unittest.cc
index a3eceb2..a62f8b6 100644
--- a/ash/common/system/tray/tray_details_view_unittest.cc
+++ b/ash/common/system/tray/tray_details_view_unittest.cc
@@ -5,7 +5,6 @@
 #include "ash/common/system/tray/tray_details_view.h"
 
 #include "ash/common/ash_view_ids.h"
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/system/tray/hover_highlight_view.h"
 #include "ash/common/system/tray/special_popup_row.h"
 #include "ash/common/system/tray/system_tray.h"
@@ -46,22 +45,6 @@
 
   void FocusTitleRow() { title_row()->content()->RequestFocus(); }
 
-  // TrayDetailsView:
-  void CreateExtraTitleRowButtons() override {
-    // TODO(tdanderson): Add test coverage for material design buttons in the
-    // title row once they are implemented.
-    if (MaterialDesignController::IsSystemTrayMenuMaterial())
-      return;
-
-    tray_popup_header_button_ =
-        new TrayPopupHeaderButton(this, IDR_AURA_UBER_TRAY_BLUETOOTH_ENABLED,
-                                  IDR_AURA_UBER_TRAY_BLUETOOTH_DISABLED,
-                                  IDR_AURA_UBER_TRAY_BLUETOOTH_ENABLED_HOVER,
-                                  IDR_AURA_UBER_TRAY_BLUETOOTH_DISABLED_HOVER,
-                                  IDS_ASH_STATUS_TRAY_BLUETOOTH);
-    title_row()->AddViewToRowNonMd(tray_popup_header_button_, true);
-  }
-
   void CreateScrollerViews() { CreateScrollableList(); }
 
  private:
@@ -184,10 +167,7 @@
   // Transition back to default view, the default view of item 2 should have
   // focus.
   tray->GetSystemBubble()->bubble_view()->set_can_activate(true);
-  if (MaterialDesignController::IsSystemTrayMenuMaterial())
-    FocusBackButton(test_item_2->detailed_view());
-  else
-    test_item_2->detailed_view()->FocusTitleRow();
+  FocusBackButton(test_item_2->detailed_view());
   TransitionFromDetailedToDefaultView(test_item_2->detailed_view());
   RunAllPendingInMessageLoop();
 
@@ -211,111 +191,6 @@
   EXPECT_FALSE(test_item_2->default_view()->HasFocus());
 }
 
-// Tests that HoverHighlightView enters hover state in response to touch.
-TEST_F(TrayDetailsViewTest, HoverHighlightViewTouchFeedback) {
-  // Material design detailed views will not use the visual feedback from
-  // HoverHighlightView.
-  if (MaterialDesignController::IsSystemTrayMenuMaterial())
-    return;
-
-  HoverHighlightView* view = CreateAndShowHoverHighlightView();
-  EXPECT_FALSE(view->hover());
-
-  ui::test::EventGenerator& generator = GetEventGenerator();
-  generator.set_current_location(view->GetBoundsInScreen().CenterPoint());
-  generator.PressTouch();
-  EXPECT_TRUE(view->hover());
-
-  generator.ReleaseTouch();
-}
-
-// Tests that touch events leaving HoverHighlightView cancel the hover state.
-TEST_F(TrayDetailsViewTest, HoverHighlightViewTouchFeedbackCancellation) {
-  // Material design detailed views will not use the visual feedback from
-  // HoverHighlightView.
-  if (MaterialDesignController::IsSystemTrayMenuMaterial())
-    return;
-
-  HoverHighlightView* view = CreateAndShowHoverHighlightView();
-  EXPECT_FALSE(view->hover());
-
-  gfx::Rect view_bounds = view->GetBoundsInScreen();
-  ui::test::EventGenerator& generator = GetEventGenerator();
-  generator.set_current_location(view_bounds.CenterPoint());
-  generator.PressTouch();
-  EXPECT_TRUE(view->hover());
-
-  gfx::Point move_point(view_bounds.x(), view_bounds.CenterPoint().y());
-  generator.MoveTouch(move_point);
-  EXPECT_FALSE(view->hover());
-
-  generator.set_current_location(move_point);
-  generator.ReleaseTouch();
-  EXPECT_FALSE(view->hover());
-}
-
-// Tests that TrayPopupHeaderButton renders a background in response to touch.
-TEST_F(TrayDetailsViewTest, TrayPopupHeaderButtonTouchFeedback) {
-  // Material design detailed views will not use TrayPopupHeaderButton.
-  if (MaterialDesignController::IsSystemTrayMenuMaterial())
-    return;
-
-  TrayPopupHeaderButton* button = CreateAndShowTrayPopupHeaderButton();
-  EXPECT_FALSE(button->background());
-
-  ui::test::EventGenerator& generator = GetEventGenerator();
-  generator.set_current_location(button->GetBoundsInScreen().CenterPoint());
-  generator.PressTouch();
-  EXPECT_TRUE(button->background());
-
-  generator.ReleaseTouch();
-  EXPECT_FALSE(button->background());
-}
-
-// Tests that touch events leaving TrayPopupHeaderButton cancel the touch
-// feedback background.
-TEST_F(TrayDetailsViewTest, TrayPopupHeaderButtonTouchFeedbackCancellation) {
-  // Material design detailed views will not use TrayPopupHeaderButton.
-  if (MaterialDesignController::IsSystemTrayMenuMaterial())
-    return;
-
-  TrayPopupHeaderButton* button = CreateAndShowTrayPopupHeaderButton();
-  EXPECT_FALSE(button->background());
-
-  gfx::Rect view_bounds = button->GetBoundsInScreen();
-  ui::test::EventGenerator& generator = GetEventGenerator();
-  generator.set_current_location(view_bounds.CenterPoint());
-  generator.PressTouch();
-  EXPECT_TRUE(button->background());
-
-  gfx::Point move_point(view_bounds.x(), view_bounds.CenterPoint().y());
-  generator.MoveTouch(move_point);
-  EXPECT_FALSE(button->background());
-
-  generator.set_current_location(move_point);
-  generator.ReleaseTouch();
-  EXPECT_FALSE(button->background());
-}
-
-// Tests that a mouse entering TrayPopupHeaderButton renders a background as
-// visual feedback.
-TEST_F(TrayDetailsViewTest, TrayPopupHeaderButtonMouseHoverFeedback) {
-  // Material design detailed views will not use TrayPopupHeaderButton.
-  if (MaterialDesignController::IsSystemTrayMenuMaterial())
-    return;
-
-  TrayPopupHeaderButton* button = CreateAndShowTrayPopupHeaderButton();
-  EXPECT_FALSE(button->background());
-
-  ui::test::EventGenerator& generator = GetEventGenerator();
-  gfx::Rect bounds = button->GetBoundsInScreen();
-  gfx::Point initial_point(bounds.x() - 1, bounds.y());
-  generator.set_current_location(initial_point);
-  generator.MoveMouseBy(1, 0);
-  RunAllPendingInMessageLoop();
-  EXPECT_TRUE(button->background());
-}
-
 TEST_F(TrayDetailsViewTest, ScrollContentsTest) {
   SystemTray* tray = GetPrimarySystemTray();
   TestItem* test_item = new TestItem;
diff --git a/ash/common/wm/dock/docked_window_layout_manager.cc b/ash/common/wm/dock/docked_window_layout_manager.cc
index a71dbe8..8a315084 100644
--- a/ash/common/wm/dock/docked_window_layout_manager.cc
+++ b/ash/common/wm/dock/docked_window_layout_manager.cc
@@ -4,7 +4,6 @@
 
 #include "ash/common/wm/dock/docked_window_layout_manager.h"
 
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/shelf/shelf_background_animator.h"
 #include "ash/common/shelf/shelf_background_animator_observer.h"
 #include "ash/common/shelf/shelf_constants.h"
@@ -25,12 +24,9 @@
 #include "grit/ash_resources.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/compositor/paint_recorder.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/image_skia_operations.h"
 #include "ui/views/background.h"
 
 namespace ash {
@@ -57,7 +53,6 @@
       : manager_(manager),
         alignment_(DOCKED_ALIGNMENT_NONE),
         background_animator_(SHELF_BACKGROUND_DEFAULT, nullptr),
-        asset_background_alpha_(0),
         opaque_background_(ui::LAYER_SOLID_COLOR),
         visible_background_type_(manager_->shelf()->GetBackgroundType()),
         visible_background_change_type_(BACKGROUND_CHANGE_IMMEDIATE) {
@@ -86,46 +81,12 @@
     UpdateBackground();
   }
 
-  void OnNativeWidgetPaint(const ui::PaintContext& context) override {
-    gfx::Rect local_window_bounds(GetWindowBoundsInScreen().size());
-    ui::PaintRecorder recorder(context, local_window_bounds.size());
-
-    if (!MaterialDesignController::IsShelfMaterial()) {
-      const gfx::ImageSkia& shelf_background(alignment_ == DOCKED_ALIGNMENT_LEFT
-                                                 ? shelf_background_left_
-                                                 : shelf_background_right_);
-      cc::PaintFlags flags;
-      flags.setAlpha(asset_background_alpha_);
-      recorder.canvas()->DrawImageInt(
-          shelf_background, 0, 0, shelf_background.width(),
-          shelf_background.height(),
-          alignment_ == DOCKED_ALIGNMENT_LEFT
-              ? local_window_bounds.width() - shelf_background.width()
-              : 0,
-          0, shelf_background.width(), local_window_bounds.height(), false,
-          flags);
-      recorder.canvas()->DrawImageInt(
-          shelf_background,
-          alignment_ == DOCKED_ALIGNMENT_LEFT ? 0
-                                              : shelf_background.width() - 1,
-          0, 1, shelf_background.height(),
-          alignment_ == DOCKED_ALIGNMENT_LEFT ? 0 : shelf_background.width(), 0,
-          local_window_bounds.width() - shelf_background.width(),
-          local_window_bounds.height(), false, flags);
-    }
-  }
-
   // ShelfBackgroundAnimatorObserver:
   void UpdateShelfOpaqueBackground(int alpha) override {
     const float kMaxAlpha = 255.0f;
     opaque_background_.SetOpacity(alpha / kMaxAlpha);
   }
 
-  void UpdateShelfAssetBackground(int alpha) override {
-    asset_background_alpha_ = alpha;
-    SchedulePaintInRect(gfx::Rect(GetWindowBoundsInScreen().size()));
-  }
-
   // WmShelfObserver:
   void OnBackgroundTypeChanged(
       ShelfBackgroundType background_type,
@@ -158,16 +119,6 @@
     opaque_background_.SetOpacity(0.0f);
     wm_window->GetLayer()->Add(&opaque_background_);
 
-    if (!MaterialDesignController::IsShelfMaterial()) {
-      ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-      gfx::ImageSkia shelf_background =
-          *rb.GetImageSkiaNamed(IDR_ASH_SHELF_BACKGROUND);
-      shelf_background_left_ = gfx::ImageSkiaOperations::CreateRotatedImage(
-          shelf_background, SkBitmapOperations::ROTATION_90_CW);
-      shelf_background_right_ = gfx::ImageSkiaOperations::CreateRotatedImage(
-          shelf_background, SkBitmapOperations::ROTATION_270_CW);
-    }
-
     // This background should be explicitly stacked below any windows already in
     // the dock, otherwise the z-order is set by the order in which windows were
     // added to the container, and UpdateStacking only manages user windows, not
@@ -194,19 +145,10 @@
   // The animator for the background transitions.
   ShelfBackgroundAnimator background_animator_;
 
-  // The alpha to use for drawing image assets covering the docked background.
-  int asset_background_alpha_;
-
   // TODO(bruthig): Remove opaque_background_ (see https://crbug.com/621551).
   // Solid black background that can be made fully opaque.
   ui::Layer opaque_background_;
 
-  // Backgrounds created from shelf background by 90 or 270 degree rotation.
-  // TODO(tdanderson): These members can be removed once the material design
-  // shelf is enabled by default. See crbug.com/614453.
-  gfx::ImageSkia shelf_background_left_;
-  gfx::ImageSkia shelf_background_right_;
-
   // The background type to use when the widget is visible. When not visible,
   // the widget uses SHELF_BACKGROUND_DEFAULT.
   ShelfBackgroundType visible_background_type_;
diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd
index 4572f5b..85f3a8e 100644
--- a/ash/resources/ash_resources.grd
+++ b/ash/resources/ash_resources.grd
@@ -12,8 +12,6 @@
       <!-- KEEP THESE IN ALPHABETICAL ORDER!  DO NOT ADD TO RANDOM PLACES JUST
            BECAUSE YOUR RESOURCES ARE FUNCTIONALLY RELATED OR FALL UNDER THE
            SAME CONDITIONALS. -->
-      <structure type="chrome_scaled_image" name="IDR_ASH_SHELF_BACKGROUND" file="common/shelf/shelf_background.png" />
-      <structure type="chrome_scaled_image" name="IDR_ASH_SHELF_CORNER" file="common/shelf/shelf_corner.png" />
       <structure type="chrome_scaled_image" name="IDR_ASH_SHELF_ICON_APPLIST" file="common/shelf/status_launcher_menu_icon.png" />
       <structure type="chrome_scaled_image" name="IDR_ASH_SHELF_LIST_BROWSER" file="common/shelf/window_switcher_icon_normal.png" />
       <structure type="chrome_scaled_image" name="IDR_ASH_SHELF_LIST_INCOGNITO_BROWSER" file="common/shelf/window_switcher_icon_incognito.png" />
diff --git a/ash/resources/default_100_percent/common/shelf/shelf_background.png b/ash/resources/default_100_percent/common/shelf/shelf_background.png
deleted file mode 100644
index 212c0de3..0000000
--- a/ash/resources/default_100_percent/common/shelf/shelf_background.png
+++ /dev/null
Binary files differ
diff --git a/ash/resources/default_100_percent/common/shelf/shelf_corner.png b/ash/resources/default_100_percent/common/shelf/shelf_corner.png
deleted file mode 100644
index fe8e2fc..0000000
--- a/ash/resources/default_100_percent/common/shelf/shelf_corner.png
+++ /dev/null
Binary files differ
diff --git a/ash/resources/default_200_percent/common/shelf/shelf_background.png b/ash/resources/default_200_percent/common/shelf/shelf_background.png
deleted file mode 100644
index 3a3e6a17..0000000
--- a/ash/resources/default_200_percent/common/shelf/shelf_background.png
+++ /dev/null
Binary files differ
diff --git a/ash/resources/default_200_percent/common/shelf/shelf_corner.png b/ash/resources/default_200_percent/common/shelf/shelf_corner.png
deleted file mode 100644
index f354c53..0000000
--- a/ash/resources/default_200_percent/common/shelf/shelf_corner.png
+++ /dev/null
Binary files differ
diff --git a/base/PRESUBMIT.py b/base/PRESUBMIT.py
index 7768604..7fc8107 100644
--- a/base/PRESUBMIT.py
+++ b/base/PRESUBMIT.py
@@ -35,8 +35,6 @@
   """Checks common to both upload and commit."""
   results = []
   results.extend(_CheckNoInterfacesInBase(input_api, output_api))
-  results.extend(
-      input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
   return results
 
 def CheckChangeOnUpload(input_api, output_api):
diff --git a/base/debug/activity_analyzer_unittest.cc b/base/debug/activity_analyzer_unittest.cc
index 7f1bce9..ee614ea 100644
--- a/base/debug/activity_analyzer_unittest.cc
+++ b/base/debug/activity_analyzer_unittest.cc
@@ -289,7 +289,7 @@
   GlobalActivityAnalyzer global_analyzer(MakeUnique<PersistentMemoryAllocator>(
       const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "", true));
 
-  ActivityUserData& global_data = GlobalActivityTracker::Get()->user_data();
+  ActivityUserData& global_data = GlobalActivityTracker::Get()->global_data();
   global_data.Set("raw", "foo", 3);
   global_data.SetString("string", "bar");
   global_data.SetChar("char", '9');
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc
index 9835b23..ec2e13b 100644
--- a/base/debug/activity_tracker.cc
+++ b/base/debug/activity_tracker.cc
@@ -41,8 +41,8 @@
 
 // The amount of memory set aside for holding arbitrary user data (key/value
 // pairs) globally or associated with ActivityData entries.
-const size_t kUserDataSize = 1024;    // bytes
-const size_t kGlobalDataSize = 4096;  // bytes
+const size_t kUserDataSize = 1 << 10;     // 1 KiB
+const size_t kGlobalDataSize = 16 << 10;  // 16 KiB
 const size_t kMaxUserDataNameLength =
     static_cast<size_t>(std::numeric_limits<uint8_t>::max());
 
@@ -288,7 +288,6 @@
                            ValueType type,
                            const void* memory,
                            size_t size) {
-  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length());
   size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1),
                   size);
@@ -1056,6 +1055,19 @@
   return *user_data_;
 }
 
+GlobalActivityTracker::GlobalUserData::GlobalUserData(void* memory, size_t size)
+    : ActivityUserData(memory, size) {}
+
+GlobalActivityTracker::GlobalUserData::~GlobalUserData() {}
+
+void GlobalActivityTracker::GlobalUserData::Set(StringPiece name,
+                                                ValueType type,
+                                                const void* memory,
+                                                size_t size) {
+  AutoLock lock(data_lock_);
+  ActivityUserData::Set(name, type, memory, size);
+}
+
 GlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker(
     PersistentMemoryAllocator::Reference mem_reference,
     void* base,
@@ -1216,6 +1228,12 @@
   modules_.insert(std::make_pair(info.file, record));
 }
 
+void GlobalActivityTracker::RecordFieldTrial(const std::string& trial_name,
+                                             StringPiece group_name) {
+  const std::string key = std::string("FieldTrial.") + trial_name;
+  global_data_.SetString(key, group_name);
+}
+
 GlobalActivityTracker::GlobalActivityTracker(
     std::unique_ptr<PersistentMemoryAllocator> allocator,
     int stack_depth)
@@ -1235,7 +1253,7 @@
                            kUserDataSize,
                            kCachedUserDataMemories,
                            /*make_iterable=*/false),
-      user_data_(
+      global_data_(
           allocator_->GetAsArray<char>(
               allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord),
               kTypeIdGlobalDataRecord,
@@ -1251,7 +1269,13 @@
 
   // The global records must be iterable in order to be found by an analyzer.
   allocator_->MakeIterable(allocator_->GetAsReference(
-      user_data_.GetBaseAddress(), kTypeIdGlobalDataRecord));
+      global_data_.GetBaseAddress(), kTypeIdGlobalDataRecord));
+
+  // Fetch and record all activated field trials.
+  FieldTrial::ActiveGroups active_groups;
+  FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
+  for (auto& group : active_groups)
+    RecordFieldTrial(group.trial_name, group.group_name);
 }
 
 GlobalActivityTracker::~GlobalActivityTracker() {
diff --git a/base/debug/activity_tracker.h b/base/debug/activity_tracker.h
index 34859195..53290e1 100644
--- a/base/debug/activity_tracker.h
+++ b/base/debug/activity_tracker.h
@@ -27,6 +27,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/location.h"
 #include "base/metrics/persistent_memory_allocator.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_checker.h"
@@ -342,7 +343,7 @@
   using Snapshot = std::map<std::string, TypedValue>;
 
   ActivityUserData(void* memory, size_t size);
-  ~ActivityUserData();
+  virtual ~ActivityUserData();
 
   // Gets the unique ID number for this user data. If this changes then the
   // contents have been overwritten by another thread. The return value is
@@ -404,6 +405,12 @@
   // Gets the base memory address used for storing data.
   const void* GetBaseAddress();
 
+ protected:
+  virtual void Set(StringPiece name,
+                   ValueType type,
+                   const void* memory,
+                   size_t size);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest);
 
@@ -437,7 +444,6 @@
     size_t extent;                    // The total storage of the value,
   };                                  // typically rounded up for alignment.
 
-  void Set(StringPiece name, ValueType type, const void* memory, size_t size);
   void SetReference(StringPiece name,
                     ValueType type,
                     const void* memory,
@@ -461,8 +467,6 @@
   // A pointer to the unique ID for this instance.
   std::atomic<uint32_t>* const id_;
 
-  base::ThreadChecker thread_checker_;
-
   // This ID is used to create unique indentifiers for user data so that it's
   // possible to tell if the information has been overwritten.
   static StaticAtomicSequenceNumber next_id_;
@@ -784,8 +788,13 @@
   // even with the same information.
   void RecordModuleInfo(const ModuleInfo& info);
 
+  // Record field trial information. This call is thread-safe. In addition to
+  // this, construction of a GlobalActivityTracker will cause all existing
+  // active field trials to be fetched and recorded.
+  void RecordFieldTrial(const std::string& trial_name, StringPiece group_name);
+
   // Accesses the global data record for storing arbitrary key/value pairs.
-  ActivityUserData& user_data() { return user_data_; }
+  ActivityUserData& global_data() { return global_data_; }
 
  private:
   friend class GlobalActivityAnalyzer;
@@ -800,6 +809,25 @@
     kCachedUserDataMemories = 10,
   };
 
+  // A wrapper around ActivityUserData that is thread-safe and thus can be used
+  // in the global scope without the requirement of being called from only one
+  // thread.
+  class GlobalUserData : public ActivityUserData {
+   public:
+    GlobalUserData(void* memory, size_t size);
+    ~GlobalUserData() override;
+
+   private:
+    void Set(StringPiece name,
+             ValueType type,
+             const void* memory,
+             size_t size) override;
+
+    Lock data_lock_;
+
+    DISALLOW_COPY_AND_ASSIGN(GlobalUserData);
+  };
+
   // State of a module as stored in persistent memory. This supports a single
   // loading of a module only. If modules are loaded multiple times at
   // different addresses, only the last will be recorded and an unload will
@@ -904,7 +932,7 @@
 
   // An object for holding global arbitrary key value pairs. Values must always
   // be written from the main UI thread.
-  ActivityUserData user_data_;
+  GlobalUserData global_data_;
 
   // A map of global module information, keyed by module path.
   std::map<const std::string, ModuleInfoRecord*> modules_;
diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc
index 1df2d0a..32b6b05 100644
--- a/base/debug/crash_logging.cc
+++ b/base/debug/crash_logging.cc
@@ -45,7 +45,7 @@
 }
 
 // The longest max_length allowed by the system.
-const size_t kLargestValueAllowed = 1024;
+const size_t kLargestValueAllowed = 2048;
 
 }  // namespace
 
diff --git a/base/files/file_util_win.cc b/base/files/file_util_win.cc
index 4e67b5a..9cb446b 100644
--- a/base/files/file_util_win.cc
+++ b/base/files/file_util_win.cc
@@ -134,6 +134,8 @@
   // already exist.
   if (::MoveFile(from_path.value().c_str(), to_path.value().c_str()))
     return true;
+  File::Error move_error = File::OSErrorToFileError(GetLastError());
+
   // Try the full-blown replace if the move fails, as ReplaceFile will only
   // succeed when |to_path| does exist. When writing to a network share, we may
   // not be able to change the ACLs. Ignore ACL errors then
@@ -142,8 +144,14 @@
                     REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL)) {
     return true;
   }
-  if (error)
-    *error = File::OSErrorToFileError(GetLastError());
+  // In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that
+  // |to_path| does not exist. In this case, the more relevant error comes
+  // from the call to MoveFile.
+  if (error) {
+    File::Error replace_error = File::OSErrorToFileError(GetLastError());
+    *error = replace_error == File::FILE_ERROR_NOT_FOUND ? move_error
+                                                         : replace_error;
+  }
   return false;
 }
 
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index 75832654..d16d79f 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -10,6 +10,7 @@
 #include "base/base_switches.h"
 #include "base/build_time.h"
 #include "base/command_line.h"
+#include "base/debug/activity_tracker.h"
 #include "base/logging.h"
 #include "base/metrics/field_trial_param_associator.h"
 #include "base/process/memory.h"
@@ -982,6 +983,15 @@
       ActivateFieldTrialEntryWhileLocked(field_trial);
   }
 
+  // Recording for stability debugging has to be done inline as a task posted
+  // to an observer may not get executed before a crash.
+  base::debug::GlobalActivityTracker* tracker =
+      base::debug::GlobalActivityTracker::Get();
+  if (tracker) {
+    tracker->RecordFieldTrial(field_trial->trial_name(),
+                              field_trial->group_name_internal());
+  }
+
   global_->observer_list_->Notify(
       FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
       field_trial->trial_name(), field_trial->group_name_internal());
diff --git a/base/security_unittest.cc b/base/security_unittest.cc
index af9d2bf1..d88a2a2 100644
--- a/base/security_unittest.cc
+++ b/base/security_unittest.cc
@@ -87,7 +87,7 @@
   }
 }
 
-#if defined(OS_IOS) || defined(OS_WIN) || defined(OS_LINUX)
+#if defined(OS_IOS) || defined(OS_LINUX)
 #define MAYBE_NewOverflow DISABLED_NewOverflow
 #else
 #define MAYBE_NewOverflow NewOverflow
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 18b255a..246a5aa 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -53,8 +53,6 @@
 // TODO(ssid): Fix all the dump providers to unregister if needed and clear the
 // blacklist, crbug.com/643438.
 const char* const kStrictThreadCheckBlacklist[] = {
-    "AndroidGraphics",
-    "BrowserGpuMemoryBufferManager",
     "ClientDiscardableSharedMemoryManager",
     "ContextProviderCommandBuffer",
     "DiscardableSharedMemoryManager",
@@ -65,17 +63,12 @@
     "ThreadLocalEventBuffer",
     "TraceLog",
     "URLRequestContext",
-    "V8Isolate",
     "VpxVideoDecoder",
-    "cc::ResourcePool",
-    "cc::ResourceProvider",
     "cc::SoftwareImageDecodeCache",
     "cc::StagingBufferPool",
     "gpu::BufferManager",
     "gpu::MappedMemoryManager",
     "gpu::RenderbufferManager",
-    "gpu::TransferBufferManager",
-    "sql::Connection",
     "BlacklistTestDumpProvider"  // for testing
 };
 
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
index d6e9f5d16..f056d2b 100644
--- a/base/trace_event/memory_infra_background_whitelist.cc
+++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -68,6 +68,7 @@
     "web_cache/Other_resources",
     "partition_alloc/allocated_objects",
     "partition_alloc/partitions",
+    "partition_alloc/partitions/array_buffer",
     "partition_alloc/partitions/buffer",
     "partition_alloc/partitions/fast_malloc",
     "partition_alloc/partitions/layout",
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index ce140e1..df5325f 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -121,7 +121,54 @@
       fileobj.write(re.sub(r'/tmp/[^/]*', temp_dir, pdb_data))
 
 
+def _CheckPathMatchesClassName(java_file):
+  package_name = ''
+  class_name = None
+  with open(java_file) as f:
+    for l in f:
+      # Strip unindented comments.
+      # Considers a leading * as a continuation of a multi-line comment (our
+      # linter doesn't enforce a space before it like there should be).
+      l = re.sub(r'^(?://.*|/?\*.*?(?:\*/\s*|$))', '', l)
+
+      m = re.match(r'package\s+(.*?);', l)
+      if m and not package_name:
+        package_name = m.group(1)
+
+      # Not exactly a proper parser, but works for sources that Chrome uses.
+      # In order to not match nested classes, it just checks for lack of indent.
+      m = re.match(r'(?:\S.*?)?(?:class|@?interface|enum)\s+(.+?)\b', l)
+      if m:
+        if class_name:
+          raise Exception(('File defines multiple top-level classes:\n    %s\n'
+                           'This confuses compiles with '
+                           'enable_incremental_javac=true.\n'
+                           'classes=%s,%s\n') %
+                          (java_file, class_name, m.groups(1)))
+        class_name = m.group(1)
+
+  if class_name is None:
+    raise Exception('Unable to find a class within %s' % java_file)
+
+  parts = package_name.split('.') + [class_name + '.java']
+  expected_path_suffix = os.path.sep.join(parts)
+  if not java_file.endswith(expected_path_suffix):
+    raise Exception(('Java package+class name do not match its path.\n'
+                     'Actual path: %s\nExpected path: %s') %
+                    (java_file, expected_path_suffix))
+
+
 def _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs):
+  incremental = options.incremental
+  # Don't bother enabling incremental compilation for third_party code, since
+  # _CheckPathMatchesClassName() fails on some of it, and it's not really much
+  # benefit.
+  for java_file in java_files:
+    if 'third_party' in java_file:
+      incremental = False
+    else:
+      _CheckPathMatchesClassName(java_file)
+
   with build_utils.TempDir() as temp_dir:
     srcjars = options.java_srcjars
     # The .excluded.jar contains .class files excluded from the main jar.
@@ -134,7 +181,7 @@
     changed_paths = None
     # jmake can handle deleted files, but it's a rare case and it would
     # complicate this script's logic.
-    if options.incremental and changes.AddedOrModifiedOnly():
+    if incremental and changes.AddedOrModifiedOnly():
       changed_paths = set(changes.IterChangedPaths())
       # Do a full compile if classpath has changed.
       # jmake doesn't seem to do this on its own... Might be that ijars mess up
@@ -142,7 +189,7 @@
       if any(p in changed_paths for p in classpath_inputs):
         changed_paths = None
 
-    if options.incremental:
+    if incremental:
       # jmake is a compiler wrapper that figures out the minimal set of .java
       # files that need to be rebuilt given a set of .java files that have
       # changed.
@@ -190,7 +237,7 @@
 
       # Can happen when a target goes from having no sources, to having sources.
       # It's created by the call to build_utils.Touch() below.
-      if options.incremental:
+      if incremental:
         if os.path.exists(pdb_path) and not os.path.getsize(pdb_path):
           os.unlink(pdb_path)
 
@@ -219,7 +266,7 @@
                '(http://crbug.com/551449).')
         os.unlink(pdb_path)
         attempt_build()
-    elif options.incremental:
+    elif incremental:
       # Make sure output exists.
       build_utils.Touch(pdb_path)
 
diff --git a/build/config/chromecast/BUILD.gn b/build/config/chromecast/BUILD.gn
index 6c208a1..811582f1 100644
--- a/build/config/chromecast/BUILD.gn
+++ b/build/config/chromecast/BUILD.gn
@@ -37,6 +37,13 @@
     "-Wl,-rpath=\$ORIGIN/lib",
     "-Wl,-rpath=\$ORIGIN",
   ]
+
+  # Binaries which don't live in the same directory as Chrome component
+  # libraries may still depend on them. Explicitly add the component library
+  # directory to the rpath for the component build.
+  if (is_component_build) {
+    ldflags += [ "-Wl,-rpath=/system/chrome" ]
+  }
 }
 
 config("executable_config") {
diff --git a/build/win/merge_pgc_files.py b/build/win/merge_pgc_files.py
new file mode 100755
index 0000000..a805ba7
--- /dev/null
+++ b/build/win/merge_pgc_files.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Merge the PGC files generated during the profiling step to the PGD database.
+
+This is required to workaround a flakyness in pgomgr.exe where it can run out
+of address space while trying to merge all the PGC files at the same time.
+"""
+
+import glob
+import json
+import optparse
+import os
+import subprocess
+import sys
+
+
+def find_pgomgr(chrome_checkout_dir):
+  """Find pgomgr.exe."""
+  win_toolchain_json_file = os.path.join(chrome_checkout_dir, 'build',
+      'win_toolchain.json')
+  if not os.path.exists(win_toolchain_json_file):
+    raise Exception('The toolchain JSON file is missing.')
+  with open(win_toolchain_json_file) as temp_f:
+    toolchain_data = json.load(temp_f)
+  if not os.path.isdir(toolchain_data['path']):
+    raise Exception('The toolchain JSON file is invalid.')
+
+  # Always use the x64 version of pgomgr (the x86 one doesn't work on the bot's
+  # environment).
+  pgomgr_dir = os.path.join(toolchain_data['path'], 'VC', 'bin', 'amd64')
+
+  pgomgr_path = os.path.join(pgomgr_dir, 'pgomgr.exe')
+  if not os.path.exists(pgomgr_path):
+    raise Exception('pgomgr.exe is missing from %s.' % pgomgr_dir)
+
+  return pgomgr_path
+
+
+def main():
+  parser = optparse.OptionParser(usage='%prog [options]')
+  parser.add_option('--checkout-dir', help='The Chrome checkout directory.')
+  parser.add_option('--target-cpu', help='[DEPRECATED] The target\'s bitness.')
+  parser.add_option('--build-dir', help='Chrome build directory.')
+  parser.add_option('--binary-name', help='The binary for which the PGC files '
+                    'should be merged, without extension.')
+  options, _ = parser.parse_args()
+
+  if not options.checkout_dir:
+    parser.error('--checkout-dir is required')
+  if not options.build_dir:
+    parser.error('--build-dir is required')
+  if not options.binary_name:
+    parser.error('--binary-name is required')
+
+  # Starts by finding pgomgr.exe.
+  pgomgr_path = find_pgomgr(options.checkout_dir)
+
+  pgc_files = glob.glob(os.path.join(options.build_dir,
+                                     '%s*.pgc' % options.binary_name))
+
+  # Number of PGC files that should be merged in each iterations, merging all
+  # the files one by one is really slow but merging more to 10 at a time doesn't
+  # really seem to impact the total time.
+  #
+  # Number of pgc merged per iteration  |  Time (in min)
+  # 1                                   |  27.2
+  # 10                                  |  12.8
+  # 20                                  |  12.0
+  # 30                                  |  11.5
+  # 40                                  |  11.4
+  # 50                                  |  11.5
+  # 60                                  |  11.6
+  # 70                                  |  11.6
+  # 80                                  |  11.7
+  #
+  # TODO(sebmarchand): Measure the memory usage of pgomgr.exe to see how it get
+  #     affected by the number of pgc files.
+  pgc_per_iter = 20
+
+  def _split_in_chunks(items, chunk_size):
+    """Split |items| in chunks of size |chunk_size|.
+
+    Source: http://stackoverflow.com/a/312464
+    """
+    for i in xrange(0, len(items), chunk_size):
+      yield items[i:i + chunk_size]
+
+  for chunk in _split_in_chunks(pgc_files, pgc_per_iter):
+    merge_command = [
+        pgomgr_path,
+        '/merge'
+    ]
+    for pgc_file in chunk:
+      merge_command.append([
+          os.path.join(options.build_dir, os.path.basename(pgc_file))
+      ])
+
+    merge_command.append([
+        os.path.join(options.build_dir, '%s.pgd' % options.binary_name)
+    ])
+    proc = subprocess.Popen(merge_command, stdout=subprocess.PIPE)
+    stdout, stderr = proc.communicate()
+    print stdout
+    if proc.returncode != 0:
+      raise Exception('Error while trying to merge the PGC files:\n%s' % stderr)
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/cc/PRESUBMIT.py b/cc/PRESUBMIT.py
index 94e66922..6fc669b 100644
--- a/cc/PRESUBMIT.py
+++ b/cc/PRESUBMIT.py
@@ -323,7 +323,6 @@
   results += CheckNamespace(input_api, output_api)
   results += CheckForUseOfWrongClock(input_api, output_api)
   results += FindUselessIfdefs(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
 
 def PostUploadHook(cl, change, output_api):
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc
index 73e62b3..43d7caa 100644
--- a/cc/blink/web_layer_impl.cc
+++ b/cc/blink/web_layer_impl.cc
@@ -217,13 +217,13 @@
   return layer_->HasTickingAnimationForTesting();
 }
 
-void WebLayerImpl::setScrollPositionDouble(blink::WebDoublePoint position) {
+void WebLayerImpl::setScrollPosition(blink::WebFloatPoint position) {
   layer_->SetScrollOffset(gfx::ScrollOffset(position.x, position.y));
 }
 
-blink::WebDoublePoint WebLayerImpl::scrollPositionDouble() const {
-  return blink::WebDoublePoint(layer_->scroll_offset().x(),
-                               layer_->scroll_offset().y());
+blink::WebFloatPoint WebLayerImpl::scrollPosition() const {
+  return blink::WebFloatPoint(layer_->scroll_offset().x(),
+                              layer_->scroll_offset().y());
 }
 
 void WebLayerImpl::setScrollClipLayer(WebLayer* clip_layer) {
@@ -416,7 +416,8 @@
         base::Bind(&blink::WebLayerScrollClient::didScroll,
                    base::Unretained(scroll_client)));
   } else {
-    layer_->set_did_scroll_callback(base::Closure());
+    layer_->set_did_scroll_callback(
+        base::Callback<void(const gfx::ScrollOffset&)>());
   }
 }
 
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h
index 1d8c2a09..2401f1a 100644
--- a/cc/blink/web_layer_impl.h
+++ b/cc/blink/web_layer_impl.h
@@ -89,8 +89,8 @@
   void setFiltersOrigin(const blink::WebFloatPoint& origin) override;
   void setBackgroundFilters(const cc::FilterOperations& filters) override;
   bool hasTickingAnimationForTesting() override;
-  void setScrollPositionDouble(blink::WebDoublePoint position) override;
-  blink::WebDoublePoint scrollPositionDouble() const override;
+  void setScrollPosition(blink::WebFloatPoint position) override;
+  blink::WebFloatPoint scrollPosition() const override;
   void setScrollClipLayer(blink::WebLayer* clip_layer) override;
   bool scrollable() const override;
   void setUserScrollable(bool horizontal, bool vertical) override;
diff --git a/cc/ipc/compositor_frame_metadata.mojom b/cc/ipc/compositor_frame_metadata.mojom
index 992f53d4..2634925 100644
--- a/cc/ipc/compositor_frame_metadata.mojom
+++ b/cc/ipc/compositor_frame_metadata.mojom
@@ -30,4 +30,5 @@
   Selection selection;
   array<ui.mojom.LatencyInfo> latency_info;
   array<SurfaceId> referenced_surfaces;
+  bool can_activate_before_dependencies;
 };
diff --git a/cc/ipc/compositor_frame_metadata_struct_traits.cc b/cc/ipc/compositor_frame_metadata_struct_traits.cc
index aa53150..e64f6727 100644
--- a/cc/ipc/compositor_frame_metadata_struct_traits.cc
+++ b/cc/ipc/compositor_frame_metadata_struct_traits.cc
@@ -38,6 +38,8 @@
   out->bottom_controls_shown_ratio = data.bottom_controls_shown_ratio();
 
   out->root_background_color = data.root_background_color();
+  out->can_activate_before_dependencies =
+      data.can_activate_before_dependencies();
   return data.ReadSelection(&out->selection) &&
          data.ReadLatencyInfo(&out->latency_info) &&
          data.ReadReferencedSurfaces(&out->referenced_surfaces);
diff --git a/cc/ipc/compositor_frame_metadata_struct_traits.h b/cc/ipc/compositor_frame_metadata_struct_traits.h
index 318e1981..381edb3f 100644
--- a/cc/ipc/compositor_frame_metadata_struct_traits.h
+++ b/cc/ipc/compositor_frame_metadata_struct_traits.h
@@ -106,6 +106,11 @@
     return metadata.referenced_surfaces;
   }
 
+  static bool can_activate_before_dependencies(
+      const cc::CompositorFrameMetadata& metadata) {
+    return metadata.can_activate_before_dependencies;
+  }
+
   static bool Read(cc::mojom::CompositorFrameMetadataDataView data,
                    cc::CompositorFrameMetadata* out);
 };
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 3446f38..5f777af 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -823,7 +823,8 @@
     property_trees->needs_rebuild = true;
 
   if (!inputs_.did_scroll_callback.is_null())
-    inputs_.did_scroll_callback.Run();
+    inputs_.did_scroll_callback.Run(scroll_offset);
+
   // The callback could potentially change the layer structure:
   // "this" may have been destroyed during the process.
 }
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index d4d3ae9d..0016527 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -251,7 +251,8 @@
     return inputs_.touch_event_handler_region;
   }
 
-  void set_did_scroll_callback(const base::Closure& callback) {
+  void set_did_scroll_callback(
+      const base::Callback<void(const gfx::ScrollOffset&)>& callback) {
     inputs_.did_scroll_callback = callback;
   }
 
@@ -614,7 +615,7 @@
 
     // The following elements can not and are not serialized.
     LayerClient* client;
-    base::Closure did_scroll_callback;
+    base::Callback<void(const gfx::ScrollOffset&)> did_scroll_callback;
     std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests;
 
     gfx::Size preferred_raster_bounds;
diff --git a/cc/output/compositor_frame_metadata.h b/cc/output/compositor_frame_metadata.h
index 206a4a0..e383e50 100644
--- a/cc/output/compositor_frame_metadata.h
+++ b/cc/output/compositor_frame_metadata.h
@@ -78,6 +78,10 @@
   // This is the set of Surfaces that are referenced by this frame.
   std::vector<SurfaceId> referenced_surfaces;
 
+  // This indicates whether this CompositorFrame can be activated before
+  // dependencies have been resolved.
+  bool can_activate_before_dependencies = true;
+
  private:
   CompositorFrameMetadata(const CompositorFrameMetadata& other);
   CompositorFrameMetadata operator=(const CompositorFrameMetadata&) = delete;
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 18609745..a0ed611 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -83,9 +83,9 @@
   return xform;
 }
 
-Float4 PremultipliedColor(SkColor color) {
+Float4 PremultipliedColor(SkColor color, float opacity) {
   const float factor = 1.0f / 255.0f;
-  const float alpha = SkColorGetA(color) * factor;
+  const float alpha = opacity * SkColorGetA(color) * factor;
 
   Float4 result = {
       {SkColorGetR(color) * factor * alpha, SkColorGetG(color) * factor * alpha,
@@ -379,17 +379,11 @@
                        TextureMailboxDeleter* texture_mailbox_deleter,
                        int highp_threshold_min)
     : DirectRenderer(settings, output_surface, resource_provider),
-      offscreen_framebuffer_id_(0),
       shared_geometry_quad_(QuadVertexRect()),
       gl_(output_surface->context_provider()->ContextGL()),
       context_support_(output_surface->context_provider()->ContextSupport()),
       texture_mailbox_deleter_(texture_mailbox_deleter),
-      is_scissor_enabled_(false),
-      stencil_shadow_(false),
-      blend_shadow_(false),
       highp_threshold_min_(highp_threshold_min),
-      highp_threshold_cache_(0),
-      use_sync_query_(false),
       gl_composited_texture_quad_border_(
           settings->gl_composited_texture_quad_border),
       bound_geometry_(NO_BINDING),
@@ -619,11 +613,8 @@
                                      const DebugBorderDrawQuad* quad) {
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
-  static float gl_matrix[16];
   const Program* program = GetProgram(ProgramKey::DebugBorder());
-  DCHECK(program);
-  DCHECK(program->initialized() || IsContextLost());
-  SetUseProgram(program->program());
+  SetUseProgram(program);
 
   // Use the full quad_rect for debug quads to not move the edges based on
   // partial swaps.
@@ -632,17 +623,8 @@
   QuadRectTransform(&render_matrix,
                     quad->shared_quad_state->quad_to_target_transform,
                     gfx::RectF(layer_rect));
-  GLRenderer::ToGLMatrix(&gl_matrix[0],
-                         frame->projection_matrix * render_matrix);
-  gl_->UniformMatrix4fv(program->matrix_location(), 1, false, &gl_matrix[0]);
-
-  SkColor color = quad->color;
-  float alpha = SkColorGetA(color) * (1.0f / 255.0f);
-
-  gl_->Uniform4f(program->color_location(),
-                 (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
-                 (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
-                 (SkColorGetB(color) * (1.0f / 255.0f)) * alpha, alpha);
+  SetShaderMatrix(frame->projection_matrix * render_matrix);
+  SetShaderColor(quad->color, 1.f);
 
   gl_->LineWidth(quad->width);
 
@@ -1345,8 +1327,7 @@
       tex_coord_precision, sampler_type, shader_blend_mode,
       params->use_aa ? USE_AA : NO_AA, mask_mode, mask_for_background,
       params->use_color_matrix));
-  SetUseProgram(params->program->program());
-  gl_->Uniform1i(params->program->sampler_location(), 0);
+  SetUseProgram(params->program);
 }
 
 void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) {
@@ -1415,16 +1396,6 @@
   if (program->edge_location() != -1)
     gl_->Uniform3fv(program->edge_location(), 8, params->edge);
 
-  if (program->viewport_location() != -1) {
-    float viewport[4] = {
-        static_cast<float>(current_window_space_viewport_.x()),
-        static_cast<float>(current_window_space_viewport_.y()),
-        static_cast<float>(current_window_space_viewport_.width()),
-        static_cast<float>(current_window_space_viewport_.height()),
-    };
-    gl_->Uniform4fv(program->viewport_location(), 1, viewport);
-  }
-
   if (program->color_matrix_location() != -1) {
     float matrix[16];
     for (int i = 0; i < 4; ++i) {
@@ -1472,14 +1443,13 @@
     }
   }
 
-  SetShaderOpacity(params->quad->shared_quad_state->opacity,
-                   program->alpha_location());
-  SetShaderQuadF(params->surface_quad, program->quad_location());
+  SetShaderOpacity(params->quad);
+  SetShaderQuadF(params->surface_quad);
 }
 
 void GLRenderer::DrawRPDQ(const DrawRenderPassDrawQuadParams& params) {
   DrawQuadGeometry(params.projection_matrix, params.quad_to_target_transform,
-                   params.dst_rect, params.program->matrix_location());
+                   params.dst_rect);
 
   // Flush the compositor context before the filter bitmap goes out of
   // scope, so the draw gets processed before the filter texture gets deleted.
@@ -1797,20 +1767,10 @@
 
   const Program* program =
       GetProgram(ProgramKey::SolidColor(use_aa ? USE_AA : NO_AA));
-  SetUseProgram(program->program());
+  SetUseProgram(program);
+  SetShaderColor(color, opacity);
 
-  gl_->Uniform4f(program->color_location(),
-                 (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
-                 (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
-                 (SkColorGetB(color) * (1.0f / 255.0f)) * alpha, alpha);
   if (use_aa) {
-    float viewport[4] = {
-        static_cast<float>(current_window_space_viewport_.x()),
-        static_cast<float>(current_window_space_viewport_.y()),
-        static_cast<float>(current_window_space_viewport_.width()),
-        static_cast<float>(current_window_space_viewport_.height()),
-    };
-    gl_->Uniform4fv(program->viewport_location(), 1, viewport);
     gl_->Uniform3fv(program->edge_location(), 8, edge);
   }
 
@@ -1824,7 +1784,7 @@
     // Normalize to tile_rect.
     local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
 
-    SetShaderQuadF(local_quad, program->quad_location());
+    SetShaderQuadF(local_quad);
 
     // The transform and vertex data are used to figure out the extents that the
     // un-antialiased quad should have and which vertex this is and the float
@@ -1836,16 +1796,12 @@
         gfx::SizeF(tile_rect.size()));
     DrawQuadGeometry(frame->projection_matrix,
                      quad->shared_quad_state->quad_to_target_transform,
-                     centered_rect, program->matrix_location());
+                     centered_rect);
   } else {
     PrepareGeometry(SHARED_BINDING);
-    SetShaderQuadF(local_quad, program->quad_location());
-    static float gl_matrix[16];
-    ToGLMatrix(&gl_matrix[0],
-               frame->projection_matrix *
-                   quad->shared_quad_state->quad_to_target_transform);
-    gl_->UniformMatrix4fv(program->matrix_location(), 1, false, &gl_matrix[0]);
-
+    SetShaderQuadF(local_quad);
+    SetShaderMatrix(frame->projection_matrix *
+                    quad->shared_quad_state->quad_to_target_transform);
     gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
   }
 }
@@ -1966,16 +1922,8 @@
       tex_coord_precision, sampler, USE_AA,
       quad->swizzle_contents ? DO_SWIZZLE : NO_SWIZZLE, false));
 
-  SetUseProgram(program->program());
-  gl_->Uniform1i(program->sampler_location(), 0);
+  SetUseProgram(program);
 
-  float viewport[4] = {
-      static_cast<float>(current_window_space_viewport_.x()),
-      static_cast<float>(current_window_space_viewport_.y()),
-      static_cast<float>(current_window_space_viewport_.width()),
-      static_cast<float>(current_window_space_viewport_.height()),
-  };
-  gl_->Uniform4fv(program->viewport_location(), 1, viewport);
   gl_->Uniform3fv(program->edge_location(), 8, edge);
 
   gl_->Uniform4f(program->vertex_tex_transform_location(),
@@ -1991,8 +1939,8 @@
   // Normalize to tile_rect.
   local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
 
-  SetShaderOpacity(quad->shared_quad_state->opacity, program->alpha_location());
-  SetShaderQuadF(local_quad, program->quad_location());
+  SetShaderOpacity(quad);
+  SetShaderQuadF(local_quad);
 
   // The transform and vertex data are used to figure out the extents that the
   // un-antialiased quad should have and which vertex this is and the float
@@ -2003,7 +1951,7 @@
       gfx::SizeF(tile_rect.size()));
   DrawQuadGeometry(frame->projection_matrix,
                    quad->shared_quad_state->quad_to_target_transform,
-                   centered_rect, program->matrix_location());
+                   centered_rect);
 }
 
 void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame,
@@ -2053,8 +2001,7 @@
                        quad->swizzle_contents ? DO_SWIZZLE : NO_SWIZZLE,
                        !quad->ShouldDrawWithBlending()));
 
-  SetUseProgram(program->program());
-  gl_->Uniform1i(program->sampler_location(), 0);
+  SetUseProgram(program);
 
   gl_->Uniform4f(program->vertex_tex_transform_location(),
                  vertex_tex_translate_x, vertex_tex_translate_y,
@@ -2062,7 +2009,7 @@
 
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
-  SetShaderOpacity(quad->shared_quad_state->opacity, program->alpha_location());
+  SetShaderOpacity(quad);
 
   // Pass quad coordinates to the uniform in the same order as GeometryBinding
   // does, then vertices will match the texture mapping in the vertex buffer.
@@ -2097,11 +2044,8 @@
   };
   gl_->Uniform2fv(program->quad_location(), 4, gl_quad);
 
-  static float gl_matrix[16];
-  ToGLMatrix(&gl_matrix[0],
-             frame->projection_matrix *
-                 quad->shared_quad_state->quad_to_target_transform);
-  gl_->UniformMatrix4fv(program->matrix_location(), 1, false, &gl_matrix[0]);
+  SetShaderMatrix(frame->projection_matrix *
+                  quad->shared_quad_state->quad_to_target_transform);
 
   gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
 }
@@ -2210,8 +2154,7 @@
   const Program* program = GetProgram(
       ProgramKey::YUVVideo(tex_coord_precision, sampler, alpha_texture_mode,
                            uv_texture_mode, color_conversion_mode));
-  DCHECK(program && (program->initialized() || IsContextLost()));
-  SetUseProgram(program->program());
+  SetUseProgram(program);
 
   gfx::SizeF ya_tex_scale(1.0f, 1.0f);
   gfx::SizeF uv_tex_scale(1.0f, 1.0f);
@@ -2298,11 +2241,11 @@
   // it. This is why this centered rect is used and not the original quad_rect.
   auto tile_rect = gfx::RectF(quad->rect);
 
-  SetShaderOpacity(quad->shared_quad_state->opacity, program->alpha_location());
+  SetShaderOpacity(quad);
   if (!clip_region) {
     DrawQuadGeometry(frame->projection_matrix,
                      quad->shared_quad_state->quad_to_target_transform,
-                     tile_rect, program->matrix_location());
+                     tile_rect);
   } else {
     float uvs[8] = {0};
     GetScaledUVs(quad->visible_rect, clip_region, uvs);
@@ -2311,7 +2254,7 @@
     region_quad -= gfx::Vector2dF(0.5f, 0.5f);
     DrawQuadGeometryClippedByQuadF(
         frame, quad->shared_quad_state->quad_to_target_transform, tile_rect,
-        region_quad, program->matrix_location(), uvs);
+        region_quad, uvs);
   }
 }
 
@@ -2320,8 +2263,6 @@
                                      const gfx::QuadF* clip_region) {
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
-  static float gl_matrix[16];
-
   DCHECK(output_surface_->context_provider()
              ->ContextCapabilities()
              .egl_image_external);
@@ -2332,9 +2273,7 @@
 
   const Program* program =
       GetProgram(ProgramKey::VideoStream(tex_coord_precision));
-  SetUseProgram(program->program());
-
-  ToGLMatrix(&gl_matrix[0], quad->matrix);
+  SetUseProgram(program);
 
   ResourceProvider::ScopedReadLockGL lock(resource_provider_,
                                           quad->resource_id());
@@ -2342,16 +2281,16 @@
   DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_));
   gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id());
 
+  static float gl_matrix[16];
+  ToGLMatrix(&gl_matrix[0], quad->matrix);
   gl_->UniformMatrix4fvStreamTextureMatrixCHROMIUM(
       program->tex_matrix_location(), false, gl_matrix);
 
-  gl_->Uniform1i(program->sampler_location(), 0);
-
-  SetShaderOpacity(quad->shared_quad_state->opacity, program->alpha_location());
+  SetShaderOpacity(quad);
   if (!clip_region) {
     DrawQuadGeometry(frame->projection_matrix,
                      quad->shared_quad_state->quad_to_target_transform,
-                     gfx::RectF(quad->rect), program->matrix_location());
+                     gfx::RectF(quad->rect));
   } else {
     gfx::QuadF region_quad(*clip_region);
     region_quad.Scale(1.0f / quad->rect.width(), 1.0f / quad->rect.height());
@@ -2360,13 +2299,13 @@
     GetScaledUVs(quad->visible_rect, clip_region, uvs);
     DrawQuadGeometryClippedByQuadF(
         frame, quad->shared_quad_state->quad_to_target_transform,
-        gfx::RectF(quad->rect), region_quad, program->matrix_location(), uvs);
+        gfx::RectF(quad->rect), region_quad, uvs);
   }
 }
 
 void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) {
   // Check to see if we have anything to draw.
-  if (draw_cache_.program_id == -1)
+  if (!draw_cache_.program)
     return;
 
   PrepareGeometry(flush_binding);
@@ -2375,10 +2314,7 @@
   SetBlendEnabled(draw_cache_.needs_blending);
 
   // Bind the program to the GL state.
-  SetUseProgram(draw_cache_.program_id);
-
-  // Bind the correct texture sampler location.
-  gl_->Uniform1i(draw_cache_.sampler_location, 0);
+  SetUseProgram(draw_cache_.program);
 
   // Assume the current active textures is 0.
   ResourceProvider::ScopedSamplerGL locked_quad(
@@ -2395,21 +2331,22 @@
 
   // Upload the tranforms for both points and uvs.
   gl_->UniformMatrix4fv(
-      static_cast<int>(draw_cache_.matrix_location),
+      draw_cache_.program->matrix_location(),
       static_cast<int>(draw_cache_.matrix_data.size()), false,
       reinterpret_cast<float*>(&draw_cache_.matrix_data.front()));
-  gl_->Uniform4fv(static_cast<int>(draw_cache_.uv_xform_location),
+  gl_->Uniform4fv(draw_cache_.program->vertex_tex_transform_location(),
                   static_cast<int>(draw_cache_.uv_xform_data.size()),
                   reinterpret_cast<float*>(&draw_cache_.uv_xform_data.front()));
 
   if (draw_cache_.background_color != SK_ColorTRANSPARENT) {
-    Float4 background_color = PremultipliedColor(draw_cache_.background_color);
-    gl_->Uniform4fv(draw_cache_.background_color_location, 1,
+    Float4 background_color =
+        PremultipliedColor(draw_cache_.background_color, 1.f);
+    gl_->Uniform4fv(draw_cache_.program->background_color_location(), 1,
                     background_color.data);
   }
 
   gl_->Uniform1fv(
-      static_cast<int>(draw_cache_.vertex_opacity_location),
+      draw_cache_.program->vertex_opacity_location(),
       static_cast<int>(draw_cache_.vertex_opacity_data.size()),
       static_cast<float*>(&draw_cache_.vertex_opacity_data.front()));
 
@@ -2426,9 +2363,7 @@
     DCHECK_EQ(1u, draw_cache_.matrix_data.size());
     SetBlendEnabled(false);
     const Program* program = GetProgram(ProgramKey::DebugBorder());
-    DCHECK(program);
-    DCHECK(program->initialized() || IsContextLost());
-    SetUseProgram(program->program());
+    SetUseProgram(program);
 
     gl_->UniformMatrix4fv(
         program->matrix_location(), 1, false,
@@ -2438,9 +2373,7 @@
     int colorIndex = static_cast<int>(draw_cache_.matrix_data.front().data[0] *
                                       draw_cache_.matrix_data.front().data[5]);
     SkColor color = DebugColors::GLCompositedTextureQuadBorderColor(colorIndex);
-
-    gl_->Uniform4f(program->color_location(), SkColorGetR(color),
-                   SkColorGetG(color), SkColorGetB(color), 1.0f);
+    SetShaderColor(color, 1.f);
 
     gl_->LineWidth(DebugColors::GLCompositedTextureQuadBoderWidth());
     // The indices for the line are stored in the same array as the triangle
@@ -2449,7 +2382,8 @@
   }
 
   // Clear the cache.
-  draw_cache_.program_id = -1;
+  draw_cache_.program = nullptr;
+  draw_cache_.resource_id = -1;
   draw_cache_.uv_xform_data.resize(0);
   draw_cache_.vertex_opacity_data.resize(0);
   draw_cache_.matrix_data.resize(0);
@@ -2486,28 +2420,20 @@
       quad->premultiplied_alpha ? PREMULTIPLIED_ALPHA : NON_PREMULTIPLIED_ALPHA,
       quad->background_color != SK_ColorTRANSPARENT));
   int resource_id = quad->resource_id();
-  int program_id = program->program();
 
   size_t max_quads = StaticGeometryBinding::NUM_QUADS;
-  if (draw_cache_.program_id != program_id ||
+  if (draw_cache_.program != program ||
       draw_cache_.resource_id != resource_id ||
       draw_cache_.needs_blending != quad->ShouldDrawWithBlending() ||
       draw_cache_.nearest_neighbor != quad->nearest_neighbor ||
       draw_cache_.background_color != quad->background_color ||
       draw_cache_.matrix_data.size() >= max_quads) {
     FlushTextureQuadCache(SHARED_BINDING);
-    draw_cache_.program_id = program_id;
+    draw_cache_.program = program;
     draw_cache_.resource_id = resource_id;
     draw_cache_.needs_blending = quad->ShouldDrawWithBlending();
     draw_cache_.nearest_neighbor = quad->nearest_neighbor;
     draw_cache_.background_color = quad->background_color;
-
-    draw_cache_.uv_xform_location = program->vertex_tex_transform_location();
-    draw_cache_.background_color_location =
-        program->background_color_location();
-    draw_cache_.vertex_opacity_location = program->vertex_opacity_location();
-    draw_cache_.matrix_location = program->matrix_location();
-    draw_cache_.sampler_location = program->sampler_location();
   }
 
   // Generate the uv-transform
@@ -2635,10 +2561,9 @@
   transform.matrix().asColMajorf(gl_matrix);
 }
 
-void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad, int quad_location) {
-  if (quad_location == -1)
+void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad) {
+  if (!program_shadow_ || program_shadow_->quad_location() == -1)
     return;
-
   float gl_quad[8];
   gl_quad[0] = quad.p1().x();
   gl_quad[1] = quad.p1().y();
@@ -2648,12 +2573,30 @@
   gl_quad[5] = quad.p3().y();
   gl_quad[6] = quad.p4().x();
   gl_quad[7] = quad.p4().y();
-  gl_->Uniform2fv(quad_location, 4, gl_quad);
+  gl_->Uniform2fv(program_shadow_->quad_location(), 4, gl_quad);
 }
 
-void GLRenderer::SetShaderOpacity(float opacity, int alpha_location) {
-  if (alpha_location != -1)
-    gl_->Uniform1f(alpha_location, opacity);
+void GLRenderer::SetShaderOpacity(const DrawQuad* quad) {
+  if (!program_shadow_ || program_shadow_->alpha_location() == -1)
+    return;
+  gl_->Uniform1f(program_shadow_->alpha_location(),
+                 quad->shared_quad_state->opacity);
+}
+
+void GLRenderer::SetShaderMatrix(const gfx::Transform& transform) {
+  if (!program_shadow_ || program_shadow_->matrix_location() == -1)
+    return;
+  float gl_matrix[16];
+  ToGLMatrix(gl_matrix, transform);
+  gl_->UniformMatrix4fv(program_shadow_->matrix_location(), 1, false,
+                        gl_matrix);
+}
+
+void GLRenderer::SetShaderColor(SkColor color, float opacity) {
+  if (!program_shadow_ || program_shadow_->color_location() == -1)
+    return;
+  Float4 float_color = PremultipliedColor(color, opacity);
+  gl_->Uniform4fv(program_shadow_->color_location(), 1, float_color.data);
 }
 
 void GLRenderer::SetStencilEnabled(bool enabled) {
@@ -2678,10 +2621,25 @@
   blend_shadow_ = enabled;
 }
 
-void GLRenderer::SetUseProgram(unsigned program) {
+void GLRenderer::SetUseProgram(const Program* program) {
+  DCHECK(program);
+  DCHECK(program->initialized() || IsContextLost());
   if (program == program_shadow_)
     return;
-  gl_->UseProgram(program);
+  gl_->UseProgram(program->program());
+
+  // Set uniforms that are common to all programs.
+  if (program->sampler_location() != -1)
+    gl_->Uniform1i(program->sampler_location(), 0);
+  if (program->viewport_location() != -1) {
+    float viewport[4] = {
+        static_cast<float>(current_window_space_viewport_.x()),
+        static_cast<float>(current_window_space_viewport_.y()),
+        static_cast<float>(current_window_space_viewport_.width()),
+        static_cast<float>(current_window_space_viewport_.height()),
+    };
+    gl_->Uniform4fv(program->viewport_location(), 1, viewport);
+  }
   program_shadow_ = program;
 }
 
@@ -2690,7 +2648,6 @@
     const gfx::Transform& draw_transform,
     const gfx::RectF& quad_rect,
     const gfx::QuadF& clipping_region_quad,
-    int matrix_location,
     const float* uvs) {
   PrepareGeometry(CLIPPED_BINDING);
   if (uvs) {
@@ -2700,9 +2657,7 @@
   }
   gfx::Transform quad_rect_matrix;
   QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect);
-  static float gl_matrix[16];
-  ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad_rect_matrix);
-  gl_->UniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0]);
+  SetShaderMatrix(frame->projection_matrix * quad_rect_matrix);
 
   gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
                     reinterpret_cast<const void*>(0));
@@ -2710,14 +2665,11 @@
 
 void GLRenderer::DrawQuadGeometry(const gfx::Transform& projection_matrix,
                                   const gfx::Transform& draw_transform,
-                                  const gfx::RectF& quad_rect,
-                                  int matrix_location) {
+                                  const gfx::RectF& quad_rect) {
   PrepareGeometry(SHARED_BINDING);
   gfx::Transform quad_rect_matrix;
   QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect);
-  static float gl_matrix[16];
-  ToGLMatrix(&gl_matrix[0], projection_matrix * quad_rect_matrix);
-  gl_->UniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0]);
+  SetShaderMatrix(projection_matrix * quad_rect_matrix);
 
   gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
 }
@@ -3157,7 +3109,7 @@
   scissor_rect_ = gfx::Rect();
   stencil_shadow_ = false;
   blend_shadow_ = true;
-  program_shadow_ = 0;
+  program_shadow_ = nullptr;
 
   RestoreGLState();
 }
@@ -3174,7 +3126,7 @@
   gl_->ActiveTexture(GL_TEXTURE0);
 
   if (program_shadow_)
-    gl_->UseProgram(program_shadow_);
+    gl_->UseProgram(program_shadow_->program());
 
   if (stencil_shadow_)
     gl_->Enable(GL_STENCIL_TEST);
@@ -3501,18 +3453,13 @@
   PrepareGeometry(SHARED_BINDING);
 
   const Program* program = GetProgram(ProgramKey::DebugBorder());
-  DCHECK(program);
-  DCHECK(program->initialized() || IsContextLost());
-  SetUseProgram(program->program());
+  SetUseProgram(program);
 
   gfx::Transform render_matrix;
   render_matrix.Translate(0.5 * output_rect.width() + output_rect.x(),
                           0.5 * output_rect.height() + output_rect.y());
   render_matrix.Scale(output_rect.width(), output_rect.height());
-  static float gl_matrix[16];
-  GLRenderer::ToGLMatrix(&gl_matrix[0],
-                         frame->projection_matrix * render_matrix);
-  gl_->UniformMatrix4fv(program->matrix_location(), 1, false, &gl_matrix[0]);
+  SetShaderMatrix(frame->projection_matrix * render_matrix);
 
   // Produce hinting for the amount of overdraw on screen for each pixel by
   // drawing hint colors to the framebuffer based on the current stencil value.
@@ -3561,9 +3508,7 @@
 
     gl_->StencilFunc(test.func, test.ref, 0xffffffff);
     // Transparent color unless color-coding of overdraw is enabled.
-    Float4 color =
-        PremultipliedColor(settings_->show_overdraw_feedback ? test.color : 0);
-    gl_->Uniform4fv(program->color_location(), 1, color.data);
+    SetShaderColor(settings_->show_overdraw_feedback ? test.color : 0, 1.f);
     gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
 
     if (query) {
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 423b730..d18bddbf 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -223,19 +223,19 @@
                         const YUVVideoDrawQuad* quad,
                         const gfx::QuadF* clip_region);
 
-  void SetShaderOpacity(float opacity, int alpha_location);
-  void SetShaderQuadF(const gfx::QuadF& quad, int quad_location);
+  void SetShaderOpacity(const DrawQuad* quad);
+  void SetShaderQuadF(const gfx::QuadF& quad);
+  void SetShaderMatrix(const gfx::Transform& transform);
+  void SetShaderColor(SkColor color, float opacity);
   void DrawQuadGeometryClippedByQuadF(const DrawingFrame* frame,
                                       const gfx::Transform& draw_transform,
                                       const gfx::RectF& quad_rect,
                                       const gfx::QuadF& clipping_region_quad,
-                                      int matrix_location,
                                       const float uv[8]);
   void DrawQuadGeometry(const gfx::Transform& projection_matrix,
                         const gfx::Transform& draw_transform,
-                        const gfx::RectF& quad_rect,
-                        int matrix_location);
-  void SetUseProgram(unsigned program);
+                        const gfx::RectF& quad_rect);
+  void SetUseProgram(const Program* program);
 
   bool MakeContextCurrent();
 
@@ -297,7 +297,7 @@
   // texture id of the resource.
   std::map<unsigned, OverlayResourceLock> swapped_and_acked_overlay_resources_;
 
-  unsigned offscreen_framebuffer_id_;
+  unsigned offscreen_framebuffer_id_ = 0u;
 
   std::unique_ptr<StaticGeometryBinding> shared_geometry_;
   std::unique_ptr<DynamicGeometryBinding> clipped_geometry_;
@@ -322,14 +322,13 @@
 
   gfx::Rect swap_buffer_rect_;
   gfx::Rect scissor_rect_;
-  bool is_using_bind_uniform_;
-  bool is_scissor_enabled_;
-  bool stencil_shadow_;
-  bool blend_shadow_;
-  unsigned program_shadow_;
+  bool is_scissor_enabled_ = false;
+  bool stencil_shadow_ = false;
+  bool blend_shadow_ = false;
+  const Program* program_shadow_ = nullptr;
   TexturedQuadDrawCache draw_cache_;
-  int highp_threshold_min_;
-  int highp_threshold_cache_;
+  int highp_threshold_min_ = 0;
+  int highp_threshold_cache_ = 0;
 
   struct PendingAsyncReadPixels;
   std::vector<std::unique_ptr<PendingAsyncReadPixels>>
@@ -344,10 +343,10 @@
   std::deque<std::unique_ptr<SyncQuery>> pending_sync_queries_;
   std::deque<std::unique_ptr<SyncQuery>> available_sync_queries_;
   std::unique_ptr<SyncQuery> current_sync_query_;
-  bool use_discard_framebuffer_;
-  bool use_sync_query_;
-  bool use_blend_equation_advanced_;
-  bool use_blend_equation_advanced_coherent_;
+  bool use_discard_framebuffer_ = false;
+  bool use_sync_query_ = false;
+  bool use_blend_equation_advanced_ = false;
+  bool use_blend_equation_advanced_coherent_ = false;
 
   // Some overlays require that content is copied from a render pass into an
   // overlay resource. This means the GLRenderer needs its own ResourcePool.
diff --git a/cc/output/gl_renderer_draw_cache.cc b/cc/output/gl_renderer_draw_cache.cc
index 91581f48..6364218 100644
--- a/cc/output/gl_renderer_draw_cache.cc
+++ b/cc/output/gl_renderer_draw_cache.cc
@@ -6,18 +6,7 @@
 
 namespace cc {
 
-TexturedQuadDrawCache::TexturedQuadDrawCache()
-    : program_id(-1),
-      resource_id(-1),
-      needs_blending(false),
-      nearest_neighbor(false),
-      background_color(0),
-      uv_xform_location(-1),
-      background_color_location(-1),
-      vertex_opacity_location(-1),
-      matrix_location(-1),
-      sampler_location(-1) {
-}
+TexturedQuadDrawCache::TexturedQuadDrawCache() {}
 
 TexturedQuadDrawCache::~TexturedQuadDrawCache() {}
 
diff --git a/cc/output/gl_renderer_draw_cache.h b/cc/output/gl_renderer_draw_cache.h
index e02b73b..493ae4ca2 100644
--- a/cc/output/gl_renderer_draw_cache.h
+++ b/cc/output/gl_renderer_draw_cache.h
@@ -12,6 +12,8 @@
 
 namespace cc {
 
+class Program;
+
 // Collects 4 floats at a time for easy upload to GL.
 struct Float4 {
   float data[4];
@@ -30,18 +32,11 @@
   ~TexturedQuadDrawCache();
 
   // Values tracked to determine if textured quads may be coalesced.
-  int program_id;
-  int resource_id;
-  bool needs_blending;
-  bool nearest_neighbor;
-  SkColor background_color;
-
-  // Information about the program binding that is required to draw.
-  int uv_xform_location;
-  int background_color_location;
-  int vertex_opacity_location;
-  int matrix_location;
-  int sampler_location;
+  const Program* program = nullptr;
+  int resource_id = -1;
+  bool needs_blending = false;
+  bool nearest_neighbor = false;
+  SkColor background_color = 0;
 
   // A cache for the coalesced quad data.
   std::vector<Float4> uv_xform_data;
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 3611a591..42cdb4f 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -410,7 +410,7 @@
         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, NO_AA,
                                NO_MASK, false, false));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestRenderPassColorMatrixProgram(TexCoordPrecision precision,
@@ -419,7 +419,7 @@
         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, NO_AA,
                                NO_MASK, false, true));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestRenderPassMaskProgram(TexCoordPrecision precision,
@@ -429,7 +429,7 @@
         renderer_->GetProgramIfInitialized(ProgramKey::RenderPass(
             precision, sampler, blend_mode, NO_AA, HAS_MASK, false, false));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision,
@@ -439,7 +439,7 @@
         renderer_->GetProgramIfInitialized(ProgramKey::RenderPass(
             precision, sampler, blend_mode, NO_AA, HAS_MASK, false, true));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestRenderPassProgramAA(TexCoordPrecision precision,
@@ -448,7 +448,7 @@
         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, USE_AA,
                                NO_MASK, false, false));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision,
@@ -457,7 +457,7 @@
         ProgramKey::RenderPass(precision, SAMPLER_TYPE_2D, blend_mode, USE_AA,
                                NO_MASK, false, true));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestRenderPassMaskProgramAA(TexCoordPrecision precision,
@@ -467,7 +467,7 @@
         renderer_->GetProgramIfInitialized(ProgramKey::RenderPass(
             precision, sampler, blend_mode, USE_AA, HAS_MASK, false, false));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
@@ -477,14 +477,14 @@
         renderer_->GetProgramIfInitialized(ProgramKey::RenderPass(
             precision, sampler, blend_mode, USE_AA, HAS_MASK, false, true));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   void TestSolidColorProgramAA() {
     const Program* program =
         renderer_->GetProgramIfInitialized(ProgramKey::SolidColor(USE_AA));
     EXPECT_PROGRAM_VALID(program);
-    EXPECT_EQ(program->program(), renderer_->program_shadow_);
+    EXPECT_EQ(program, renderer_->program_shadow_);
   }
 
   RendererSettings settings_;
diff --git a/cc/surfaces/BUILD.gn b/cc/surfaces/BUILD.gn
index 3e67b196a..f9e953f 100644
--- a/cc/surfaces/BUILD.gn
+++ b/cc/surfaces/BUILD.gn
@@ -44,6 +44,7 @@
     "display_client.h",
     "display_scheduler.cc",
     "display_scheduler.h",
+    "pending_frame_observer.h",
     "referenced_surface_tracker.cc",
     "referenced_surface_tracker.h",
     "sequence_surface_reference_factory.cc",
@@ -52,6 +53,8 @@
     "surface.h",
     "surface_aggregator.cc",
     "surface_aggregator.h",
+    "surface_dependency_tracker.cc",
+    "surface_dependency_tracker.h",
     "surface_factory.cc",
     "surface_factory.h",
     "surface_factory_client.h",
diff --git a/cc/surfaces/compositor_frame_sink_support.cc b/cc/surfaces/compositor_frame_sink_support.cc
index 95d7f09..95222ed 100644
--- a/cc/surfaces/compositor_frame_sink_support.cc
+++ b/cc/surfaces/compositor_frame_sink_support.cc
@@ -17,31 +17,25 @@
     CompositorFrameSinkSupportClient* client,
     SurfaceManager* surface_manager,
     const FrameSinkId& frame_sink_id,
-    Display* display,
-    bool handles_frame_sink_id_invalidation,
-    bool needs_sync_points)
+    std::unique_ptr<Display> display,
+    std::unique_ptr<BeginFrameSource> display_begin_frame_source)
     : client_(client),
       surface_manager_(surface_manager),
       frame_sink_id_(frame_sink_id),
-      display_(display),
+      display_begin_frame_source_(std::move(display_begin_frame_source)),
+      display_(std::move(display)),
       surface_factory_(frame_sink_id_, surface_manager_, this),
-      handles_frame_sink_id_invalidation_(handles_frame_sink_id_invalidation),
       weak_factory_(this) {
-  if (handles_frame_sink_id_invalidation_)
-    surface_manager_->RegisterFrameSinkId(frame_sink_id_);
-
+  surface_manager_->RegisterFrameSinkId(frame_sink_id_);
   surface_manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this);
-  surface_factory_.set_needs_sync_points(needs_sync_points);
 
-  if (display_)
+  if (display_) {
     display_->Initialize(this, surface_manager_);
+    display_->SetVisible(true);
+  }
 }
 
 CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
-  // Unregister |this| as a BeginFrameObserver so that the BeginFrameSource does
-  // not call into |this| after it's deleted.
-  SetNeedsBeginFrame(false);
-
   for (auto& child_frame_sink_id : child_frame_sinks_) {
     DCHECK(child_frame_sink_id.is_valid());
     surface_manager_->UnregisterFrameSinkHierarchy(frame_sink_id_,
@@ -52,8 +46,7 @@
   // |surface_factory_|'s resources early on.
   surface_factory_.EvictSurface();
   surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_);
-  if (handles_frame_sink_id_invalidation_)
-    surface_manager_->InvalidateFrameSinkId(frame_sink_id_);
+  surface_manager_->InvalidateFrameSinkId(frame_sink_id_);
 }
 
 void CompositorFrameSinkSupport::EvictFrame() {
@@ -69,14 +62,14 @@
     const LocalSurfaceId& local_surface_id,
     CompositorFrame frame) {
   ++ack_pending_count_;
-  if (display_) {
-    display_->SetLocalSurfaceId(local_surface_id,
-                                frame.metadata.device_scale_factor);
-  }
   surface_factory_.SubmitCompositorFrame(
       local_surface_id, std::move(frame),
       base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
                  weak_factory_.GetWeakPtr()));
+  if (display_) {
+    display_->SetLocalSurfaceId(local_surface_id,
+                                frame.metadata.device_scale_factor);
+  }
 }
 
 void CompositorFrameSinkSupport::Require(const LocalSurfaceId& local_surface_id,
@@ -119,10 +112,6 @@
   child_frame_sinks_.erase(it);
 }
 
-void CompositorFrameSinkSupport::ForceReclaimResources() {
-  surface_factory_.ClearSurface();
-}
-
 void CompositorFrameSinkSupport::DisplayOutputSurfaceLost() {}
 
 void CompositorFrameSinkSupport::DisplayWillDrawAndSwap(
diff --git a/cc/surfaces/compositor_frame_sink_support.h b/cc/surfaces/compositor_frame_sink_support.h
index eb63791e..8471bbd 100644
--- a/cc/surfaces/compositor_frame_sink_support.h
+++ b/cc/surfaces/compositor_frame_sink_support.h
@@ -26,16 +26,12 @@
       public SurfaceFactoryClient,
       public BeginFrameObserver {
  public:
-  // |display| is nullptr if the CompositorFrameSinkSupport submits
-  // CompositorFrames to a offscreen texutre/bitmap instead of a
-  // DisplayCompositor. e.g. OffscreenCanvasCompositorFrameSink and
-  // GpuOffscreenCompositorFrameSink.
-  CompositorFrameSinkSupport(CompositorFrameSinkSupportClient* client,
-                             SurfaceManager* surface_manager,
-                             const FrameSinkId& frame_sink_id,
-                             Display* display,
-                             bool handles_frame_sink_id_invalidation,
-                             bool needs_sync_points);
+  CompositorFrameSinkSupport(
+      CompositorFrameSinkSupportClient* client,
+      SurfaceManager* surface_manager,
+      const FrameSinkId& frame_sink_id,
+      std::unique_ptr<Display> display,
+      std::unique_ptr<BeginFrameSource> display_begin_frame_source);
 
   ~CompositorFrameSinkSupport() override;
 
@@ -50,9 +46,8 @@
   void Satisfy(const SurfaceSequence& sequence);
   void AddChildFrameSink(const FrameSinkId& child_frame_sink_id);
   void RemoveChildFrameSink(const FrameSinkId& child_frame_sink_id);
-  void ForceReclaimResources();
 
-  Display* display() { return display_; }
+  Display* display() { return display_.get(); }
 
  private:
   void DidReceiveCompositorFrameAck();
@@ -79,8 +74,14 @@
   CompositorFrameSinkSupportClient* const client_;
 
   SurfaceManager* const surface_manager_;
+
   const FrameSinkId frame_sink_id_;
-  Display* const display_;
+
+  // GpuCompositorFrameSink holds a Display and its BeginFrameSource if it
+  // created with non-null gpu::SurfaceHandle. In the window server, the display
+  // root window's CompositorFrameSink will have a valid gpu::SurfaceHandle.
+  std::unique_ptr<BeginFrameSource> display_begin_frame_source_;
+  std::unique_ptr<Display> display_;
 
   SurfaceFactory surface_factory_;
   // Counts the number of CompositorFrames that have been submitted and have not
@@ -100,18 +101,6 @@
   // Whether or not a frame observer has been added.
   bool added_frame_observer_ = false;
 
-  // TODO(staraz): Remove this flag once ui::Compositor no longer needs
-  // RegisterFrameSinkId().
-  // A SurfaceSequence's validity is bound to the lifetime of the parent
-  // FrameSink that created it. We track the lifetime of FrameSink's through
-  // RegisterFrameSinkId and InvalidateFrameSink. During startup and GPU
-  // restart, a SurfaceSequence created by the top most layer compositor may be
-  // used prior to the creation of the associated CompositorFrameSinkSupport.
-  // CompositorFrameSinkSupport is created asynchronously when a new GPU channel
-  // is established. Once we switch to SurfaceReferences, this ordering concern
-  // goes away and we can remove this bool.
-  const bool handles_frame_sink_id_invalidation_;
-
   // The set of BeginFrame children of this CompositorFrameSink.
   std::unordered_set<FrameSinkId, FrameSinkIdHash> child_frame_sinks_;
 
diff --git a/cc/surfaces/direct_compositor_frame_sink.cc b/cc/surfaces/direct_compositor_frame_sink.cc
index 1fa4d8d..10c37ee7 100644
--- a/cc/surfaces/direct_compositor_frame_sink.cc
+++ b/cc/surfaces/direct_compositor_frame_sink.cc
@@ -29,12 +29,14 @@
                           shared_bitmap_manager),
       frame_sink_id_(frame_sink_id),
       surface_manager_(surface_manager),
-      display_(display) {
+      display_(display),
+      factory_(frame_sink_id, surface_manager, this) {
   DCHECK(thread_checker_.CalledOnValidThread());
   capabilities_.can_force_reclaim_resources = true;
   // Display and DirectCompositorFrameSink share a GL context, so sync
   // points aren't needed when passing resources between them.
   capabilities_.delegated_sync_points_required = false;
+  factory_.set_needs_sync_points(false);
 }
 
 DirectCompositorFrameSink::DirectCompositorFrameSink(
@@ -45,7 +47,8 @@
     : CompositorFrameSink(std::move(vulkan_context_provider)),
       frame_sink_id_(frame_sink_id),
       surface_manager_(surface_manager),
-      display_(display) {
+      display_(display),
+      factory_(frame_sink_id_, surface_manager, this) {
   DCHECK(thread_checker_.CalledOnValidThread());
   capabilities_.can_force_reclaim_resources = true;
 }
@@ -61,28 +64,26 @@
   if (!CompositorFrameSink::BindToClient(client))
     return false;
 
+  surface_manager_->RegisterSurfaceFactoryClient(frame_sink_id_, this);
+
   // We want the Display's output surface to hear about lost context, and since
   // this shares a context with it, we should not be listening for lost context
   // callbacks on the context here.
   if (auto* cp = context_provider())
     cp->SetLostContextCallback(base::Closure());
 
-  support_ = base::MakeUnique<CompositorFrameSinkSupport>(
-      this, surface_manager_, frame_sink_id_, display_, false,
-      capabilities_.delegated_sync_points_required);
-
-  begin_frame_source_ = base::MakeUnique<ExternalBeginFrameSource>(this);
-  client_->SetBeginFrameSource(begin_frame_source_.get());
   // Avoid initializing GL context here, as this should be sharing the
   // Display's context.
-
+  display_->Initialize(this, surface_manager_);
   return true;
 }
 
 void DirectCompositorFrameSink::DetachFromClient() {
-  client_->SetBeginFrameSource(nullptr);
-  begin_frame_source_.reset();
-  support_.reset();
+  // Unregister the SurfaceFactoryClient here instead of the dtor so that only
+  // one client is alive for this namespace at any given time.
+  surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_);
+  factory_.EvictSurface();
+
   CompositorFrameSink::DetachFromClient();
 }
 
@@ -92,12 +93,30 @@
     delegated_local_surface_id_ = surface_id_allocator_.GenerateId();
     last_swap_frame_size_ = frame_size;
   }
-  support_->SubmitCompositorFrame(delegated_local_surface_id_,
-                                  std::move(frame));
+  display_->SetLocalSurfaceId(delegated_local_surface_id_,
+                              frame.metadata.device_scale_factor);
+
+  factory_.SubmitCompositorFrame(
+      delegated_local_surface_id_, std::move(frame),
+      base::Bind(&DirectCompositorFrameSink::DidDrawCallback,
+                 base::Unretained(this)));
 }
 
 void DirectCompositorFrameSink::ForceReclaimResources() {
-  support_->ForceReclaimResources();
+  if (delegated_local_surface_id_.is_valid())
+    factory_.ClearSurface();
+}
+
+void DirectCompositorFrameSink::ReturnResources(
+    const ReturnedResourceArray& resources) {
+  if (client_)
+    client_->ReclaimResources(resources);
+}
+
+void DirectCompositorFrameSink::SetBeginFrameSource(
+    BeginFrameSource* begin_frame_source) {
+  DCHECK(client_);
+  client_->SetBeginFrameSource(begin_frame_source);
 }
 
 void DirectCompositorFrameSink::DisplayOutputSurfaceLost() {
@@ -117,29 +136,8 @@
   // be drawn.
 }
 
-void DirectCompositorFrameSink::DidReceiveCompositorFrameAck() {
-  client_->DidReceiveCompositorFrameAck();
-}
-
-void DirectCompositorFrameSink::OnBeginFrame(const BeginFrameArgs& args) {
-  begin_frame_source_->OnBeginFrame(args);
-}
-
-void DirectCompositorFrameSink::ReclaimResources(
-    const ReturnedResourceArray& resources) {
-  client_->ReclaimResources(resources);
-}
-
-void DirectCompositorFrameSink::WillDrawSurface() {
-  // TODO(staraz): Implement this.
-}
-
 void DirectCompositorFrameSink::DidDrawCallback() {
   client_->DidReceiveCompositorFrameAck();
 }
 
-void DirectCompositorFrameSink::OnNeedsBeginFrames(bool needs_begin_frame) {
-  support_->SetNeedsBeginFrame(needs_begin_frame);
-}
-
 }  // namespace cc
diff --git a/cc/surfaces/direct_compositor_frame_sink.h b/cc/surfaces/direct_compositor_frame_sink.h
index db0a009..609f381 100644
--- a/cc/surfaces/direct_compositor_frame_sink.h
+++ b/cc/surfaces/direct_compositor_frame_sink.h
@@ -8,8 +8,6 @@
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
 #include "cc/output/compositor_frame_sink.h"
-#include "cc/surfaces/compositor_frame_sink_support.h"
-#include "cc/surfaces/compositor_frame_sink_support_client.h"
 #include "cc/surfaces/display_client.h"
 #include "cc/surfaces/surface_factory.h"
 #include "cc/surfaces/surface_factory_client.h"
@@ -25,9 +23,8 @@
 // client's frame being the root surface of the Display.
 class CC_SURFACES_EXPORT DirectCompositorFrameSink
     : public CompositorFrameSink,
-      public NON_EXPORTED_BASE(DisplayClient),
-      public CompositorFrameSinkSupportClient,
-      public ExternalBeginFrameSourceClient {
+      public SurfaceFactoryClient,
+      public NON_EXPORTED_BASE(DisplayClient) {
  public:
   // The underlying Display, SurfaceManager, and SurfaceIdAllocator must outlive
   // this class.
@@ -52,36 +49,30 @@
   void SubmitCompositorFrame(CompositorFrame frame) override;
   void ForceReclaimResources() override;
 
+  // SurfaceFactoryClient implementation.
+  void ReturnResources(const ReturnedResourceArray& resources) override;
+  void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override;
+
   // DisplayClient implementation.
   void DisplayOutputSurfaceLost() override;
   void DisplayWillDrawAndSwap(bool will_draw_and_swap,
                               const RenderPassList& render_passes) override;
   void DisplayDidDrawAndSwap() override;
 
-  // CompositorFrameSinkSupportClient implementation:
-  void DidReceiveCompositorFrameAck() override;
-  void OnBeginFrame(const BeginFrameArgs& args) override;
-  void ReclaimResources(const ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
-
  private:
   void DidDrawCallback();
 
-  // ExternalBeginFrameSouceClient implementation:
-  void OnNeedsBeginFrames(bool needs_begin_frames) override;
-
   // This class is only meant to be used on a single thread.
   base::ThreadChecker thread_checker_;
 
   const FrameSinkId frame_sink_id_;
   LocalSurfaceId delegated_local_surface_id_;
-  SurfaceIdAllocator surface_id_allocator_;
   SurfaceManager* surface_manager_;
+  SurfaceIdAllocator surface_id_allocator_;
   Display* display_;
+  SurfaceFactory factory_;
   gfx::Size last_swap_frame_size_;
   bool is_lost_ = false;
-  std::unique_ptr<CompositorFrameSinkSupport> support_;
-  std::unique_ptr<ExternalBeginFrameSource> begin_frame_source_;
 
   DISALLOW_COPY_AND_ASSIGN(DirectCompositorFrameSink);
 };
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc
index 735c2288..5136fc5 100644
--- a/cc/surfaces/display.cc
+++ b/cc/surfaces/display.cc
@@ -219,7 +219,7 @@
 
 void Display::UpdateRootSurfaceResourcesLocked() {
   Surface* surface = surface_manager_->GetSurfaceForId(current_surface_id_);
-  bool root_surface_resources_locked = !surface || !surface->HasFrame();
+  bool root_surface_resources_locked = !surface || !surface->HasActiveFrame();
   if (scheduler_)
     scheduler_->SetRootSurfaceResourcesLocked(root_surface_resources_locked);
 }
@@ -374,8 +374,8 @@
       aggregator_->previous_contained_surfaces().count(surface_id)) {
     Surface* surface = surface_manager_->GetSurfaceForId(surface_id);
     if (surface) {
-      if (!surface->HasFrame() ||
-          surface->GetEligibleFrame().resource_list.empty()) {
+      if (!surface->HasActiveFrame() ||
+          surface->GetActiveFrame().resource_list.empty()) {
         aggregator_->ReleaseResources(surface_id);
       }
     }
diff --git a/cc/surfaces/local_surface_id.h b/cc/surfaces/local_surface_id.h
index ef8be59..138bfa64 100644
--- a/cc/surfaces/local_surface_id.h
+++ b/cc/surfaces/local_surface_id.h
@@ -53,6 +53,7 @@
   }
 
   size_t hash() const {
+    DCHECK(is_valid()) << ToString();
     return base::HashInts(
         local_id_, static_cast<uint64_t>(base::UnguessableTokenHash()(nonce_)));
   }
diff --git a/cc/surfaces/pending_frame_observer.h b/cc/surfaces/pending_frame_observer.h
new file mode 100644
index 0000000..ec7acab
--- /dev/null
+++ b/cc/surfaces/pending_frame_observer.h
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_SURFACES_PENDING_FRAME_OBSERVER_H_
+#define CC_SURFACES_PENDING_FRAME_OBSERVER_H_
+
+#include "base/containers/flat_set.h"
+#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surfaces_export.h"
+
+namespace cc {
+
+using SurfaceDependencies = base::flat_set<SurfaceId>;
+
+class Surface;
+
+// Clients that wish to observe when the state of a pending CompostiorFrame
+// changes should implement this class.
+class CC_SURFACES_EXPORT PendingFrameObserver {
+ public:
+  // Called when a CompositorFrame within |surface| has activated.
+  virtual void OnSurfaceActivated(Surface* surface) = 0;
+
+  // Called when the dependencies of a pending CompositorFrame within |surface|
+  // have changed.
+  virtual void OnSurfaceDependenciesChanged(
+      Surface* surface,
+      const SurfaceDependencies& added_dependencies,
+      const SurfaceDependencies& removed_dependencies) = 0;
+
+  // Called when |surface| is being destroyed.
+  virtual void OnSurfaceDiscarded(Surface* surface) = 0;
+
+ protected:
+  virtual ~PendingFrameObserver() = default;
+};
+
+}  // namespace cc
+
+#endif  // CC_SURFACES_PENDING_FRAME_OBSERVER_H_
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index dd41c3d..57e3a3c9 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -12,6 +12,7 @@
 #include "cc/base/container_util.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/copy_output_request.h"
+#include "cc/surfaces/pending_frame_observer.h"
 #include "cc/surfaces/surface_factory.h"
 #include "cc/surfaces/surface_id_allocator.h"
 #include "cc/surfaces/surface_manager.h"
@@ -31,11 +32,18 @@
 
 Surface::~Surface() {
   ClearCopyRequests();
-  if (current_frame_ && factory_) {
-    UnrefFrameResources(*current_frame_);
+  if (factory_) {
+    if (pending_frame_)
+      UnrefFrameResources(*pending_frame_);
+    if (active_frame_)
+      UnrefFrameResources(*active_frame_);
   }
   if (!draw_callback_.is_null())
     draw_callback_.Run();
+
+  for (auto& observer : observers_)
+    observer.OnSurfaceDiscarded(this);
+  observers_.Clear();
 }
 
 void Surface::SetPreviousFrameSurface(Surface* surface) {
@@ -45,94 +53,221 @@
 }
 
 void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) {
+  base::Optional<CompositorFrame> previous_pending_frame =
+      std::move(pending_frame_);
+  pending_frame_.reset();
+
+  UpdateBlockingSurfaces(previous_pending_frame, frame);
+
+  if (!blocking_surfaces_.empty()) {
+    pending_frame_ = std::move(frame);
+    if (pending_frame_) {
+      factory_->ReceiveFromChild(pending_frame_->resource_list);
+      // Ask the surface manager to inform |this| when its dependencies are
+      // resolved.
+      factory_->manager()->RequestSurfaceResolution(this);
+    }
+  } else {
+    // If there are no blockers, then immediately activate the frame.
+    ActivateFrame(std::move(frame));
+  }
+
+  // Returns resources for the previous pending frame.
+  if (previous_pending_frame)
+    UnrefFrameResources(*previous_pending_frame);
+
+  if (!draw_callback_.is_null())
+    draw_callback_.Run();
+  draw_callback_ = callback;
+}
+
+void Surface::EvictFrame() {
+  QueueFrame(CompositorFrame(), DrawCallback());
+  active_frame_.reset();
+}
+
+void Surface::RequestCopyOfOutput(
+    std::unique_ptr<CopyOutputRequest> copy_request) {
+  if (!active_frame_ || active_frame_->render_pass_list.empty()) {
+    copy_request->SendEmptyResult();
+    return;
+  }
+
+  std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
+      active_frame_->render_pass_list.back()->copy_requests;
+
+  if (copy_request->has_source()) {
+    const base::UnguessableToken& source = copy_request->source();
+    // Remove existing CopyOutputRequests made on the Surface by the same
+    // source.
+    auto to_remove =
+        std::remove_if(copy_requests.begin(), copy_requests.end(),
+                       [&source](const std::unique_ptr<CopyOutputRequest>& x) {
+                         return x->has_source() && x->source() == source;
+                       });
+    copy_requests.erase(to_remove, copy_requests.end());
+  }
+  copy_requests.push_back(std::move(copy_request));
+}
+
+void Surface::NotifySurfaceIdAvailable(const SurfaceId& surface_id) {
+  auto it = blocking_surfaces_.find(surface_id);
+  // This surface may no longer have blockers if the deadline has passed.
+  if (it == blocking_surfaces_.end())
+    return;
+
+  blocking_surfaces_.erase(it);
+
+  if (!blocking_surfaces_.empty())
+    return;
+
+  // All blockers have been cleared. The surface can be activated now.
+  ActivatePendingFrame();
+}
+
+void Surface::AddObserver(PendingFrameObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void Surface::RemoveObserver(PendingFrameObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void Surface::ActivatePendingFrameForDeadline() {
+  if (!pending_frame_ ||
+      !pending_frame_->metadata.can_activate_before_dependencies) {
+    return;
+  }
+
+  // If a frame is being activated because of a deadline, then clear its set
+  // of blockers.
+  blocking_surfaces_.clear();
+  ActivatePendingFrame();
+}
+
+void Surface::ActivatePendingFrame() {
+  DCHECK(pending_frame_);
+  ActivateFrame(std::move(pending_frame_.value()));
+  pending_frame_.reset();
+  // ActiveFrame resources are now double ref-ed. Unref.
+  UnrefFrameResources(*active_frame_);
+}
+
+// A frame is activated if all its Surface ID dependences are active or a
+// deadline has hit and the frame was forcibly activated by the display
+// compositor.
+void Surface::ActivateFrame(CompositorFrame frame) {
   DCHECK(factory_);
   ClearCopyRequests();
 
   TakeLatencyInfo(&frame.metadata.latency_info);
 
-  base::Optional<CompositorFrame> previous_frame = std::move(current_frame_);
-  current_frame_ = std::move(frame);
+  base::Optional<CompositorFrame> previous_frame = std::move(active_frame_);
+  active_frame_ = std::move(frame);
 
-  if (current_frame_) {
-    factory_->ReceiveFromChild(current_frame_->resource_list);
-  }
+  factory_->ReceiveFromChild(active_frame_->resource_list);
 
   // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't
   // increment frame index for them.
-  if (current_frame_ && !current_frame_->render_pass_list.empty()) {
+  if (!active_frame_->render_pass_list.empty())
     ++frame_index_;
-  }
 
   previous_frame_surface_id_ = surface_id();
 
   if (previous_frame)
     UnrefFrameResources(*previous_frame);
 
-  if (!draw_callback_.is_null())
-    draw_callback_.Run();
-  draw_callback_ = callback;
+  referenced_surfaces_ = active_frame_->metadata.referenced_surfaces;
 
-  referenced_surfaces_ = current_frame_->metadata.referenced_surfaces;
+  for (auto& observer : observers_)
+    observer.OnSurfaceActivated(this);
 }
 
-void Surface::EvictFrame() {
-  QueueFrame(CompositorFrame(), DrawCallback());
-  current_frame_.reset();
-}
-
-void Surface::RequestCopyOfOutput(
-    std::unique_ptr<CopyOutputRequest> copy_request) {
-  if (current_frame_ && !current_frame_->render_pass_list.empty()) {
-    std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
-        current_frame_->render_pass_list.back()->copy_requests;
-
-    if (copy_request->has_source()) {
-      const base::UnguessableToken& source = copy_request->source();
-      // Remove existing CopyOutputRequests made on the Surface by the same
-      // source.
-      auto to_remove = std::remove_if(
-          copy_requests.begin(), copy_requests.end(),
-          [&source](const std::unique_ptr<CopyOutputRequest>& x) {
-            return x->has_source() && x->source() == source;
-          });
-      copy_requests.erase(to_remove, copy_requests.end());
-    }
-    copy_requests.push_back(std::move(copy_request));
-  } else {
-    copy_request->SendEmptyResult();
+void Surface::UpdateBlockingSurfaces(
+    const base::Optional<CompositorFrame>& previous_pending_frame,
+    const CompositorFrame& current_frame) {
+  // If there is no SurfaceDependencyTracker installed then the |current_frame|
+  // does not block on anything.
+  if (!factory_->manager()->dependency_tracker()) {
+    blocking_surfaces_.clear();
+    return;
   }
+
+  base::flat_set<SurfaceId> new_blocking_surfaces;
+
+  for (const SurfaceId& surface_id :
+       current_frame.metadata.referenced_surfaces) {
+    Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
+    // If a referenced surface does not have a corresponding active frame in the
+    // display compositor, then it blocks this frame.
+    if (!surface || !surface->HasActiveFrame())
+      new_blocking_surfaces.insert(surface_id);
+  }
+
+  // If this Surface has a previous pending frame, then we must determine the
+  // changes in dependencies so that we can update the SurfaceDependencyTracker
+  // map.
+  if (previous_pending_frame.has_value()) {
+    SurfaceDependencies removed_dependencies;
+    for (const SurfaceId& surface_id : blocking_surfaces_) {
+      if (!new_blocking_surfaces.count(surface_id))
+        removed_dependencies.insert(surface_id);
+    }
+
+    SurfaceDependencies added_dependencies;
+    for (const SurfaceId& surface_id : new_blocking_surfaces) {
+      if (!blocking_surfaces_.count(surface_id))
+        added_dependencies.insert(surface_id);
+    }
+
+    // If there is a change in the dependency set, then inform observers.
+    if (!added_dependencies.empty() || !removed_dependencies.empty()) {
+      for (auto& observer : observers_) {
+        observer.OnSurfaceDependenciesChanged(this, added_dependencies,
+                                              removed_dependencies);
+      }
+    }
+  }
+
+  blocking_surfaces_ = std::move(new_blocking_surfaces);
 }
 
 void Surface::TakeCopyOutputRequests(
     std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) {
   DCHECK(copy_requests->empty());
-  if (current_frame_) {
-    for (const auto& render_pass : current_frame_->render_pass_list) {
-      for (auto& request : render_pass->copy_requests) {
-        copy_requests->insert(
-            std::make_pair(render_pass->id, std::move(request)));
-      }
-      render_pass->copy_requests.clear();
+  if (!active_frame_)
+    return;
+
+  for (const auto& render_pass : active_frame_->render_pass_list) {
+    for (auto& request : render_pass->copy_requests) {
+      copy_requests->insert(
+          std::make_pair(render_pass->id, std::move(request)));
     }
+    render_pass->copy_requests.clear();
   }
 }
 
-const CompositorFrame& Surface::GetEligibleFrame() const {
-  DCHECK(current_frame_);
-  return current_frame_.value();
+const CompositorFrame& Surface::GetActiveFrame() const {
+  DCHECK(active_frame_);
+  return active_frame_.value();
+}
+
+const CompositorFrame& Surface::GetPendingFrame() {
+  DCHECK(pending_frame_);
+  return pending_frame_.value();
 }
 
 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) {
-  if (!current_frame_)
+  if (!active_frame_)
     return;
   if (latency_info->empty()) {
-    current_frame_->metadata.latency_info.swap(*latency_info);
+    active_frame_->metadata.latency_info.swap(*latency_info);
     return;
   }
-  std::copy(current_frame_->metadata.latency_info.begin(),
-            current_frame_->metadata.latency_info.end(),
+  std::copy(active_frame_->metadata.latency_info.begin(),
+            active_frame_->metadata.latency_info.end(),
             std::back_inserter(*latency_info));
-  current_frame_->metadata.latency_info.clear();
+  active_frame_->metadata.latency_info.clear();
 }
 
 void Surface::RunDrawCallbacks() {
@@ -170,8 +305,8 @@
 }
 
 void Surface::ClearCopyRequests() {
-  if (current_frame_) {
-    for (const auto& render_pass : current_frame_->render_pass_list) {
+  if (active_frame_) {
+    for (const auto& render_pass : active_frame_->render_pass_list) {
       for (const auto& copy_request : render_pass->copy_requests)
         copy_request->SendEmptyResult();
     }
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h
index 0ac97a1..0e74e16e 100644
--- a/cc/surfaces/surface.h
+++ b/cc/surfaces/surface.h
@@ -20,6 +20,7 @@
 #include "base/optional.h"
 #include "cc/output/copy_output_request.h"
 #include "cc/surfaces/frame_sink_id.h"
+#include "cc/surfaces/pending_frame_observer.h"
 #include "cc/surfaces/surface_factory.h"
 #include "cc/surfaces/surface_id.h"
 #include "cc/surfaces/surface_sequence.h"
@@ -54,14 +55,30 @@
   void QueueFrame(CompositorFrame frame, const DrawCallback& draw_callback);
   void EvictFrame();
   void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> copy_request);
+
+  // Notifies the Surface that a blocking SurfaceId now has an active frame.
+  void NotifySurfaceIdAvailable(const SurfaceId& surface_id);
+
+  void AddObserver(PendingFrameObserver* observer);
+  void RemoveObserver(PendingFrameObserver* observer);
+
+  // Called if a deadline has been hit and this surface is not yet active but
+  // it's marked as respecting deadlines.
+  void ActivatePendingFrameForDeadline();
+
   // Adds each CopyOutputRequest in the current frame to copy_requests. The
   // caller takes ownership of them. |copy_requests| is keyed by RenderPass ids.
   void TakeCopyOutputRequests(
       std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests);
 
   // Returns the most recent frame that is eligible to be rendered.
-  // You must check whether HasFrame() returns true before calling this method.
-  const CompositorFrame& GetEligibleFrame() const;
+  // You must check whether HasActiveFrame() returns true before calling this
+  // method.
+  const CompositorFrame& GetActiveFrame() const;
+
+  // Returns the currently pending frame. You must check where HasPendingFrame()
+  // returns true before calling this method.
+  const CompositorFrame& GetPendingFrame();
 
   // Returns a number that increments by 1 every time a new frame is enqueued.
   int frame_index() const { return frame_index_; }
@@ -88,12 +105,20 @@
     return referenced_surfaces_;
   }
 
-  bool HasFrame() const { return current_frame_.has_value(); }
+  bool HasActiveFrame() const { return active_frame_.has_value(); }
+  bool HasPendingFrame() const { return pending_frame_.has_value(); }
 
   bool destroyed() const { return destroyed_; }
   void set_destroyed(bool destroyed) { destroyed_ = destroyed; }
 
  private:
+  void ActivatePendingFrame();
+  // Called when all of the surface's dependencies have been resolved.
+  void ActivateFrame(CompositorFrame frame);
+  void UpdateBlockingSurfaces(
+      const base::Optional<CompositorFrame>& previous_pending_frame,
+      const CompositorFrame& current_frame);
+
   void UnrefFrameResources(const CompositorFrame& frame_data);
   void ClearCopyRequests();
 
@@ -101,7 +126,8 @@
   SurfaceId previous_frame_surface_id_;
   base::WeakPtr<SurfaceFactory> factory_;
   // TODO(jamesr): Support multiple frames in flight.
-  base::Optional<CompositorFrame> current_frame_;
+  base::Optional<CompositorFrame> pending_frame_;
+  base::Optional<CompositorFrame> active_frame_;
   int frame_index_;
   bool destroyed_;
   std::vector<SurfaceSequence> destruction_dependencies_;
@@ -112,11 +138,16 @@
 
   std::vector<SurfaceId> referenced_surfaces_;
 
+  SurfaceDependencies blocking_surfaces_;
+  base::ObserverList<PendingFrameObserver, true> observers_;
+
   DrawCallback draw_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(Surface);
 };
 
+using PendingSurfaceSet = base::flat_set<Surface*>;
+
 }  // namespace cc
 
 #endif  // CC_SURFACES_SURFACE_H_
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index 21e85ca..82bc500 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -168,9 +168,9 @@
   Surface* surface = manager_->GetSurfaceForId(surface_id);
   if (!surface)
     return;
-  if (!surface->HasFrame())
+  if (!surface->HasActiveFrame())
     return;
-  const CompositorFrame& frame = surface->GetEligibleFrame();
+  const CompositorFrame& frame = surface->GetActiveFrame();
 
   // A map keyed by RenderPass id.
   std::multimap<int, std::unique_ptr<CopyOutputRequest>> copy_requests;
@@ -536,9 +536,9 @@
     return gfx::Rect();
   }
   contained_surfaces_[surface_id] = surface->frame_index();
-  if (!surface->HasFrame())
+  if (!surface->HasActiveFrame())
     return gfx::Rect();
-  const CompositorFrame& frame = surface->GetEligibleFrame();
+  const CompositorFrame& frame = surface->GetActiveFrame();
   int child_id = 0;
   // TODO(jbauman): hack for unit tests that don't set up rp
   if (provider_) {
@@ -719,9 +719,9 @@
     Surface* surface = manager_->GetSurfaceForId(surface_id);
     if (!surface)
       continue;
-    if (!surface->HasFrame())
+    if (!surface->HasActiveFrame())
       continue;
-    const CompositorFrame& frame = surface->GetEligibleFrame();
+    const CompositorFrame& frame = surface->GetActiveFrame();
     bool surface_has_copy_requests = false;
     for (const auto& render_pass : frame.render_pass_list) {
       surface_has_copy_requests |= !render_pass->copy_requests.empty();
@@ -769,10 +769,10 @@
   DCHECK(surface);
   contained_surfaces_[surface_id] = surface->frame_index();
 
-  if (!surface->HasFrame())
+  if (!surface->HasActiveFrame())
     return CompositorFrame();
 
-  const CompositorFrame& root_surface_frame = surface->GetEligibleFrame();
+  const CompositorFrame& root_surface_frame = surface->GetActiveFrame();
   TRACE_EVENT0("cc", "SurfaceAggregator::Aggregate");
 
   CompositorFrame frame;
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index a4227f9..788e52e 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -474,7 +474,7 @@
 
   // Ensure copy requests have been removed from root surface.
   const CompositorFrame& original_frame =
-      manager_.GetSurfaceForId(root_surface_id)->GetEligibleFrame();
+      manager_.GetSurfaceForId(root_surface_id)->GetActiveFrame();
   const RenderPassList& original_pass_list = original_frame.render_pass_list;
   ASSERT_EQ(2u, original_pass_list.size());
   DCHECK(original_pass_list[0]->copy_requests.empty());
diff --git a/cc/surfaces/surface_dependency_tracker.cc b/cc/surfaces/surface_dependency_tracker.cc
new file mode 100644
index 0000000..934586b
--- /dev/null
+++ b/cc/surfaces/surface_dependency_tracker.cc
@@ -0,0 +1,180 @@
+// 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 "cc/surfaces/surface_dependency_tracker.h"
+
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_info.h"
+#include "cc/surfaces/surface_manager.h"
+
+namespace cc {
+
+namespace {
+constexpr uint32_t kMaxBeginFrameCount = 4;
+}
+
+SurfaceDependencyTracker::SurfaceDependencyTracker(
+    SurfaceManager* surface_manager,
+    BeginFrameSource* begin_frame_source)
+    : surface_manager_(surface_manager),
+      begin_frame_source_(begin_frame_source) {
+  surface_manager_->AddObserver(this);
+  begin_frame_source_->AddObserver(this);
+}
+
+SurfaceDependencyTracker::~SurfaceDependencyTracker() {
+  surface_manager_->RemoveObserver(this);
+  begin_frame_source_->RemoveObserver(this);
+}
+
+void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
+  DCHECK(surface->HasPendingFrame());
+
+  const CompositorFrame& pending_frame = surface->GetPendingFrame();
+  bool needs_begin_frame =
+      pending_frame.metadata.can_activate_before_dependencies;
+
+  // Referenced surface IDs that aren't currently known to the surface manager
+  // or do not have an active CompsotiorFrame block this frame.
+  for (const SurfaceId& surface_id :
+       pending_frame.metadata.referenced_surfaces) {
+    Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id);
+    if (!surface_dependency || !surface_dependency->HasActiveFrame())
+      blocked_surfaces_[surface_id].insert(surface);
+  }
+
+  if (!pending_surfaces_.count(surface)) {
+    surface->AddObserver(this);
+    pending_surfaces_.insert(surface);
+  }
+
+  if (needs_begin_frame && !frames_since_deadline_set_)
+    frames_since_deadline_set_ = 0;
+}
+
+void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) {
+  // If no deadline is set then we have nothing to do.
+  if (!frames_since_deadline_set_)
+    return;
+
+  // TODO(fsamuel, kylechar): We have a single global deadline here. We should
+  // scope deadlines to surface subtrees. We cannot do that until
+  // SurfaceReferences have been fully implemented
+  // (see https://crbug.com/689719).
+  last_begin_frame_args_ = args;
+  // Nothing to do if we haven't hit a deadline yet.
+  if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount)
+    return;
+
+  // Activate all surfaces that respect the deadline.
+  PendingSurfaceSet pending_surfaces(pending_surfaces_);
+  for (Surface* pending_surface : pending_surfaces)
+    pending_surface->ActivatePendingFrameForDeadline();
+
+  frames_since_deadline_set_.reset();
+}
+
+const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const {
+  return last_begin_frame_args_;
+}
+
+void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {}
+
+void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) {
+  // If the surface being destroyed doesn't have a pending frame then we have
+  // nothing to do here.
+  if (!surface->HasPendingFrame())
+    return;
+
+  const CompositorFrame& pending_frame = surface->GetPendingFrame();
+
+  DCHECK(!pending_frame.metadata.referenced_surfaces.empty());
+
+  for (const SurfaceId& surface_id :
+       pending_frame.metadata.referenced_surfaces) {
+    auto it = blocked_surfaces_.find(surface_id);
+    if (it == blocked_surfaces_.end())
+      continue;
+
+    auto& pending_surface_set = it->second;
+    auto pending_surface_it = pending_surface_set.find(surface);
+    if (pending_surface_it != pending_surface_set.end()) {
+      pending_surface_set.erase(surface);
+      if (pending_surface_set.empty())
+        blocked_surfaces_.erase(surface_id);
+    }
+  }
+
+  if (blocked_surfaces_.empty())
+    frames_since_deadline_set_.reset();
+
+  pending_surfaces_.erase(surface);
+  surface->RemoveObserver(this);
+
+  // TODO(fsamuel): We should consider removing this surface as a dependency on
+  // other surfaces. This dependency will be removed when the deadline hits
+  // anyway but maybe we should try to actiate these frames early (see
+  // https://crbug.com/689725).
+}
+
+void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) {
+  surface->RemoveObserver(this);
+  pending_surfaces_.erase(surface);
+  NotifySurfaceIdAvailable(surface->surface_id());
+}
+
+void SurfaceDependencyTracker::OnSurfaceDependenciesChanged(
+    Surface* surface,
+    const SurfaceDependencies& added_dependencies,
+    const SurfaceDependencies& removed_dependencies) {
+  // Update the |blocked_surfaces_| map with the changes in dependencies.
+  for (const SurfaceId& surface_id : added_dependencies)
+    blocked_surfaces_[surface_id].insert(surface);
+
+  for (const SurfaceId& surface_id : removed_dependencies) {
+    auto it = blocked_surfaces_.find(surface_id);
+    it->second.erase(surface);
+    if (it->second.empty())
+      blocked_surfaces_.erase(it);
+  }
+
+  // If there are no more dependencies to resolve then we don't need to have a
+  // deadline.
+  if (blocked_surfaces_.empty())
+    frames_since_deadline_set_.reset();
+}
+
+// SurfaceObserver implementation:
+void SurfaceDependencyTracker::OnSurfaceCreated(
+    const SurfaceInfo& surface_info) {
+  // This is called when a Surface has an activated frame for the first time.
+  // SurfaceDependencyTracker only observes Surfaces that contain pending
+  // frames. SurfaceDependencyTracker becomes aware of CompositorFrames that
+  // activate immediately go through here.
+  NotifySurfaceIdAvailable(surface_info.id());
+}
+
+void SurfaceDependencyTracker::OnSurfaceDamaged(const SurfaceId& surface_id,
+                                                bool* changed) {}
+
+void SurfaceDependencyTracker::NotifySurfaceIdAvailable(
+    const SurfaceId& surface_id) {
+  auto it = blocked_surfaces_.find(surface_id);
+  if (it == blocked_surfaces_.end())
+    return;
+
+  // Unblock surfaces that depend on this |surface_id|.
+  PendingSurfaceSet blocked_pending_surface_set(it->second);
+  blocked_surfaces_.erase(it);
+  // If there are no more blockers in the system, then we no longer need to
+  // have a deadline.
+  if (blocked_surfaces_.empty())
+    frames_since_deadline_set_.reset();
+
+  // Tell each surface about the availability of its blocker.
+  for (Surface* blocked_pending_surface : blocked_pending_surface_set)
+    blocked_pending_surface->NotifySurfaceIdAvailable(surface_id);
+}
+
+}  // namespace cc
diff --git a/cc/surfaces/surface_dependency_tracker.h b/cc/surfaces/surface_dependency_tracker.h
new file mode 100644
index 0000000..908a2b2
--- /dev/null
+++ b/cc/surfaces/surface_dependency_tracker.h
@@ -0,0 +1,93 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_SURFACES_SURFACE_DEPENDENCY_TRACKER_H_
+#define CC_SURFACES_SURFACE_DEPENDENCY_TRACKER_H_
+
+#include "cc/scheduler/begin_frame_source.h"
+#include "cc/surfaces/pending_frame_observer.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_observer.h"
+#include "cc/surfaces/surfaces_export.h"
+
+namespace cc {
+
+class SurfaceManager;
+
+// SurfaceDependencyTracker tracks unresolved dependencies blocking
+// CompositorFrames from activating. This class maintains a map from
+// a dependent surface ID to a set of Surfaces that have CompositorFrames
+// blocked on that surface ID. SurfaceDependencyTracker observes when
+// dependent frames activate, and informs blocked surfaces.
+//
+// When a blocking CompositorFrame is first submitted, SurfaceDependencyTracker
+// will begin listening for BeginFrames, setting a deadline some number of
+// BeginFrames in the future. If there are unresolved dependencies when the
+// deadline hits, then SurfaceDependencyTracker will clear then and activate
+// all pending CompositorFrames. Once there are no more remaining pending
+// frames, then SurfaceDependencyTracker will stop observing BeginFrames.
+// TODO(fsamuel): Deadlines should not be global. They should be scoped to a
+// surface subtree. However, that will not be possible until SurfaceReference
+// work is complete.
+class CC_SURFACES_EXPORT SurfaceDependencyTracker : public BeginFrameObserver,
+                                                    public PendingFrameObserver,
+                                                    public SurfaceObserver {
+ public:
+  SurfaceDependencyTracker(SurfaceManager* surface_manager,
+                           BeginFrameSource* begin_frame_source);
+  ~SurfaceDependencyTracker() override;
+
+  // Called when |surface| has a pending CompositorFrame and it wishes to be
+  // informed when that surface's dependencies are resolved.
+  void RequestSurfaceResolution(Surface* surface);
+
+  bool has_deadline() const { return frames_since_deadline_set_.has_value(); }
+
+  // BeginFrameObserver implementation.
+  void OnBeginFrame(const BeginFrameArgs& args) override;
+  const BeginFrameArgs& LastUsedBeginFrameArgs() const override;
+  void OnBeginFrameSourcePausedChanged(bool paused) override;
+
+  // PendingFrameObserver implementation:
+  void OnSurfaceActivated(Surface* pending_frame) override;
+  void OnSurfaceDependenciesChanged(
+      Surface* pending_frame,
+      const SurfaceDependencies& added_dependencies,
+      const SurfaceDependencies& removed_dependencies) override;
+  void OnSurfaceDiscarded(Surface* pending_frame) override;
+
+  // SurfaceObserver implementation:
+  void OnSurfaceCreated(const SurfaceInfo& surface_info) override;
+  void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) override;
+
+ private:
+  // Informs all Surfaces with pending frames blocked on the provided
+  // |surface_id| that there is now an active frame available in Surface
+  // corresponding to |surface_id|.
+  void NotifySurfaceIdAvailable(const SurfaceId& surface_id);
+
+  SurfaceManager* const surface_manager_;
+
+  // The last begin frame args generated by the begin frame source.
+  BeginFrameArgs last_begin_frame_args_;
+
+  // The BeginFrameSource used to set deadlines.
+  BeginFrameSource* const begin_frame_source_;
+
+  // The number of BeginFrames observed since a deadline was set. If
+  // base::nullopt_t then a deadline is not set.
+  base::Optional<uint32_t> frames_since_deadline_set_;
+
+  // A map from a SurfaceId to the set of Surfaces blocked on that SurfaceId.
+  std::unordered_map<SurfaceId, PendingSurfaceSet, SurfaceIdHash>
+      blocked_surfaces_;
+
+  PendingSurfaceSet pending_surfaces_;
+
+  DISALLOW_COPY_AND_ASSIGN(SurfaceDependencyTracker);
+};
+
+}  // namespace cc
+
+#endif  // CC_SURFACES_SURFACE_DEPENDENCY_TRACKER_H_
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc
index 63f9b57..907a59f 100644
--- a/cc/surfaces/surface_factory.cc
+++ b/cc/surfaces/surface_factory.cc
@@ -65,14 +65,9 @@
     surface = std::move(current_surface_);
   } else {
     surface = Create(local_surface_id);
-    gfx::Size frame_size;
-    // CompositorFrames may not be populated with a RenderPass in unit tests.
-    if (!frame.render_pass_list.empty())
-      frame_size = frame.render_pass_list.back()->output_rect.size();
-    manager_->SurfaceCreated(SurfaceInfo(
-        surface->surface_id(), frame.metadata.device_scale_factor, frame_size));
   }
   surface->QueueFrame(std::move(frame), callback);
+
   if (!manager_->SurfaceModified(SurfaceId(frame_sink_id_, local_surface_id))) {
     TRACE_EVENT_INSTANT0("cc", "Damage not visible.", TRACE_EVENT_SCOPE_THREAD);
     surface->RunDrawCallbacks();
@@ -120,15 +115,41 @@
   holder_.UnrefResources(resources);
 }
 
+void SurfaceFactory::OnSurfaceActivated(Surface* surface) {
+  DCHECK(surface->HasActiveFrame());
+  const CompositorFrame& frame = surface->GetActiveFrame();
+  // CompositorFrames might not be populated with a RenderPass in unit tests.
+  gfx::Size frame_size;
+  if (!frame.render_pass_list.empty())
+    frame_size = frame.render_pass_list.back()->output_rect.size();
+
+  // SurfaceCreated only applies for the first Surface activation. Thus,
+  // SurfaceFactory stops observing new activations after the first one.
+  manager_->SurfaceCreated(SurfaceInfo(
+      surface->surface_id(), frame.metadata.device_scale_factor, frame_size));
+  surface->RemoveObserver(this);
+}
+
+void SurfaceFactory::OnSurfaceDependenciesChanged(
+    Surface* pending_surface,
+    const SurfaceDependencies& added_dependencies,
+    const SurfaceDependencies& removed_dependencies) {}
+
+void SurfaceFactory::OnSurfaceDiscarded(Surface* pending_surface) {}
+
 std::unique_ptr<Surface> SurfaceFactory::Create(
     const LocalSurfaceId& local_surface_id) {
   auto surface = base::MakeUnique<Surface>(
       SurfaceId(frame_sink_id_, local_surface_id), weak_factory_.GetWeakPtr());
   manager_->RegisterSurface(surface.get());
+  // Observe a Surface from the time it's created until it's activated for the
+  // first time.
+  surface->AddObserver(this);
   return surface;
 }
 
 void SurfaceFactory::Destroy(std::unique_ptr<Surface> surface) {
+  surface->RemoveObserver(this);
   if (manager_)
     manager_->Destroy(std::move(surface));
 }
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h
index f77fdc4..4a9f6af 100644
--- a/cc/surfaces/surface_factory.h
+++ b/cc/surfaces/surface_factory.h
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "cc/output/compositor_frame.h"
+#include "cc/surfaces/pending_frame_observer.h"
 #include "cc/surfaces/surface_id.h"
 #include "cc/surfaces/surface_resource_holder.h"
 #include "cc/surfaces/surface_sequence.h"
@@ -32,14 +33,14 @@
 // particular factory will be returned to that factory's client when they are no
 // longer being used. This is the only class most users of surfaces will need to
 // directly interact with.
-class CC_SURFACES_EXPORT SurfaceFactory {
+class CC_SURFACES_EXPORT SurfaceFactory : public PendingFrameObserver {
  public:
   using DrawCallback = base::Callback<void()>;
 
   SurfaceFactory(const FrameSinkId& frame_sink_id,
                  SurfaceManager* manager,
                  SurfaceFactoryClient* client);
-  ~SurfaceFactory();
+  ~SurfaceFactory() override;
 
   const FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
 
@@ -78,6 +79,8 @@
 
   SurfaceManager* manager() { return manager_; }
 
+  Surface* current_surface_for_testing() { return current_surface_.get(); }
+
   // This can be set to false if resources from this SurfaceFactory don't need
   // to have sync points set on them when returned from the Display, for
   // example if the Display shares a context with the creator.
@@ -89,6 +92,14 @@
   void DidDestroySurfaceManager() { manager_ = nullptr; }
 
  private:
+  // PendingFrameObserver implementation.
+  void OnSurfaceActivated(Surface* pending_surface) override;
+  void OnSurfaceDependenciesChanged(
+      Surface* pending_surface,
+      const SurfaceDependencies& added_dependencies,
+      const SurfaceDependencies& removed_dependencies) override;
+  void OnSurfaceDiscarded(Surface* pending_surface) override;
+
   std::unique_ptr<Surface> Create(const LocalSurfaceId& local_surface_id);
   void Destroy(std::unique_ptr<Surface> surface);
 
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
index d7385ab..28c8042 100644
--- a/cc/surfaces/surface_factory_unittest.cc
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -151,7 +151,7 @@
   void RefCurrentFrameResources() {
     Surface* surface = manager_.GetSurfaceForId(
         SurfaceId(factory_->frame_sink_id(), local_surface_id_));
-    factory_->RefResources(surface->GetEligibleFrame().resource_list);
+    factory_->RefResources(surface->GetActiveFrame().resource_list);
   }
 
  protected:
diff --git a/cc/surfaces/surface_hittest.cc b/cc/surfaces/surface_hittest.cc
index ffc9f4c5..88de04fc8 100644
--- a/cc/surfaces/surface_hittest.cc
+++ b/cc/surfaces/surface_hittest.cc
@@ -256,9 +256,9 @@
   Surface* surface = manager_->GetSurfaceForId(surface_id);
   if (!surface)
     return nullptr;
-  if (!surface->HasFrame())
+  if (!surface->HasActiveFrame())
     return nullptr;
-  const CompositorFrame& surface_frame = surface->GetEligibleFrame();
+  const CompositorFrame& surface_frame = surface->GetActiveFrame();
 
   if (surface_frame.render_pass_list.empty())
     return nullptr;
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index b03b81e..c91bf2c 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -80,6 +80,16 @@
 }
 #endif
 
+void SurfaceManager::SetDependencyTracker(
+    std::unique_ptr<SurfaceDependencyTracker> dependency_tracker) {
+  dependency_tracker_ = std::move(dependency_tracker);
+}
+
+void SurfaceManager::RequestSurfaceResolution(Surface* pending_surface) {
+  if (dependency_tracker_)
+    dependency_tracker_->RequestSurfaceResolution(pending_surface);
+}
+
 void SurfaceManager::RegisterSurface(Surface* surface) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(surface);
@@ -597,10 +607,19 @@
     *str << surface->surface_id().ToString();
     *str << (surface->destroyed() ? " destroyed " : " live ");
 
-    if (surface->HasFrame()) {
+    if (surface->HasPendingFrame()) {
       // This provides the surface size from the root render pass.
-      const CompositorFrame& frame = surface->GetEligibleFrame();
-      *str << frame.render_pass_list.back()->output_rect.size().ToString();
+      const CompositorFrame& frame = surface->GetPendingFrame();
+      *str << "pending "
+           << frame.render_pass_list.back()->output_rect.size().ToString()
+           << " ";
+    }
+
+    if (surface->HasActiveFrame()) {
+      // This provides the surface size from the root render pass.
+      const CompositorFrame& frame = surface->GetActiveFrame();
+      *str << "active "
+           << frame.render_pass_list.back()->output_rect.size().ToString();
     }
   } else {
     *str << surface_id;
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h
index f7d68cf..f0e9630b 100644
--- a/cc/surfaces/surface_manager.h
+++ b/cc/surfaces/surface_manager.h
@@ -19,6 +19,7 @@
 #include "base/observer_list.h"
 #include "base/threading/thread_checker.h"
 #include "cc/surfaces/frame_sink_id.h"
+#include "cc/surfaces/surface_dependency_tracker.h"
 #include "cc/surfaces/surface_id.h"
 #include "cc/surfaces/surface_observer.h"
 #include "cc/surfaces/surface_reference.h"
@@ -52,6 +53,14 @@
   std::string SurfaceReferencesToString();
 #endif
 
+  void SetDependencyTracker(
+      std::unique_ptr<SurfaceDependencyTracker> dependency_tracker);
+  SurfaceDependencyTracker* dependency_tracker() {
+    return dependency_tracker_.get();
+  }
+
+  void RequestSurfaceResolution(Surface* pending_surface);
+
   void RegisterSurface(Surface* surface);
   void DeregisterSurface(const SurfaceId& surface_id);
 
@@ -261,6 +270,8 @@
   std::unordered_map<FrameSinkId, std::vector<LocalSurfaceId>, FrameSinkIdHash>
       temp_references_;
 
+  std::unique_ptr<SurfaceDependencyTracker> dependency_tracker_;
+
   base::WeakPtrFactory<SurfaceManager> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SurfaceManager);
diff --git a/cc/surfaces/surface_unittest.cc b/cc/surfaces/surface_unittest.cc
index dc6dc2d..46bf249e 100644
--- a/cc/surfaces/surface_unittest.cc
+++ b/cc/surfaces/surface_unittest.cc
@@ -3,10 +3,14 @@
 // found in the LICENSE file.
 
 #include "cc/surfaces/surface.h"
+#include "base/memory/ptr_util.h"
+#include "cc/surfaces/surface_dependency_tracker.h"
 #include "cc/surfaces/surface_factory.h"
 #include "cc/surfaces/surface_factory_client.h"
 #include "cc/surfaces/surface_id_allocator.h"
 #include "cc/surfaces/surface_manager.h"
+#include "cc/test/begin_frame_args_test.h"
+#include "cc/test/fake_external_begin_frame_source.h"
 #include "cc/test/scheduler_test_common.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/size.h"
@@ -16,6 +20,14 @@
 
 static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
 
+CompositorFrame MakeCompositorFrame(
+    std::vector<SurfaceId> referenced_surfaces) {
+  CompositorFrame compositor_frame;
+  compositor_frame.metadata.referenced_surfaces =
+      std::move(referenced_surfaces);
+  return compositor_frame;
+}
+
 class FakeSurfaceFactoryClient : public SurfaceFactoryClient {
  public:
   FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {}
@@ -32,6 +44,398 @@
   BeginFrameSource* begin_frame_source_;
 };
 
+// Surface 1 is blocked on Surface 2 and Surface 3.
+TEST(SurfaceTest, DisplayCompositorLockingBlockedOnTwo) {
+  SurfaceManager manager;
+  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source(
+      new FakeExternalBeginFrameSource(0.f, false));
+
+  std::unique_ptr<SurfaceDependencyTracker> dependency_tracker(
+      new SurfaceDependencyTracker(&manager, begin_frame_source.get()));
+  manager.SetDependencyTracker(std::move(dependency_tracker));
+
+  LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create());
+  SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1);
+
+  LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create());
+  SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2);
+
+  LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create());
+  SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3);
+
+  FakeSurfaceFactoryClient surface_factory_client1;
+  SurfaceFactory factory1(FrameSinkId(1, 1), &manager,
+                          &surface_factory_client1);
+  factory1.SubmitCompositorFrame(
+      local_surface_id1, MakeCompositorFrame({surface_id2, surface_id3}),
+      SurfaceFactory::DrawCallback());
+  EXPECT_TRUE(manager.dependency_tracker()->has_deadline());
+
+  // |factory1| is blocked on |surface_id2| and |surface_id3|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  FakeSurfaceFactoryClient surface_factory_client2;
+  SurfaceFactory factory2(FrameSinkId(2, 2), &manager,
+                          &surface_factory_client2);
+  factory2.SubmitCompositorFrame(local_surface_id2,
+                                 MakeCompositorFrame(std::vector<SurfaceId>()),
+                                 SurfaceFactory::DrawCallback());
+
+  EXPECT_TRUE(manager.dependency_tracker()->has_deadline());
+  EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame());
+
+  // |factory1| is blocked on just |surface_id3|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  FakeSurfaceFactoryClient surface_factory_client3;
+  SurfaceFactory factory3(FrameSinkId(3, 3), &manager,
+                          &surface_factory_client3);
+  factory3.SubmitCompositorFrame(local_surface_id3,
+                                 MakeCompositorFrame(std::vector<SurfaceId>()),
+                                 SurfaceFactory::DrawCallback());
+  EXPECT_FALSE(manager.dependency_tracker()->has_deadline());
+
+  // |factory1|'s Frame is now active.
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  factory1.EvictSurface();
+  factory2.EvictSurface();
+  factory3.EvictSurface();
+
+  // Destroy the SurfaceDependencyTracker before we destroy the
+  // BeginFrameSource.
+  manager.SetDependencyTracker(nullptr);
+}
+
+// Surface 1 is blocked on Surface 2 which is blocked on Surface 3.
+TEST(SurfaceTest, DisplayCompositorLockingBlockedChain) {
+  SurfaceManager manager;
+  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source(
+      new FakeExternalBeginFrameSource(0.f, false));
+
+  std::unique_ptr<SurfaceDependencyTracker> dependency_tracker(
+      new SurfaceDependencyTracker(&manager, begin_frame_source.get()));
+  manager.SetDependencyTracker(std::move(dependency_tracker));
+
+  LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create());
+  SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1);
+
+  LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create());
+  SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2);
+
+  LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create());
+  SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3);
+
+  FakeSurfaceFactoryClient surface_factory_client1;
+  SurfaceFactory factory1(FrameSinkId(1, 1), &manager,
+                          &surface_factory_client1);
+  factory1.SubmitCompositorFrame(local_surface_id1,
+                                 MakeCompositorFrame({surface_id2}),
+                                 SurfaceFactory::DrawCallback());
+
+  // |factory1| is blocked on |surface_id2|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  FakeSurfaceFactoryClient surface_factory_client2;
+  SurfaceFactory factory2(FrameSinkId(2, 2), &manager,
+                          &surface_factory_client2);
+  factory2.SubmitCompositorFrame(local_surface_id2,
+                                 MakeCompositorFrame({surface_id3}),
+                                 SurfaceFactory::DrawCallback());
+
+  // |factory2| is blocked on |surface_id3|.
+  EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame());
+
+  // |factory1| is still blocked on just |surface_id2|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  FakeSurfaceFactoryClient surface_factory_client3;
+  SurfaceFactory factory3(FrameSinkId(3, 3), &manager,
+                          &surface_factory_client3);
+  CompositorFrame frame3;
+  factory3.SubmitCompositorFrame(local_surface_id3,
+                                 MakeCompositorFrame(std::vector<SurfaceId>()),
+                                 SurfaceFactory::DrawCallback());
+
+  // |factory1|'s Frame is now active.
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  // |factory2|'s Frame is now active.
+  EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame());
+
+  factory1.EvictSurface();
+  factory2.EvictSurface();
+  factory3.EvictSurface();
+
+  // Destroy the SurfaceDependencyTracker before we destroy the
+  // BeginFrameSource.
+  manager.SetDependencyTracker(nullptr);
+}
+
+// Surface 1 and Surface 2 are blocked on Surface 3.
+TEST(SurfaceTest, DisplayCompositorLockingTwoBlockedOnOne) {
+  SurfaceManager manager;
+  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source(
+      new FakeExternalBeginFrameSource(0.f, false));
+
+  std::unique_ptr<SurfaceDependencyTracker> dependency_tracker(
+      new SurfaceDependencyTracker(&manager, begin_frame_source.get()));
+  manager.SetDependencyTracker(std::move(dependency_tracker));
+
+  LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create());
+  SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1);
+
+  LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create());
+  SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2);
+
+  LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create());
+  SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3);
+
+  FakeSurfaceFactoryClient surface_factory_client1;
+  SurfaceFactory factory1(FrameSinkId(1, 1), &manager,
+                          &surface_factory_client1);
+  factory1.SubmitCompositorFrame(local_surface_id1,
+                                 MakeCompositorFrame({surface_id3}),
+                                 SurfaceFactory::DrawCallback());
+
+  // |factory1| is blocked on |surface_id3|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  FakeSurfaceFactoryClient surface_factory_client2;
+  SurfaceFactory factory2(FrameSinkId(2, 2), &manager,
+                          &surface_factory_client2);
+  factory2.SubmitCompositorFrame(local_surface_id2,
+                                 MakeCompositorFrame({surface_id3}),
+                                 SurfaceFactory::DrawCallback());
+
+  // |factory2| is blocked on |surface_id3|.
+  EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame());
+
+  // |factory1| is still blocked on |surface_id3|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  FakeSurfaceFactoryClient surface_factory_client3;
+  SurfaceFactory factory3(FrameSinkId(3, 3), &manager,
+                          &surface_factory_client3);
+  factory3.SubmitCompositorFrame(local_surface_id3,
+                                 MakeCompositorFrame(std::vector<SurfaceId>()),
+                                 SurfaceFactory::DrawCallback());
+
+  // |factory1|'s Frame is now active.
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  // |factory2|'s Frame is now active.
+  EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame());
+
+  factory1.EvictSurface();
+  factory2.EvictSurface();
+  factory3.EvictSurface();
+
+  // Destroy the SurfaceDependencyTracker before we destroy the
+  // BeginFrameSource.
+  manager.SetDependencyTracker(nullptr);
+}
+
+// |factory1| is blocked on |surface_id2| but the deadline hits.
+TEST(SurfaceTest, DisplayCompositorLockingDeadlineHits) {
+  SurfaceManager manager;
+  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source(
+      new FakeExternalBeginFrameSource(0.f, false));
+
+  std::unique_ptr<SurfaceDependencyTracker> dependency_tracker(
+      new SurfaceDependencyTracker(&manager, begin_frame_source.get()));
+  manager.SetDependencyTracker(std::move(dependency_tracker));
+
+  LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create());
+  SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1);
+
+  LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create());
+  SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2);
+
+  LocalSurfaceId local_surface_id3(8, base::UnguessableToken::Create());
+  SurfaceId surface_id3(FrameSinkId(3, 3), local_surface_id3);
+
+  FakeSurfaceFactoryClient surface_factory_client1;
+  SurfaceFactory factory1(FrameSinkId(1, 1), &manager,
+                          &surface_factory_client1);
+  CompositorFrame frame;
+  factory1.SubmitCompositorFrame(local_surface_id1,
+                                 MakeCompositorFrame({surface_id2}),
+                                 SurfaceFactory::DrawCallback());
+  EXPECT_TRUE(manager.dependency_tracker()->has_deadline());
+
+  // |factory1| is blocked on |surface_id2|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+  FakeSurfaceFactoryClient surface_factory_client2;
+  SurfaceFactory factory2(FrameSinkId(2, 2), &manager,
+                          &surface_factory_client2);
+  factory2.SubmitCompositorFrame(local_surface_id2,
+                                 MakeCompositorFrame({surface_id3}),
+                                 SurfaceFactory::DrawCallback());
+  EXPECT_TRUE(manager.dependency_tracker()->has_deadline());
+
+  // |factory2| is blocked on |surface_id3|.
+  EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame());
+
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+
+  for (int i = 0; i < 3; ++i) {
+    begin_frame_source->TestOnBeginFrame(args);
+    // |factory1| is still blocked on |surface_id2|.
+    EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+    EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+
+    // |factory2| is still blcoked on |surface_id3|.
+    EXPECT_FALSE(factory2.current_surface_for_testing()->HasActiveFrame());
+    EXPECT_TRUE(factory2.current_surface_for_testing()->HasPendingFrame());
+  }
+
+  begin_frame_source->TestOnBeginFrame(args);
+
+  // |factory1| and |factory2| are no longer blocked.
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame());
+  EXPECT_TRUE(factory2.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory2.current_surface_for_testing()->HasPendingFrame());
+  EXPECT_FALSE(manager.dependency_tracker()->has_deadline());
+
+  factory1.EvictSurface();
+  factory2.EvictSurface();
+
+  // Destroy the SurfaceDependencyTracker before we destroy the
+  // BeginFrameSource.
+  manager.SetDependencyTracker(nullptr);
+}
+
+// Verifies that the deadline does not reset if we submit CompositorFrames
+// to new Surfaces with unresolved dependencies.
+TEST(SurfaceTest, DisplayCompositorLockingFramesSubmittedAfterDeadlineSet) {
+  SurfaceManager manager;
+  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source(
+      new FakeExternalBeginFrameSource(0.f, false));
+
+  std::unique_ptr<SurfaceDependencyTracker> dependency_tracker(
+      new SurfaceDependencyTracker(&manager, begin_frame_source.get()));
+  manager.SetDependencyTracker(std::move(dependency_tracker));
+
+  LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create());
+  SurfaceId surface_id(FrameSinkId(1, 1), local_surface_id);
+
+  std::vector<std::unique_ptr<SurfaceFactoryClient>> surface_factory_clients;
+  std::vector<std::unique_ptr<SurfaceFactory>> surface_factories;
+
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+
+  // Issue BeginFrames and create new surfaces with dependencies.
+  for (int i = 0; i < 3; ++i) {
+    LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create());
+    std::unique_ptr<SurfaceFactoryClient> surface_factory_client(
+        base::MakeUnique<FakeSurfaceFactoryClient>());
+    std::unique_ptr<SurfaceFactory> surface_factory(
+        base::MakeUnique<SurfaceFactory>(FrameSinkId(2 + i, 2 + i), &manager,
+                                         surface_factory_client.get()));
+    surface_factory->SubmitCompositorFrame(local_surface_id,
+                                           MakeCompositorFrame({surface_id}),
+                                           SurfaceFactory::DrawCallback());
+    // The deadline has been set.
+    EXPECT_TRUE(manager.dependency_tracker()->has_deadline());
+
+    // |surface_factory| is blocked on |surface_id2|.
+    EXPECT_FALSE(
+        surface_factory->current_surface_for_testing()->HasActiveFrame());
+    EXPECT_TRUE(
+        surface_factory->current_surface_for_testing()->HasPendingFrame());
+
+    // Issue a BeginFrame.
+    begin_frame_source->TestOnBeginFrame(args);
+
+    surface_factory_clients.push_back(std::move(surface_factory_client));
+    surface_factories.push_back(std::move(surface_factory));
+  }
+
+  // This BeginFrame should cause all the Surfaces to activate.
+  begin_frame_source->TestOnBeginFrame(args);
+
+  // Verify that all the Surfaces have activated.
+  for (int i = 0; i < 3; ++i) {
+    EXPECT_TRUE(
+        surface_factories[i]->current_surface_for_testing()->HasActiveFrame());
+    EXPECT_FALSE(
+        surface_factories[i]->current_surface_for_testing()->HasPendingFrame());
+    // We must evict the surface before we destroy the factories.
+    surface_factories[i]->EvictSurface();
+  }
+
+  // Destroy all the SurfaceFactories and their clients.
+  surface_factories.clear();
+  surface_factory_clients.clear();
+
+  // Destroy the SurfaceDependencyTracker before we destroy the
+  // BeginFrameSource.
+  manager.SetDependencyTracker(nullptr);
+}
+
+// Frame activates once a new frame is submitted.
+TEST(SurfaceTest, DisplayCompositorLockingNewFrameOverridesOldDependencies) {
+  SurfaceManager manager;
+  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source(
+      new FakeExternalBeginFrameSource(0.f, false));
+
+  manager.SetDependencyTracker(base::MakeUnique<SurfaceDependencyTracker>(
+      &manager, begin_frame_source.get()));
+
+  LocalSurfaceId local_surface_id1(6, base::UnguessableToken::Create());
+  SurfaceId surface_id1(FrameSinkId(1, 1), local_surface_id1);
+
+  LocalSurfaceId local_surface_id2(7, base::UnguessableToken::Create());
+  SurfaceId surface_id2(FrameSinkId(2, 2), local_surface_id2);
+
+  FakeSurfaceFactoryClient surface_factory_client1;
+  SurfaceFactory factory1(FrameSinkId(1, 1), &manager,
+                          &surface_factory_client1);
+  factory1.SubmitCompositorFrame(local_surface_id1,
+                                 MakeCompositorFrame({surface_id2}),
+                                 SurfaceFactory::DrawCallback());
+
+  // |factory1|'s Frame is blocked on |surface_id2|.
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasPendingFrame());
+  EXPECT_TRUE(manager.dependency_tracker()->has_deadline());
+
+  // Another frame is submitted to |factory1| that has no dependencies.
+  factory1.SubmitCompositorFrame(local_surface_id1,
+                                 MakeCompositorFrame(std::vector<SurfaceId>()),
+                                 SurfaceFactory::DrawCallback());
+  EXPECT_TRUE(factory1.current_surface_for_testing()->HasActiveFrame());
+  EXPECT_FALSE(factory1.current_surface_for_testing()->HasPendingFrame());
+  EXPECT_FALSE(manager.dependency_tracker()->has_deadline());
+
+  factory1.EvictSurface();
+
+  // Destroy the SurfaceDependencyTracker before we destroy the
+  // BeginFrameSource.
+  manager.SetDependencyTracker(nullptr);
+}
+
 TEST(SurfaceTest, SurfaceLifetime) {
   SurfaceManager manager;
   FakeSurfaceFactoryClient surface_factory_client;
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index 59fbfb6..8cb13e9 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -147,7 +147,7 @@
     }
   }
 
-  void DidScrollOuterViewport() { num_scrolls_++; }
+  void DidScrollOuterViewport(const gfx::ScrollOffset&) { num_scrolls_++; }
 
   void AfterTest() override { EXPECT_EQ(1, num_scrolls_); }
 
@@ -230,7 +230,7 @@
     }
   }
 
-  void DidScrollOuterViewport() { num_scrolls_++; }
+  void DidScrollOuterViewport(const gfx::ScrollOffset&) { num_scrolls_++; }
 
   void AfterTest() override { EXPECT_EQ(1, num_scrolls_); }
 
@@ -412,7 +412,7 @@
     }
   }
 
-  void DidScrollOuterViewport() { num_impl_scrolls_++; }
+  void DidScrollOuterViewport(const gfx::ScrollOffset&) { num_impl_scrolls_++; }
 
   void AfterTest() override {
     EXPECT_EQ(3, num_impl_scrolls_);
@@ -630,11 +630,12 @@
     }
   }
 
-  void DidScroll() {
+  void DidScroll(const gfx::ScrollOffset& offset) {
     final_scroll_offset_ = expected_scroll_layer_->scroll_offset();
+    EXPECT_VECTOR_EQ(offset, final_scroll_offset_);
   }
 
-  void DidScrollOuterViewport() { num_scrolls_++; }
+  void DidScrollOuterViewport(const gfx::ScrollOffset&) { num_scrolls_++; }
 
   void UpdateLayerTreeHost() override {
     EXPECT_VECTOR_EQ(gfx::Vector2d(),
@@ -923,7 +924,7 @@
     }
   }
 
-  void DidScrollOuterViewport() { num_scrolls_++; }
+  void DidScrollOuterViewport(const gfx::ScrollOffset&) { num_scrolls_++; }
 
   void AfterTest() override { EXPECT_EQ(1, num_scrolls_); }
 
@@ -1420,9 +1421,7 @@
  protected:
   class FakeLayerScrollClient {
    public:
-    void DidScroll() {
-      owner_->DidScroll(layer_);
-    }
+    void DidScroll(const gfx::ScrollOffset&) { owner_->DidScroll(layer_); }
     LayerTreeHostScrollTestLayerStructureChange* owner_;
     Layer* layer_;
   };
@@ -1572,7 +1571,7 @@
     }
   }
 
-  void DidScrollOuterViewport() { num_scrolls_++; }
+  void DidScrollOuterViewport(const gfx::ScrollOffset&) { num_scrolls_++; }
 
   void AfterTest() override {
     EXPECT_EQ(3, num_commits_);
@@ -1791,7 +1790,7 @@
     num_draws_++;
   }
 
-  void DidScrollOuterViewport() { num_impl_scrolls_++; }
+  void DidScrollOuterViewport(const gfx::ScrollOffset&) { num_impl_scrolls_++; }
 
   void AfterTest() override {
     EXPECT_EQ(3, num_impl_scrolls_);
diff --git a/chrome/VERSION b/chrome/VERSION
index 10fd3e5..33ec8b54 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=58
 MINOR=0
-BUILD=3007
+BUILD=3008
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 101078b..a2537ba 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -419,6 +419,7 @@
     "//printing:printing_java",
     "//third_party/WebKit/public:android_mojo_bindings_java",
     "//third_party/WebKit/public:blink_headers_java",
+    "//third_party/WebKit/public:mojo_bindings_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/android_tools:android_support_design_java",
     "//third_party/android_tools:android_support_v7_appcompat_java",
diff --git a/chrome/android/java/res/values-sw600dp/values.xml b/chrome/android/java/res/values-sw600dp/values.xml
index 5a8b57a..2b91507 100644
--- a/chrome/android/java/res/values-sw600dp/values.xml
+++ b/chrome/android/java/res/values-sw600dp/values.xml
@@ -18,8 +18,8 @@
     <!-- These constants were chosen empirically for their visually pleasant behavior.
          Contact tedchoc@chromium.org or dtrainor@chromium.org for questions about
          changing these values. -->
-    <item name="top_controls_show_threshold" format="float" type="floats">0.27</item>
-    <item name="top_controls_hide_threshold" format="float" type="floats">0.17</item>
+    <item name="top_controls_show_threshold" format="float" type="dimen">0.27</item>
+    <item name="top_controls_hide_threshold" format="float" type="dimen">0.17</item>
 
     <!-- The number of thumbnails that the thumbnail cache can hold. -->
     <integer name="default_thumbnail_cache_size">3</integer>
diff --git a/chrome/android/java/res/values/values.xml b/chrome/android/java/res/values/values.xml
index 094d436b..72b17c2 100644
--- a/chrome/android/java/res/values/values.xml
+++ b/chrome/android/java/res/values/values.xml
@@ -21,8 +21,8 @@
     <!-- These constants were chosen empirically for their visually pleasant behavior.
          Contact tedchoc@chromium.org or dtrainor@chromium.org for questions about
          changing these values. -->
-    <item name="top_controls_show_threshold" format="float" type="floats">0.5</item>
-    <item name="top_controls_hide_threshold" format="float" type="floats">0.5</item>
+    <item name="top_controls_show_threshold" format="float" type="dimen">0.5</item>
+    <item name="top_controls_hide_threshold" format="float" type="dimen">0.5</item>
 
     <!-- The number of thumbnails that the thumbnail cache can hold. -->
     <integer name="default_thumbnail_cache_size">5</integer>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ApplicationInitialization.java b/chrome/android/java/src/org/chromium/chrome/browser/ApplicationInitialization.java
index b490a869..9f15f0e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ApplicationInitialization.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ApplicationInitialization.java
@@ -35,10 +35,10 @@
         if (commandLine.hasSwitch(ChromeSwitches.DISABLE_FULLSCREEN)) return;
 
         TypedValue threshold = new TypedValue();
-        resources.getValue(R.floats.top_controls_show_threshold, threshold, true);
+        resources.getValue(R.dimen.top_controls_show_threshold, threshold, true);
         commandLine.appendSwitchWithValue(
                 ContentSwitches.TOP_CONTROLS_SHOW_THRESHOLD, threshold.coerceToString().toString());
-        resources.getValue(R.floats.top_controls_hide_threshold, threshold, true);
+        resources.getValue(R.dimen.top_controls_hide_threshold, threshold, true);
         commandLine.appendSwitchWithValue(
                 ContentSwitches.TOP_CONTROLS_HIDE_THRESHOLD, threshold.coerceToString().toString());
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 32348adc..f4a9f8f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -938,7 +938,7 @@
                     if (url == null || url.equals(UrlConstants.NTP_URL)) {
                         if (fromLauncherShortcut) {
                             getTabCreator(true).launchUrl(
-                                    UrlConstants.NTP_URL, TabLaunchType.FROM_EXTERNAL_APP);
+                                    UrlConstants.NTP_URL, TabLaunchType.FROM_LAUNCHER_SHORTCUT);
                             recordLauncherShortcutAction(true);
                             reportNewTabShortcutUsed(true);
                         } else {
@@ -1358,7 +1358,7 @@
         if (!mUIInitialized) return false;
         final Tab currentTab = getActivityTab();
 
-        if (mVrShellDelegate.exitVRIfNecessary(false /* isPausing */)) return true;
+        if (mVrShellDelegate.onBackPressed()) return true;
 
         if (currentTab == null) {
             recordBackPressedUma("currentTab is null", BACK_PRESSED_TAB_IS_NULL);
@@ -1500,7 +1500,7 @@
             loadUrlParams.setVerbatimHeaders(headers);
             return getTabCreator(isIncognito).createNewTab(
                     loadUrlParams,
-                    fromLauncherShortcut ? TabLaunchType.FROM_EXTERNAL_APP
+                    fromLauncherShortcut ? TabLaunchType.FROM_LAUNCHER_SHORTCUT
                             : TabLaunchType.FROM_LINK,
                     null,
                     intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
index ef712dc..9be40bf1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -92,6 +92,7 @@
             if (type == TabLaunchType.FROM_RESTORE) return;
             if (type == TabLaunchType.FROM_REPARENTING) return;
             if (type == TabLaunchType.FROM_EXTERNAL_APP) return;
+            if (type == TabLaunchType.FROM_LAUNCHER_SHORTCUT) return;
 
             tabCreating(getTabModelSelector().getCurrentTabId(), tab.getUrl(), tab.isIncognito());
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
index 437c88d..0b99b21 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
@@ -311,6 +311,30 @@
     }
 
     /**
+     * Enqueue a request to download a file using Android DownloadManager.
+     * @param url Url to download.
+     * @param userAgent User agent to use.
+     * @param contentDisposition Content disposition of the request.
+     * @param mimeType MIME type.
+     * @param cookie Cookie to use.
+     * @param referrer Referrer to use.
+     */
+    @CalledByNative
+    private void enqueueAndroidDownloadManagerRequest(String url, String userAgent,
+            String contentDisposition, String mimeType, String cookie, String referrer) {
+        DownloadInfo downloadInfo = new DownloadInfo.Builder()
+                .setUrl(url)
+                .setUserAgent(userAgent)
+                .setContentDisposition(contentDisposition)
+                .setMimeType(mimeType)
+                .setCookie(cookie)
+                .setReferrer(referrer)
+                .setIsGETRequest(true)
+                .build();
+        enqueueDownloadManagerRequest(downloadInfo);
+    }
+
+    /**
      * Called when download starts.
      *
      * @param filename Name of the file.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
index 3fbc9a55..15adc90 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.favicon;
 
 import android.graphics.Bitmap;
-import android.graphics.Color;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -92,15 +91,6 @@
     }
 
     /**
-     * Return the dominant color of a given bitmap in {@link Color} format.
-     * @param image The bitmap image to find the dominant color for.
-     * @return The dominant color in {@link Color} format.
-     */
-    public static int getDominantColorForBitmap(Bitmap image) {
-        return nativeGetDominantColorForBitmap(image);
-    }
-
-    /**
      * Get 16x16 Favicon bitmap for the requested arguments. Only retrives favicons in synced
      * session storage. (e.g. favicons synced from other devices).
      * TODO(apiccion): provide a way to obtain higher resolution favicons.
@@ -139,7 +129,6 @@
             FaviconImageCallback faviconImageCallback);
     private static native Bitmap nativeGetSyncedFaviconImageForURL(long nativeFaviconHelper,
             Profile profile, String pageUrl);
-    private static native int nativeGetDominantColorForBitmap(Bitmap image);
     private static native void nativeEnsureIconIsAvailable(long nativeFaviconHelper,
             Profile profile, WebContents webContents, String pageUrl, String iconUrl,
             boolean isLargeIcon, boolean isTemporary, IconAvailabilityCallback callback);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index 080fbf7..11431f7be 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -546,6 +546,15 @@
         return manager.mNotificationBuilder;
     }
 
+    @VisibleForTesting
+    @Nullable
+    static MediaNotificationInfo getMediaNotificationInfoForTesting(
+            int notificationId) {
+        MediaNotificationManager manager = getManager(notificationId);
+
+        return (manager == null) ? null : manager.mMediaNotificationInfo;
+    }
+
     private static boolean isRunningN() {
         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
index 1e5c3336..2c70262d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
@@ -309,6 +309,7 @@
             // {@link #onTitleUpdated()}. The following assignment is to keep |mCurrentMetadata| up
             // to date as |mPageMetadata| may have changed.
             mCurrentMetadata = getMetadata();
+            mMediaSessionActions = null;
 
             if (isNotificationHiddingOrHidden()) return;
 
@@ -316,6 +317,7 @@
             mNotificationInfoBuilder.setNotificationLargeIcon(mFavicon);
             mNotificationInfoBuilder.setMediaSessionImage(mPageMediaImage);
             mNotificationInfoBuilder.setMetadata(mCurrentMetadata);
+            mNotificationInfoBuilder.setMediaSessionActions(mMediaSessionActions);
             showNotification();
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
index f30ab895..172ff86 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
@@ -29,23 +29,25 @@
         InterfaceRegistrar.Registry.addWebContentsRegistrar(
                 new ChromeWebContentsInterfaceRegistrar());
     }
-}
 
-class ChromeContextInterfaceRegistrar implements InterfaceRegistrar<Context> {
-    @Override
-    public void registerInterfaces(InterfaceRegistry registry, final Context applicationContext) {
-        registry.addInterface(
-                BarcodeDetection.MANAGER, new BarcodeDetectionImpl.Factory(applicationContext));
-        registry.addInterface(
-                TextDetection.MANAGER, new TextDetectionImpl.Factory(applicationContext));
+    private static class ChromeContextInterfaceRegistrar implements InterfaceRegistrar<Context> {
+        @Override
+        public void registerInterfaces(
+                InterfaceRegistry registry, final Context applicationContext) {
+            registry.addInterface(
+                    BarcodeDetection.MANAGER, new BarcodeDetectionImpl.Factory(applicationContext));
+            registry.addInterface(
+                    TextDetection.MANAGER, new TextDetectionImpl.Factory(applicationContext));
+        }
     }
-}
 
-class ChromeWebContentsInterfaceRegistrar implements InterfaceRegistrar<WebContents> {
-    @Override
-    public void registerInterfaces(InterfaceRegistry registry, final WebContents webContents) {
-        registry.addInterface(PaymentRequest.MANAGER, new PaymentRequestFactory(webContents));
-        registry.addInterface(
-                ShareService.MANAGER, new ShareServiceImplementationFactory(webContents));
+    private static class ChromeWebContentsInterfaceRegistrar
+            implements InterfaceRegistrar<WebContents> {
+        @Override
+        public void registerInterfaces(InterfaceRegistry registry, final WebContents webContents) {
+            registry.addInterface(PaymentRequest.MANAGER, new PaymentRequestFactory(webContents));
+            registry.addInterface(
+                    ShareService.MANAGER, new ShareServiceImplementationFactory(webContents));
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/ExponentialBackoffScheduler.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/ExponentialBackoffScheduler.java
index e9a6ef54..1515888 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/ExponentialBackoffScheduler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/ExponentialBackoffScheduler.java
@@ -34,6 +34,8 @@
  *
  * This class is not thread-safe because any two different classes could be accessing the same
  * SharedPreferences.
+ *
+ * TODO(dfalcantara): Consider making this an AlarmManagerHelper class to manage general alarms.
  */
 @NotThreadSafe
 public class ExponentialBackoffScheduler {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaClient.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaClient.java
index d3e0bd6b..98b8f87 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaClient.java
@@ -4,23 +4,27 @@
 
 package org.chromium.chrome.browser.omaha;
 
+import android.app.AlarmManager;
 import android.app.IntentService;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
 import android.os.Build;
-import android.support.annotation.IntDef;
+import android.os.Looper;
 
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Log;
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.ChromeApplication;
 
 import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -51,9 +55,6 @@
  */
 public class OmahaClient extends IntentService {
     // Results of {@link #handlePostRequest()}.
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({POST_RESULT_NO_REQUEST, POST_RESULT_SENT, POST_RESULT_FAILED, POST_RESULT_SCHEDULED})
-    @interface PostResult {}
     static final int POST_RESULT_NO_REQUEST = 0;
     static final int POST_RESULT_SENT = 1;
     static final int POST_RESULT_FAILED = 2;
@@ -61,15 +62,19 @@
 
     private static final String TAG = "omaha";
 
-    /** Deprecated; kept around to cancel alarms set for OmahaClient pre-M58. */
+    // Intent actions.
+    private static final String ACTION_INITIALIZE =
+            "org.chromium.chrome.browser.omaha.ACTION_INITIALIZE";
     private static final String ACTION_REGISTER_REQUEST =
             "org.chromium.chrome.browser.omaha.ACTION_REGISTER_REQUEST";
+    private static final String ACTION_POST_REQUEST =
+            "org.chromium.chrome.browser.omaha.ACTION_POST_REQUEST";
 
     // Delays between events.
-    static final long MS_POST_BASE_DELAY = TimeUnit.HOURS.toMillis(1);
-    static final long MS_POST_MAX_DELAY = TimeUnit.HOURS.toMillis(5);
+    private static final long MS_POST_BASE_DELAY = TimeUnit.HOURS.toMillis(1);
+    private static final long MS_POST_MAX_DELAY = TimeUnit.HOURS.toMillis(5);
     static final long MS_BETWEEN_REQUESTS = TimeUnit.HOURS.toMillis(5);
-    static final int MS_CONNECTION_TIMEOUT = (int) TimeUnit.MINUTES.toMillis(1);
+    private static final int MS_CONNECTION_TIMEOUT = (int) TimeUnit.MINUTES.toMillis(1);
 
     // Strings indicating how the Chrome APK arrived on the user's device. These values MUST NOT
     // be changed without updating the corresponding Omaha server strings.
@@ -82,7 +87,8 @@
 
     // Member fields not persisted to disk.
     private boolean mStateHasBeenRestored;
-    private OmahaDelegate mDelegate;
+    private ExponentialBackoffScheduler mBackoffScheduler;
+    private RequestGenerator mGenerator;
 
     // State saved written to and read from disk.
     private RequestData mCurrentRequest;
@@ -99,115 +105,176 @@
         setIntentRedelivery(true);
     }
 
+    @VisibleForTesting
+    long getTimestampForNextPostAttempt() {
+        return mTimestampForNextPostAttempt;
+    }
+
+    @VisibleForTesting
+    long getTimestampForNewRequest() {
+        return mTimestampForNewRequest;
+    }
+
+    @VisibleForTesting
+    int getCumulativeFailedAttempts() {
+        return getBackoffScheduler().getNumFailedAttempts();
+    }
+
+    /**
+     * Creates the scheduler used to space out POST attempts.
+     */
+    @VisibleForTesting
+    ExponentialBackoffScheduler createBackoffScheduler(String prefPackage, Context context,
+            long base, long max) {
+        return new ExponentialBackoffScheduler(prefPackage, context, base, max);
+    }
+
+    /**
+     * Creates the request generator used to create Omaha XML.
+     */
+    @VisibleForTesting
+    RequestGenerator createRequestGenerator(Context context) {
+        return ((ChromeApplication) context.getApplicationContext()).createOmahaRequestGenerator();
+    }
+
     /**
      * Handles an action on a thread separate from the UI thread.
      * @param intent Intent fired by some part of Chrome.
      */
     @Override
     public void onHandleIntent(Intent intent) {
-        assert !ThreadUtils.runningOnUiThread();
-        run();
-    }
+        assert Looper.myLooper() != Looper.getMainLooper();
 
-    protected void run() {
         if (OmahaBase.isDisabled() || Build.VERSION.SDK_INT > Build.VERSION_CODES.N
                 || getRequestGenerator() == null) {
             Log.v(TAG, "Disabled.  Ignoring intent.");
             return;
         }
 
-        if (mDelegate == null) mDelegate = new OmahaDelegateImpl(this);
+        restoreState(this);
 
-        restoreState(getContext());
-
-        long nextTimestamp = Long.MAX_VALUE;
-        if (mDelegate.isChromeBeingUsed()) {
-            handleRegisterActiveRequest();
-            nextTimestamp = Math.min(nextTimestamp, mTimestampForNewRequest);
+        if (ACTION_INITIALIZE.equals(intent.getAction())) {
+            handleInitialize();
+        } else if (ACTION_REGISTER_REQUEST.equals(intent.getAction())) {
+            handleRegisterRequest();
+        } else if (ACTION_POST_REQUEST.equals(intent.getAction())) {
+            handlePostRequest();
+        } else {
+            Log.e(TAG, "Got unknown action from intent: " + intent.getAction());
         }
 
-        if (hasRequest()) {
-            int result = handlePostRequest();
-            if (result == POST_RESULT_FAILED || result == POST_RESULT_SCHEDULED) {
-                nextTimestamp = Math.min(nextTimestamp, mTimestampForNextPostAttempt);
-            }
-        }
-
-        // TODO(dfalcantara): Prevent Omaha code from repeatedly rescheduling itself immediately in
-        //                    case a scheduling error occurs.
-        if (nextTimestamp != Long.MAX_VALUE && nextTimestamp >= 0) {
-            mDelegate.scheduleService(this, nextTimestamp);
-        }
-        saveState(getContext());
+        saveState(this);
     }
 
     /**
      * Begin communicating with the Omaha Update Server.
      */
     static void startService(Context context) {
-        context.startService(createOmahaIntent(context));
+        Intent omahaIntent = createInitializeIntent(context);
+        context.startService(omahaIntent);
     }
 
-    static Intent createOmahaIntent(Context context) {
-        return new Intent(context, OmahaClient.class);
+    static Intent createInitializeIntent(Context context) {
+        Intent intent = new Intent(context, OmahaClient.class);
+        intent.setAction(ACTION_INITIALIZE);
+        return intent;
+    }
+
+    /**
+     * Start a recurring alarm to fire request generation intents.
+     */
+    private void handleInitialize() {
+        scheduleActiveUserCheck();
+
+        // If a request exists, kick off POSTing it to the server immediately.
+        if (hasRequest()) handlePostRequest();
+    }
+
+    /**
+     * Returns an Intent for registering a new request to send to the server.
+     */
+    static Intent createRegisterRequestIntent(Context context) {
+        Intent intent = new Intent(context, OmahaClient.class);
+        intent.setAction(ACTION_REGISTER_REQUEST);
+        return intent;
     }
 
     /**
      * Determines if a new request should be generated.  New requests are only generated if enough
      * time has passed between now and the last time a request was generated.
      */
-    private void handleRegisterActiveRequest() {
+    private void handleRegisterRequest() {
+        if (!isChromeBeingUsed()) {
+            getBackoffScheduler().cancelAlarm(createRegisterRequestIntent(this));
+            return;
+        }
+
         // If the current request is too old, generate a new one.
         long currentTimestamp = getBackoffScheduler().getCurrentTime();
         boolean isTooOld = hasRequest()
                 && mCurrentRequest.getAgeInMilliseconds(currentTimestamp) >= MS_BETWEEN_REQUESTS;
-        boolean isOverdue = currentTimestamp >= mTimestampForNewRequest;
+        boolean isOverdue = !hasRequest() && currentTimestamp >= mTimestampForNewRequest;
         if (isTooOld || isOverdue) {
             registerNewRequest(currentTimestamp);
         }
+
+        // Send the request.
+        if (hasRequest()) {
+            handlePostRequest();
+        }
+    }
+
+    /**
+     * Returns an Intent for POSTing the current request to the Omaha server.
+     */
+    static Intent createPostRequestIntent(Context context) {
+        Intent intent = new Intent(context, OmahaClient.class);
+        intent.setAction(ACTION_POST_REQUEST);
+        return intent;
     }
 
     /**
      * Sends the request it is holding.
      */
-    private int handlePostRequest() {
-        if (!hasRequest()) {
-            mDelegate.onHandlePostRequestDone(POST_RESULT_NO_REQUEST, false);
-            return POST_RESULT_NO_REQUEST;
-        }
+    @VisibleForTesting
+    protected int handlePostRequest() {
+        if (!hasRequest()) return POST_RESULT_NO_REQUEST;
 
         // If enough time has passed since the last attempt, try sending a request.
         int result;
         long currentTimestamp = getBackoffScheduler().getCurrentTime();
-        boolean installEventWasSent = false;
         if (currentTimestamp >= mTimestampForNextPostAttempt) {
             // All requests made during the same session should have the same ID.
-            String sessionID = mDelegate.generateUUID();
+            String sessionID = generateRandomUUID();
             boolean sendingInstallRequest = mSendInstallEvent;
             boolean succeeded = generateAndPostRequest(currentTimestamp, sessionID);
 
             if (succeeded && sendingInstallRequest) {
                 // Only the first request ever generated should contain an install event.
                 mSendInstallEvent = false;
-                installEventWasSent = true;
 
                 // Create and immediately send another request for a ping and update check.
                 registerNewRequest(currentTimestamp);
-                succeeded &= generateAndPostRequest(currentTimestamp, sessionID);
+                generateAndPostRequest(currentTimestamp, sessionID);
             }
 
             result = succeeded ? POST_RESULT_SENT : POST_RESULT_FAILED;
         } else {
+            schedulePost();
             result = POST_RESULT_SCHEDULED;
         }
 
-        mDelegate.onHandlePostRequestDone(result, installEventWasSent);
         return result;
     }
 
+    /** Set an alarm to POST at the proper time.  Previous alarms are destroyed. */
+    private void schedulePost() {
+        Intent postIntent = createPostRequestIntent(this);
+        getBackoffScheduler().createAlarm(postIntent, mTimestampForNextPostAttempt);
+    }
+
     private boolean generateAndPostRequest(long currentTimestamp, String sessionID) {
         ExponentialBackoffScheduler scheduler = getBackoffScheduler();
-        boolean succeeded = false;
         try {
             // Generate the XML for the current request.
             long installAgeInDays = RequestGenerator.installAge(currentTimestamp,
@@ -228,29 +295,61 @@
             mLatestVersion = parser.getNewVersion();
             mMarketURL = parser.getURL();
 
-            succeeded = true;
-        } catch (RequestFailureException e) {
-            Log.e(TAG, "Failed to contact server: ", e);
-        }
-
-        if (succeeded) {
             // If we've gotten this far, we've successfully sent a request.
             mCurrentRequest = null;
 
+            mTimestampForNewRequest = getBackoffScheduler().getCurrentTime() + MS_BETWEEN_REQUESTS;
+            scheduleActiveUserCheck();
+
             scheduler.resetFailedAttempts();
-            mTimestampForNewRequest = scheduler.getCurrentTime() + MS_BETWEEN_REQUESTS;
             mTimestampForNextPostAttempt = scheduler.calculateNextTimestamp();
             Log.i(TAG, "Request to Server Successful. Timestamp for next request:"
                     + String.valueOf(mTimestampForNextPostAttempt));
-        } else {
-            // Set the alarm to try again later.  Failures are incremented after setting the timer
-            // to allow the first failure to incur the minimum base delay between POSTs.
-            mTimestampForNextPostAttempt = scheduler.calculateNextTimestamp();
-            scheduler.increaseFailedAttempts();
-        }
 
-        mDelegate.onGenerateAndPostRequestDone(succeeded);
-        return succeeded;
+            return true;
+        } catch (RequestFailureException e) {
+            // Set the alarm to try again later.
+            Log.e(TAG, "Failed to contact server: ", e);
+            scheduler.increaseFailedAttempts();
+            mTimestampForNextPostAttempt = scheduler.calculateNextTimestamp();
+            scheduler.createAlarm(createPostRequestIntent(this), mTimestampForNextPostAttempt);
+            return false;
+        }
+    }
+
+    /**
+     * Sets a repeating alarm that fires request registration Intents.
+     * Setting the alarm overwrites whatever alarm is already there, and rebooting
+     * clears whatever alarms are currently set.
+     */
+    private void scheduleActiveUserCheck() {
+        Intent registerIntent = createRegisterRequestIntent(this);
+        PendingIntent pIntent = PendingIntent.getService(this, 0, registerIntent, 0);
+        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+        setAlarm(am, pIntent, mTimestampForNewRequest);
+    }
+
+    /**
+     * Sets up a timer to fire after each interval.
+     * Override to prevent a real alarm from being set.
+     */
+    @VisibleForTesting
+    protected void setAlarm(AlarmManager am, PendingIntent operation, long triggerAtTime) {
+        try {
+            am.setRepeating(AlarmManager.RTC, triggerAtTime, MS_BETWEEN_REQUESTS, operation);
+        } catch (SecurityException e) {
+            Log.e(TAG, "Failed to set repeating alarm.");
+        }
+    }
+
+    /**
+     * Determine whether or not Chrome is currently being used actively.
+     */
+    @VisibleForTesting
+    protected boolean isChromeBeingUsed() {
+        boolean isChromeVisible = ApplicationStatus.hasVisibleActivities();
+        boolean isScreenOn = ApiCompatibilityUtils.isInteractive(this);
+        return isChromeVisible && isScreenOn;
     }
 
     /**
@@ -258,7 +357,8 @@
      * fresh.
      * @param currentTimestamp Current time.
      */
-    private void registerNewRequest(long currentTimestamp) {
+    @VisibleForTesting
+    void registerNewRequest(long currentTimestamp) {
         mCurrentRequest = createRequestData(currentTimestamp, null);
         getBackoffScheduler().resetFailedAttempts();
         mTimestampForNextPostAttempt = currentTimestamp;
@@ -266,22 +366,22 @@
         // Tentatively set the timestamp for a new request.  This will be updated when the server
         // is successfully contacted.
         mTimestampForNewRequest = currentTimestamp + MS_BETWEEN_REQUESTS;
-
-        mDelegate.onRegisterNewRequestDone(mTimestampForNewRequest, mTimestampForNextPostAttempt);
+        scheduleActiveUserCheck();
     }
 
     private RequestData createRequestData(long currentTimestamp, String persistedID) {
         // If we're sending a persisted event, keep trying to send the same request ID.
         String requestID;
         if (persistedID == null || INVALID_REQUEST_ID.equals(persistedID)) {
-            requestID = mDelegate.generateUUID();
+            requestID = generateRandomUUID();
         } else {
             requestID = persistedID;
         }
         return new RequestData(mSendInstallEvent, currentTimestamp, requestID, mInstallSource);
     }
 
-    private boolean hasRequest() {
+    @VisibleForTesting
+    boolean hasRequest() {
         return mCurrentRequest != null;
     }
 
@@ -290,7 +390,8 @@
      * @return the XML response as a String.
      * @throws RequestFailureException if the request fails.
      */
-    private String postRequest(long timestamp, String xml) throws RequestFailureException {
+    @VisibleForTesting
+    String postRequest(long timestamp, String xml) throws RequestFailureException {
         String response = null;
 
         HttpURLConnection urlConnection = null;
@@ -300,7 +401,7 @@
             // Prepare the HTTP header.
             urlConnection.setDoOutput(true);
             urlConnection.setFixedLengthStreamingMode(xml.getBytes().length);
-            if (mSendInstallEvent && getBackoffScheduler().getNumFailedAttempts() > 0) {
+            if (mSendInstallEvent && getCumulativeFailedAttempts() > 0) {
                 String age = Long.toString(mCurrentRequest.getAgeInSeconds(timestamp));
                 urlConnection.addRequestProperty("X-RequestAge", age);
             }
@@ -340,17 +441,33 @@
     }
 
     /**
+     * Determine how the Chrome APK arrived on the device.
+     * @param context Context to pull resources from.
+     * @return A String indicating the install source.
+     */
+    String determineInstallSource() {
+        boolean isInSystemImage = (getApplicationFlags() & ApplicationInfo.FLAG_SYSTEM) != 0;
+        return isInSystemImage ? INSTALL_SOURCE_SYSTEM : INSTALL_SOURCE_ORGANIC;
+    }
+
+    /**
+     * Returns the Application's flags, used to determine if Chrome was installed as part of the
+     * system image.
+     * @return The Application's flags.
+     */
+    @VisibleForTesting
+    int getApplicationFlags() {
+        return getApplicationInfo().flags;
+    }
+
+    /**
      * Reads the data back from the file it was saved to.  Uses SharedPreferences to handle I/O.
      * Sanity checks are performed on the timestamps to guard against clock changing.
      */
     @VisibleForTesting
     void restoreState(Context context) {
         if (mStateHasBeenRestored) return;
-
-        String installSource =
-                mDelegate.isInSystemImage() ? INSTALL_SOURCE_SYSTEM : INSTALL_SOURCE_ORGANIC;
-        ExponentialBackoffScheduler scheduler = getBackoffScheduler();
-        long currentTime = scheduler.getCurrentTime();
+        long currentTime = getBackoffScheduler().getCurrentTime();
 
         SharedPreferences preferences = OmahaBase.getSharedPreferences(context);
         mTimestampForNewRequest =
@@ -359,7 +476,8 @@
                 preferences.getLong(OmahaBase.PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, currentTime);
         mTimestampOfInstall = preferences.getLong(OmahaBase.PREF_TIMESTAMP_OF_INSTALL, currentTime);
         mSendInstallEvent = preferences.getBoolean(OmahaBase.PREF_SEND_INSTALL_EVENT, true);
-        mInstallSource = preferences.getString(OmahaBase.PREF_INSTALL_SOURCE, installSource);
+        mInstallSource =
+                preferences.getString(OmahaBase.PREF_INSTALL_SOURCE, determineInstallSource());
         mLatestVersion = preferences.getString(OmahaBase.PREF_LATEST_VERSION, "");
         mMarketURL = preferences.getString(OmahaBase.PREF_MARKET_URL, "");
 
@@ -383,15 +501,13 @@
 
         // Confirm that the timestamp for the next POST is less than the current delay.
         long delayToNextPost = mTimestampForNextPostAttempt - currentTime;
-        long lastGeneratedDelay = scheduler.getGeneratedDelay();
-        if (delayToNextPost > lastGeneratedDelay) {
+        if (delayToNextPost > getBackoffScheduler().getGeneratedDelay()) {
             Log.w(TAG, "Delay to next post attempt (" + delayToNextPost
-                    + ") is greater than expected (" + lastGeneratedDelay
+                    + ") is greater than expected (" + getBackoffScheduler().getGeneratedDelay()
                     + ").  Resetting to now.");
             mTimestampForNextPostAttempt = currentTime;
         }
 
-        migrateToNewerChromeVersions();
         mStateHasBeenRestored = true;
     }
 
@@ -415,32 +531,26 @@
         editor.putString(OmahaBase.PREF_MARKET_URL, mMarketURL == null ? "" : mMarketURL);
         editor.putString(OmahaBase.PREF_INSTALL_SOURCE, mInstallSource);
         editor.apply();
-
-        mDelegate.onSaveStateDone(mTimestampForNewRequest, mTimestampForNextPostAttempt);
     }
 
-    private void migrateToNewerChromeVersions() {
-        // Remove any repeating alarms in favor of the new scheduling setup on M58 and up.
-        // Seems cheaper to cancel the alarm repeatedly than to store a SharedPreference and never
-        // do it again.
-        Intent intent = new Intent(getContext(), OmahaClient.class);
-        intent.setAction(ACTION_REGISTER_REQUEST);
-        getBackoffScheduler().cancelAlarm(intent);
+    /**
+     * Generates a random UUID.
+     */
+    @VisibleForTesting
+    protected String generateRandomUUID() {
+        return UUID.randomUUID().toString();
     }
 
-    Context getContext() {
-        return mDelegate.getContext();
+    protected final RequestGenerator getRequestGenerator() {
+        if (mGenerator == null) mGenerator = createRequestGenerator(this);
+        return mGenerator;
     }
 
-    private RequestGenerator getRequestGenerator() {
-        return mDelegate.getRequestGenerator();
-    }
-
-    private ExponentialBackoffScheduler getBackoffScheduler() {
-        return mDelegate.getScheduler();
-    }
-
-    void setDelegateForTests(OmahaDelegate delegate) {
-        mDelegate = delegate;
+    protected final ExponentialBackoffScheduler getBackoffScheduler() {
+        if (mBackoffScheduler == null) {
+            mBackoffScheduler = createBackoffScheduler(
+                    OmahaBase.PREF_PACKAGE, this, MS_POST_BASE_DELAY, MS_POST_MAX_DELAY);
+        }
+        return mBackoffScheduler;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaDelegate.java
deleted file mode 100644
index 9509174..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaDelegate.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.omaha;
-
-import android.app.Service;
-import android.content.Context;
-
-import org.chromium.chrome.browser.omaha.OmahaClient.PostResult;
-
-/** Delegates calls out from the OmahaClient. */
-public abstract class OmahaDelegate {
-    protected final Context mContext;
-    private RequestGenerator mRequestGenerator;
-
-    OmahaDelegate(Context context) {
-        mContext = context;
-    }
-
-    /** @return Context that is used to interact with the system. */
-    Context getContext() {
-        return mContext;
-    }
-
-    /** @return Whether Chrome is installed as part of the system image. */
-    abstract boolean isInSystemImage();
-
-    /** @return The scheduler used to trigger jobs. */
-    abstract ExponentialBackoffScheduler getScheduler();
-
-    /** @return The {@link RequestGenerator} used to create Omaha XML. */
-    final RequestGenerator getRequestGenerator() {
-        if (mRequestGenerator == null) mRequestGenerator = createRequestGenerator(getContext());
-        return mRequestGenerator;
-    }
-
-    /** @return A UUID that can be used to identify particular requests. */
-    abstract String generateUUID();
-
-    /** Determine whether or not Chrome is currently being used actively. */
-    abstract boolean isChromeBeingUsed();
-
-    /**
-     * Schedules the {@link Service} to run again at the given time.
-     * @param service         Service that is doing the scheduling.
-     * @param nextTimestampMs When the service should be run again.
-     */
-    abstract void scheduleService(Service service, long nextTimestampMs);
-
-    /** Creates a {@link RequestGenerator}. */
-    abstract RequestGenerator createRequestGenerator(Context context);
-
-    /**
-     * Called when {@link OmahaClient#registerNewRequest} finishes.
-     * @param timestampRequestMs When the next active user request should be generated.
-     * @param timestampPostMs    Earliest time the next POST should be allowed.
-     */
-    void onRegisterNewRequestDone(long timestampRequestMs, long timestampPostMs) {}
-
-    /**
-     * Called when {@link OmahaClient#handlePostRequest} finishes.
-     * @param result              See {@link PostResult}.
-     * @param installEventWasSent Whether or not an install event was sent.
-     */
-    void onHandlePostRequestDone(@PostResult int result, boolean installEventWasSent) {}
-
-    /**
-     * Called when {@link OmahaClient#generateAndPostRequest} finishes.
-     * @param succeeded Whether or not the post was successfully received by the server.
-     */
-    void onGenerateAndPostRequestDone(boolean succeeded) {}
-
-    /**
-     * Called when {@link OmahaClient#saveState} finishes.
-     * @param timestampRequestMs When the next active user request should be generated.
-     * @param timestampPostMs    Earliest time the next POST should be allowed.
-     */
-    void onSaveStateDone(long timestampRequestMs, long timestampPostMs) {}
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaDelegateImpl.java
deleted file mode 100644
index b0ae437..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaDelegateImpl.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.omaha;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.chrome.browser.ChromeApplication;
-
-import java.util.UUID;
-
-/** Delegates calls out from the OmahaClient. */
-public class OmahaDelegateImpl extends OmahaDelegate {
-    private final ExponentialBackoffScheduler mScheduler;
-
-    OmahaDelegateImpl(Context context) {
-        super(context);
-        mScheduler = new ExponentialBackoffScheduler(OmahaBase.PREF_PACKAGE, context,
-                OmahaClient.MS_POST_BASE_DELAY, OmahaClient.MS_POST_MAX_DELAY);
-    }
-
-    @Override
-    boolean isInSystemImage() {
-        return (getContext().getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-    }
-
-    @Override
-    ExponentialBackoffScheduler getScheduler() {
-        return mScheduler;
-    }
-
-    @Override
-    String generateUUID() {
-        return UUID.randomUUID().toString();
-    }
-
-    @Override
-    boolean isChromeBeingUsed() {
-        boolean isChromeVisible = ApplicationStatus.hasVisibleActivities();
-        boolean isScreenOn = ApiCompatibilityUtils.isInteractive(getContext());
-        return isChromeVisible && isScreenOn;
-    }
-
-    @Override
-    void scheduleService(Service service, long nextTimestamp) {
-        if (service instanceof OmahaClient) {
-            getScheduler().createAlarm(OmahaClient.createOmahaIntent(getContext()), nextTimestamp);
-        } else {
-            // TODO(dfalcantara): Do something here with a JobService.
-        }
-    }
-
-    @Override
-    protected RequestGenerator createRequestGenerator(Context context) {
-        return ((ChromeApplication) context.getApplicationContext()).createOmahaRequestGenerator();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
index 9b76320..4413a88 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
@@ -675,15 +675,21 @@
                     }
                     return;
                 }
+                assert isAddingNewAddress || isSelectingIncompleteAddress;
 
-                final AutofillAddress editAddress = isSelectingIncompleteAddress
-                        ? new AutofillAddress(mContext,
-                                  findTargetProfile(mProfilesForBillingAddress, eventData.first))
-                        : null;
+                AutofillProfile profile = isSelectingIncompleteAddress
+                        ? findTargetProfile(mProfilesForBillingAddress, eventData.first)
+                        : new AutofillProfile();
+                if (TextUtils.isEmpty(profile.getFullName())) {
+                    // Prefill card holder name as the billing address name.
+                    profile.setFullName(
+                            card.getIsLocal() ? mNameField.getValue().toString() : card.getName());
+                }
+                final AutofillAddress editAddress = new AutofillAddress(mContext, profile);
                 mAddressEditor.edit(editAddress, new Callback<AutofillAddress>() {
                     @Override
                     public void onResult(AutofillAddress billingAddress) {
-                        if (billingAddress == null || !billingAddress.isComplete()) {
+                        if (!billingAddress.isComplete()) {
                             // User cancelled out of the add or edit flow. Restore the selection
                             // to the card's billing address, if any, else clear the selection.
                             if (mBillingAddressField.getDropdownKeys().contains(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebOptInActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebOptInActivity.java
deleted file mode 100644
index 2c99e1d..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebOptInActivity.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015 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.
-
-package org.chromium.chrome.browser.physicalweb;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.text.SpannableString;
-import android.text.TextPaint;
-import android.text.method.LinkMovementMethod;
-import android.text.style.ClickableSpan;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager;
-import org.chromium.ui.text.SpanApplier;
-import org.chromium.ui.text.SpanApplier.SpanInfo;
-
-/**
- * This activity invites the user to opt-in to the Physical Web feature.
- */
-public class PhysicalWebOptInActivity extends AppCompatActivity {
-    private static final String EXTRA_CUSTOM_TABS_SESSION =
-            "android.support.customtabs.extra.SESSION";
-    private static final String PHYSICAL_WEB_LEARN_MORE_URL =
-            "https://support.google.com/chrome/answer/6239299/";
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.physical_web_optin);
-
-        TextView description = (TextView) findViewById(R.id.physical_web_optin_description);
-        description.setMovementMethod(LinkMovementMethod.getInstance());
-        description.setText(getDescriptionText());
-
-        Button declineButton = (Button) findViewById(R.id.physical_web_decline);
-        declineButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                PhysicalWebUma.onOptInDeclineButtonPressed();
-                PrivacyPreferencesManager.getInstance().setPhysicalWebEnabled(false);
-                finish();
-            }
-        });
-
-        Button enableButton = (Button) findViewById(R.id.physical_web_enable);
-        enableButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                PhysicalWebUma.onOptInEnableButtonPressed();
-                PrivacyPreferencesManager.getInstance().setPhysicalWebEnabled(true);
-                finish();
-            }
-        });
-    }
-
-    private SpannableString getDescriptionText() {
-        return SpanApplier.applySpans(
-                getString(R.string.physical_web_optin_description),
-                new SpanInfo("<learnmore>", "</learnmore>", new ClickableSpan() {
-                    @Override
-                    public void onClick(View v) {
-                        Intent intent = new Intent(Intent.ACTION_VIEW,
-                                Uri.parse(PHYSICAL_WEB_LEARN_MORE_URL));
-                        // Add the SESSION extra to indicate we want a Chrome custom tab. This
-                        // allows the help page to open in the same task as the opt-in activity so
-                        // they can share a back stack.
-                        String session = null;
-                        intent.putExtra(EXTRA_CUSTOM_TABS_SESSION, session);
-                        PhysicalWebOptInActivity.this.startActivity(intent);
-                    }
-
-                    @Override
-                    public void updateDrawState(TextPaint ds) {
-                        // Color links but do not underline them.
-                        ds.setColor(ds.linkColor);
-                    }
-                }));
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index 7f23342..d47e06c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -105,7 +105,6 @@
 import org.chromium.printing.PrintingControllerImpl;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.base.PageTransition;
-import org.chromium.ui.base.ViewAndroidDelegate;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.mojom.WindowOpenDisposition;
 
@@ -375,26 +374,6 @@
 
     private class TabContentViewClient extends ContentViewClient {
         @Override
-        public void onBackgroundColorChanged(int color) {
-            Tab.this.onBackgroundColorChanged(color);
-        }
-
-        @Override
-        public void onTopControlsChanged(float topControlsOffsetY, float topContentOffsetY) {
-            super.onTopControlsChanged(topControlsOffsetY, topContentOffsetY);
-            onOffsetsChanged(topControlsOffsetY, mPreviousBottomControlsOffsetY,
-                    topContentOffsetY, isShowingSadTab());
-        }
-
-        @Override
-        public void onBottomControlsChanged(float bottomControlsOffsetY,
-                float bottomContentOffsetY) {
-            super.onBottomControlsChanged(bottomControlsOffsetY, bottomContentOffsetY);
-            onOffsetsChanged(mPreviousTopControlsOffsetY, bottomControlsOffsetY,
-                    mPreviousContentOffsetY, isShowingSadTab());
-        }
-
-        @Override
         public void onImeEvent() {
             // Some text was set in the page. Don't reuse it if a tab is
             // open from the same external application, we might lose some
@@ -409,33 +388,6 @@
         }
 
         @Override
-        public int getSystemWindowInsetLeft() {
-            ChromeActivity activity = getActivity();
-            if (activity != null && activity.getInsetObserverView() != null) {
-                return activity.getInsetObserverView().getSystemWindowInsetsLeft();
-            }
-            return 0;
-        }
-
-        @Override
-        public int getSystemWindowInsetTop() {
-            ChromeActivity activity = getActivity();
-            if (activity != null && activity.getInsetObserverView() != null) {
-                return activity.getInsetObserverView().getSystemWindowInsetsTop();
-            }
-            return 0;
-        }
-
-        @Override
-        public int getSystemWindowInsetRight() {
-            ChromeActivity activity = getActivity();
-            if (activity != null && activity.getInsetObserverView() != null) {
-                return activity.getInsetObserverView().getSystemWindowInsetsRight();
-            }
-            return 0;
-        }
-
-        @Override
         public int getSystemWindowInsetBottom() {
             ChromeActivity activity = getActivity();
             if (activity != null && activity.getInsetObserverView() != null) {
@@ -1642,7 +1594,7 @@
         ContentView cv = ContentView.createContentView(mThemedApplicationContext, cvc);
         cv.setContentDescription(mThemedApplicationContext.getResources().getString(
                 R.string.accessibility_content_view));
-        cvc.initialize(ViewAndroidDelegate.createBasicDelegate(cv), cv, webContents,
+        cvc.initialize(new TabViewAndroidDelegate(this, cv), cv, webContents,
                 getWindowAndroid());
         ChromeActionModeCallback actionModeCallback = new ChromeActionModeCallback(
                 mThemedApplicationContext, this, cvc.getActionModeCallbackHelper());
@@ -2226,7 +2178,7 @@
      * Called when the background color for the content changes.
      * @param color The current for the background.
      */
-    protected void onBackgroundColorChanged(int color) {
+    void onBackgroundColorChanged(int color) {
         for (TabObserver observer : mObservers) observer.onBackgroundColorChanged(this, color);
     }
 
@@ -2526,19 +2478,21 @@
      * Called when offset values related with fullscreen functionality has been changed by the
      * compositor.
      * @param topControlsOffsetY The Y offset of the top controls in physical pixels.
+     *    {@code Float.NaN} if the value is invalid and the cached value should be used.
      * @param bottomControlsOffsetY The Y offset of the bottom controls in physical pixels.
+     *    {@code Float.NaN} if the value is invalid and the cached value should be used.
      * @param contentOffsetY The Y offset of the content in physical pixels.
-     * @param isNonFullscreenPage Whether a current page is non-fullscreen page or not.
      */
-    private void onOffsetsChanged(
-            float topControlsOffsetY, float bottomControlsOffsetY, float contentOffsetY,
-            boolean isNonFullscreenPage) {
-        mPreviousTopControlsOffsetY = topControlsOffsetY;
-        mPreviousBottomControlsOffsetY = bottomControlsOffsetY;
+    void onOffsetsChanged(
+            float topControlsOffsetY, float bottomControlsOffsetY, float contentOffsetY) {
+        if (!Float.isNaN(topControlsOffsetY)) mPreviousTopControlsOffsetY = topControlsOffsetY;
+        if (!Float.isNaN(bottomControlsOffsetY)) {
+            mPreviousBottomControlsOffsetY = bottomControlsOffsetY;
+        }
         mPreviousContentOffsetY = contentOffsetY;
 
         if (mFullscreenManager == null) return;
-        if (isNonFullscreenPage || isNativePage()) {
+        if (isShowingSadTab() || isNativePage()) {
             mFullscreenManager.setPositionsForTabToNonFullscreen();
         } else {
             mFullscreenManager.setPositionsForTab(topControlsOffsetY, bottomControlsOffsetY,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
new file mode 100644
index 0000000..e4689e0e
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
@@ -0,0 +1,59 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tab;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.view.ViewGroup;
+
+import org.chromium.base.Log;
+import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.ui.base.ViewAndroidDelegate;
+
+/**
+ * Implementation of the abstract class {@link ViewAndroidDelegate} for Chrome.
+ */
+class TabViewAndroidDelegate extends ViewAndroidDelegate {
+    /** Used for logging. */
+    private static final String TAG = "TabVAD";
+
+    private final Tab mTab;
+    private final ViewGroup mContainerView;
+
+    TabViewAndroidDelegate(Tab tab, ViewGroup containerView) {
+        mTab = tab;
+        mContainerView = containerView;
+    }
+
+    @Override
+    public void onBackgroundColorChanged(int color) {
+        mTab.onBackgroundColorChanged(color);
+    }
+
+    @Override
+    public void onTopControlsChanged(float topControlsOffsetY, float topContentOffsetY) {
+        mTab.onOffsetsChanged(topControlsOffsetY, Float.NaN, topContentOffsetY);
+    }
+
+    @Override
+    public void onBottomControlsChanged(float bottomControlsOffsetY, float bottomContentOffsetY) {
+        mTab.onOffsetsChanged(Float.NaN, bottomControlsOffsetY, Float.NaN);
+    }
+
+    @Override
+    public void startContentIntent(Intent intent, String intentUrl, boolean isMainFrame) {
+        try {
+            RecordUserAction.record("Android.ContentDetectorActivated");
+            mContainerView.getContext().startActivity(intent);
+        } catch (ActivityNotFoundException ex) {
+            Log.w(TAG, "No application can handle %s", intentUrl);
+        }
+    }
+
+    @Override
+    public ViewGroup getContainerView() {
+        return mContainerView;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
index bab35e7..7090118b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -303,6 +303,7 @@
             case FROM_CHROME_UI:
             case FROM_LONGPRESS_FOREGROUND:
             case FROM_LONGPRESS_BACKGROUND:
+            case FROM_LAUNCHER_SHORTCUT:
                 transition = PageTransition.AUTO_TOPLEVEL;
                 break;
             default:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java
index ee7ea065..29b52a8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java
@@ -55,7 +55,10 @@
         /**
          * Changed windows by moving from one activity to another. Will be opened in the foreground.
          */
-        FROM_REPARENTING
+        FROM_REPARENTING,
+
+        /** Opened from a launcher shortcut. */
+        FROM_LAUNCHER_SHORTCUT,
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapper.java
index b8704e2..9b33d71e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapper.java
@@ -19,7 +19,8 @@
     /**
      * Creates a VrShellImpl instance.
      */
-    public VrShell createVrShell(CompositorViewHolder compositorViewHolder);
+    public VrShell createVrShell(VrShellDelegate delegate,
+            CompositorViewHolder compositorViewHolder);
 
     /**
      * Creates a VrDaydreamApImpl instance.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapperImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapperImpl.java
index dfba89bf..8190e04d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapperImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrClassesWrapperImpl.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.vr_shell;
 
-import android.app.Activity;
 import android.content.Context;
 import android.os.StrictMode;
 
@@ -13,6 +12,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.UsedByReflection;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 
 /**
@@ -25,7 +25,7 @@
     private final Context mContext;
 
     @UsedByReflection("VrShellDelegate.java")
-    public VrClassesWrapperImpl(Activity activity) {
+    public VrClassesWrapperImpl(ChromeActivity activity) {
         mContext = activity;
     }
 
@@ -39,7 +39,7 @@
     public NonPresentingGvrContext createNonPresentingGvrContext() {
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
         try {
-            return new NonPresentingGvrContextImpl((Activity) mContext);
+            return new NonPresentingGvrContextImpl((ChromeActivity) mContext);
         } catch (Exception ex) {
             Log.e(TAG, "Unable to instantiate NonPresentingGvrContextImpl", ex);
             return null;
@@ -49,10 +49,11 @@
     }
 
     @Override
-    public VrShell createVrShell(CompositorViewHolder compositorViewHolder) {
+    public VrShell createVrShell(VrShellDelegate delegate,
+            CompositorViewHolder compositorViewHolder) {
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
         try {
-            return new VrShellImpl((Activity) mContext, compositorViewHolder);
+            return new VrShellImpl((ChromeActivity) mContext, delegate, compositorViewHolder);
         } catch (Exception ex) {
             Log.e(TAG, "Unable to instantiate VrShellImpl", ex);
             return null;
@@ -73,6 +74,6 @@
 
     @Override
     public void setVrModeEnabled(boolean enabled) {
-        AndroidCompat.setVrModeEnabled((Activity) mContext, enabled);
+        AndroidCompat.setVrModeEnabled((ChromeActivity) mContext, enabled);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
index e5571dc..6184b59 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
@@ -16,12 +16,7 @@
     /**
      * Performs native VrShell initialization.
      */
-    void initializeNative(Tab currentTab, VrShellDelegate delegate, boolean forWebVR);
-
-    /**
-     * Swaps to the designated tab.
-     */
-    void swapTab(Tab currentTab);
+    void initializeNative(Tab currentTab, boolean forWebVR);
 
     /**
      * Pauses VrShell.
@@ -47,29 +42,4 @@
      * Returns the GVRLayout as a FrameLayout.
      */
     FrameLayout getContainer();
-
-    /**
-     * Sets a callback to be run when the close button is tapped.
-     */
-    void setCloseButtonListener(Runnable runner);
-
-    /**
-     * Handles a change in page load progress.
-     */
-    void onLoadProgressChanged(double progress);
-
-    /**
-     * Passes a list of tabs to the VR UI.
-     */
-    void onTabListCreated(Tab[] mainTabs, Tab[] incognitoTabs);
-
-    /**
-     * Handles updating the UI for a tab that's had its title changed.
-     */
-    void onTabUpdated(boolean incognito, int id, String title);
-
-    /**
-     * Handles updating the UI for a tab that's been removed.
-     */
-    void onTabRemoved(boolean incognito, int id);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 649c19e..0f77bac 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -10,6 +10,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Handler;
 import android.os.StrictMode;
@@ -29,16 +30,11 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -84,9 +80,6 @@
     private static final long REENTER_VR_TIMEOUT_MS = 1000;
 
     private final ChromeTabbedActivity mActivity;
-    private TabObserver mTabObserver;
-    private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
-    private TabModelSelectorObserver mTabModelSelectorObserver;
     private Intent mEnterVRIntent;
 
     @VrSupportLevel
@@ -99,10 +92,11 @@
     private VrCoreVersionChecker mVrCoreVersionChecker;
 
     private boolean mInVr;
+    private boolean mEnteringVr;
+    private boolean mPaused;
     private int mRestoreSystemUiVisibilityFlag = -1;
-    private int mRestoreOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    private Integer mRestoreOrientation = null;
     private long mNativeVrShellDelegate;
-    private Tab mTab;
     private boolean mRequestedWebVR;
     private long mLastVRExit;
     private boolean mListeningForWebVrActivate;
@@ -124,12 +118,6 @@
         if (mVrClassesWrapper == null || !isVrCoreCompatible()) {
             mVrSupportLevel = VR_NOT_AVAILABLE;
             mEnterVRIntent = null;
-            mTabObserver = null;
-            if (mTabModelSelectorTabObserver != null) {
-                mTabModelSelectorTabObserver.destroy();
-                mTabModelSelectorTabObserver = null;
-            }
-            mTabModelSelectorObserver = null;
             return;
         }
 
@@ -150,12 +138,6 @@
                                 Build.VERSION_CODES.KITKAT)) {
                     mVrSupportLevel = VR_NOT_AVAILABLE;
                     mEnterVRIntent = null;
-                    mTabObserver = null;
-                    if (mTabModelSelectorTabObserver != null) {
-                        mTabModelSelectorTabObserver.destroy();
-                        mTabModelSelectorTabObserver = null;
-                    }
-                    mTabModelSelectorObserver = null;
                     return;
                 }
             }
@@ -165,45 +147,6 @@
             mEnterVRIntent =
                     mVrDaydreamApi.createVrIntent(new ComponentName(mActivity, VR_ACTIVITY_ALIAS));
         }
-
-        if (mTabObserver == null) {
-            mTabObserver = new EmptyTabObserver() {
-                @Override
-                public void onContentChanged(Tab tab) {
-                    if (tab.getNativePage() != null || tab.isShowingSadTab()) {
-                        // For now we don't handle native pages. crbug.com/661609.
-                        shutdownVR(false, mVrSupportLevel == VR_DAYDREAM /* showTransition */);
-                    }
-                }
-
-                @Override
-                public void onWebContentsSwapped(
-                        Tab tab, boolean didStartLoad, boolean didFinishLoad) {
-                    // swapTab might be slightly overkill, but best to be on the safe side.
-                    mVrShell.swapTab(tab);
-                }
-
-                @Override
-                public void onLoadProgressChanged(Tab tab, int progress) {
-                    if (!mInVr) return;
-                    mVrShell.onLoadProgressChanged(progress / 100.0);
-                }
-            };
-        }
-        if (mTabModelSelectorObserver == null) {
-            mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
-                @Override
-                public void onChange() {
-                    swapToForegroundTab();
-                }
-
-                @Override
-                public void onNewTabCreated(Tab tab) {
-                    mVrShell.onTabUpdated(tab.isIncognito(), tab.getId(), tab.getTitle());
-                }
-            };
-        }
-
         mVrSupportLevel = mVrDaydreamApi.isDaydreamReadyDevice() ? VR_DAYDREAM : VR_CARDBOARD;
     }
 
@@ -235,7 +178,7 @@
                     (Class<? extends VrClassesWrapper>) Class.forName(
                             "org.chromium.chrome.browser.vr_shell.VrClassesWrapperImpl");
             Constructor<?> vrClassesBuilderConstructor =
-                    vrClassesBuilderClass.getConstructor(Activity.class);
+                    vrClassesBuilderClass.getConstructor(ChromeActivity.class);
             return (VrClassesWrapper) vrClassesBuilderConstructor.newInstance(mActivity);
         } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                 | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) {
@@ -265,130 +208,74 @@
             mVrDaydreamApi.launchVrHomescreen();
             return;
         }
-        enterVR();
+
+        if (mInVr) {
+            setEnterVRResult(true);
+            return;
+        }
+        if (!canEnterVR(mActivity.getActivityTab())) {
+            setEnterVRResult(false);
+            return;
+        }
+        if (mPaused) {
+            // We can't enter VR before the application resumes, or we encounter bizarre crashes
+            // related to gpu surfaces. Set this flag to enter VR on the next resume.
+            prepareToEnterVR();
+            mEnteringVr = true;
+        } else {
+            enterVR();
+        }
+    }
+
+    private void prepareToEnterVR() {
+        if (mRestoreOrientation == null) {
+            mRestoreOrientation = mActivity.getRequestedOrientation();
+        }
+        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+        setupVrModeWindowFlags();
     }
 
     private void enterVR() {
-        if (mInVr) {
-            setEnterVRResult(true, mRequestedWebVR);
+        if (mActivity.getResources()
+                .getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
+            prepareToEnterVR();
+            new Handler().post(new Runnable() {
+                @Override
+                public void run() {
+                    enterVR();
+                }
+            });
             return;
         }
-
-        if (!canEnterVR(mActivity.getActivityTab())) {
-            setEnterVRResult(false, mRequestedWebVR);
-            return;
-        }
-
-        mRestoreOrientation = mActivity.getRequestedOrientation();
-        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-        setupVrModeWindowFlags();
-        final boolean requestedWebVR = mRequestedWebVR;
-        mRequestedWebVR = false;
-        // We need to post this to the end of the message queue so that the display properties can
-        // update in response to our request to enter landscape and hide the system UI.
-        new Handler().post(new Runnable() {
-            @Override
-            public void run() {
-                enterVRWithOrientationSet(requestedWebVR);
-            }
-        });
-    }
-
-    private void enterVRWithOrientationSet(boolean requestedWebVR) {
+        mEnteringVr = false;
         if (!createVrShell()) {
-            mActivity.setRequestedOrientation(mRestoreOrientation);
+            if (mRestoreOrientation != null) mActivity.setRequestedOrientation(mRestoreOrientation);
+            mRestoreOrientation = null;
             clearVrModeWindowFlags();
-            setEnterVRResult(false, requestedWebVR);
+            setEnterVRResult(false);
             return;
         }
         mVrClassesWrapper.setVrModeEnabled(true);
         mInVr = true;
-        mTab = mActivity.getActivityTab();
-        mTab.addObserver(mTabObserver);
+
         addVrViews();
-        mVrShell.initializeNative(mTab, this, requestedWebVR);
-        mVrShell.setCloseButtonListener(new Runnable() {
-            @Override
-            public void run() {
-                exitVRIfNecessary(false);
-            }
-        });
+        mVrShell.initializeNative(mActivity.getActivityTab(), mRequestedWebVR);
         // onResume needs to be called on GvrLayout after initialization to make sure DON flow work
         // properly.
         mVrShell.resume();
-        mTab.updateFullscreenEnabledState();
-        setEnterVRResult(true, requestedWebVR);
-        createTabList();
-        mActivity.getTabModelSelector().addObserver(mTabModelSelectorObserver);
-        createTabModelSelectorTabObserver();
+
+        setEnterVRResult(true);
     }
 
-    private void createTabModelSelectorTabObserver() {
-        assert mTabModelSelectorTabObserver == null;
-        mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(
-                mActivity.getTabModelSelector()) {
-            @Override
-            public void onTitleUpdated(Tab tab) {
-                mVrShell.onTabUpdated(tab.isIncognito(), tab.getId(), tab.getTitle());
-            }
-
-            @Override
-            public void onClosingStateChanged(Tab tab, boolean closing) {
-                if (closing) {
-                    mVrShell.onTabRemoved(tab.isIncognito(), tab.getId());
-                } else {
-                    mVrShell.onTabUpdated(tab.isIncognito(), tab.getId(), tab.getTitle());
-                }
-            }
-
-            @Override
-            public void onDestroyed(Tab tab) {
-                mVrShell.onTabRemoved(tab.isIncognito(), tab.getId());
-            }
-        };
-    }
-
-    private void setEnterVRResult(boolean success, boolean requestedWebVR) {
-        if (requestedWebVR) nativeSetPresentResult(mNativeVrShellDelegate, success);
+    private void setEnterVRResult(boolean success) {
+        if (mRequestedWebVR) nativeSetPresentResult(mNativeVrShellDelegate, success);
         if (!success && !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent())) {
             mVrClassesWrapper.setVrModeEnabled(false);
         }
         mRequestedWebVR = false;
     }
 
-    private void swapToForegroundTab() {
-        Tab tab = mActivity.getActivityTab();
-        if (tab == mTab) return;
-        if (!canEnterVR(tab)) {
-            forceExitVr();
-            return;
-        }
-        mTab.removeObserver(mTabObserver);
-        mTab.updateFullscreenEnabledState();
-
-        mVrShell.swapTab(tab);
-        mTab = tab;
-        mTab.addObserver(mTabObserver);
-        mTab.updateFullscreenEnabledState();
-    }
-
-    private void createTabList() {
-        TabModel main = mActivity.getTabModelSelector().getModel(false);
-        int count = main.getCount();
-        Tab[] mainTabs = new Tab[count];
-        for (int i = 0; i < count; ++i) {
-            mainTabs[i] = main.getTabAt(i);
-        }
-        TabModel incognito = mActivity.getTabModelSelector().getModel(true);
-        count = incognito.getCount();
-        Tab[] incognitoTabs = new Tab[count];
-        for (int i = 0; i < count; ++i) {
-            incognitoTabs[i] = incognito.getTabAt(i);
-        }
-        mVrShell.onTabListCreated(mainTabs, incognitoTabs);
-    }
-
-    private boolean canEnterVR(Tab tab) {
+    /* package */ boolean canEnterVR(Tab tab) {
         if (!LibraryLoader.isInitialized()) {
             return false;
         }
@@ -454,7 +341,6 @@
             // Avoid using launchInVr which would trigger DON flow regardless current viewer type
             // due to the lack of support for unexported activities.
             enterVR();
-            return ENTER_VR_REQUESTED;
         } else {
             if (!mVrDaydreamApi.launchInVr(getPendingEnterVRIntent())) return ENTER_VR_CANCELLED;
         }
@@ -468,33 +354,32 @@
         if (mVrSupportLevel == VR_CARDBOARD) {
             // Transition screen is not available for Cardboard only (non-Daydream) devices.
             // TODO(bshe): Fix this once b/33490788 is fixed.
-            shutdownVR(false, false);
+            shutdownVR(false /* isPausing */, false /* showTransition */);
         } else {
             // TODO(bajones): Once VR Shell can be invoked outside of WebVR this
             // should no longer exit the shell outright. Need a way to determine
             // how VrShell was created.
-            shutdownVR(false, !isVrShellEnabled());
+            shutdownVR(false /* isPausing */, !isVrShellEnabled() /* showTransition */);
         }
         return true;
     }
 
-    @CalledByNative
-    private void forceExitVr() {
-        shutdownVR(false, true);
-    }
-
     /**
      * Resumes VR Shell.
      */
     public void maybeResumeVR() {
+        mPaused = false;
         if (mVrSupportLevel == VR_NOT_AVAILABLE) return;
         if (mVrSupportLevel == VR_DAYDREAM
                 && (isVrShellEnabled() || mListeningForWebVrActivateBeforePause)) {
             registerDaydreamIntent();
         }
-        // If this is still set, it means the user backed out of the DON flow, and we won't be
-        // receiving an intent from daydream.
-        if (mRequestedWebVR) {
+
+        if (mEnteringVr) {
+            enterVR();
+        } else if (mRequestedWebVR) {
+            // If this is still set, it means the user backed out of the DON flow, and we won't be
+            // receiving an intent from daydream.
             nativeSetPresentResult(mNativeVrShellDelegate, false);
             mRequestedWebVR = false;
         }
@@ -526,6 +411,7 @@
      * Pauses VR Shell.
      */
     public void maybePauseVR() {
+        mPaused = true;
         if (mVrSupportLevel == VR_NOT_AVAILABLE) return;
 
         if (mVrSupportLevel == VR_DAYDREAM) {
@@ -545,17 +431,16 @@
         // TODO(mthiesse): When VR Shell lives in its own activity, and integrates with Daydream
         // home, pause instead of exiting VR here. For now, because VR Apps shouldn't show up in the
         // non-VR recents, and we don't want ChromeTabbedActivity disappearing, exit VR.
-        exitVRIfNecessary(true);
+        shutdownVR(true /* isPausing */, false /* showTransition */);
     }
 
     /**
-     * Exits the current VR mode (WebVR or VRShell)
-     * @return Whether or not we exited VR.
+     * See {@link ChromeActivity#handleBackPressed}
      */
-    public boolean exitVRIfNecessary(boolean isPausing) {
+    public boolean onBackPressed() {
         if (mVrSupportLevel == VR_NOT_AVAILABLE) return false;
         if (!mInVr) return false;
-        shutdownVR(isPausing, false);
+        shutdownVR(false /* isPausing */, false /* showTransition */);
         return true;
     }
 
@@ -619,28 +504,25 @@
     /**
      * Exits VR Shell, performing all necessary cleanup.
      */
-    private void shutdownVR(boolean isPausing, boolean showTransition) {
+    /* package */ void shutdownVR(boolean isPausing, boolean showTransition) {
         if (!mInVr) return;
+        mInVr = false;
         mRequestedWebVR = false;
+        boolean transition = mVrSupportLevel == VR_DAYDREAM && showTransition;
         if (!isPausing) {
-            if (!showTransition || !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent())) {
+            if (!transition || !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent())) {
                 mVrClassesWrapper.setVrModeEnabled(false);
             }
         } else {
             mVrClassesWrapper.setVrModeEnabled(false);
             mLastVRExit = SystemClock.uptimeMillis();
         }
-        mActivity.getTabModelSelector().removeObserver(mTabModelSelectorObserver);
-        mTabModelSelectorTabObserver.destroy();
-        mTabModelSelectorTabObserver = null;
-        mActivity.setRequestedOrientation(mRestoreOrientation);
+        if (mRestoreOrientation != null) mActivity.setRequestedOrientation(mRestoreOrientation);
+        mRestoreOrientation = null;
         mVrShell.pause();
         removeVrViews();
         clearVrModeWindowFlags();
         destroyVrShell();
-        mInVr = false;
-        mTab.removeObserver(mTabObserver);
-        mTab.updateFullscreenEnabledState();
         mActivity.getFullscreenManager().setPositionsForTabToNonFullscreen();
     }
 
@@ -654,7 +536,7 @@
 
     private boolean createVrShell() {
         if (mVrClassesWrapper == null) return false;
-        mVrShell = mVrClassesWrapper.createVrShell(mActivity.getCompositorViewHolder());
+        mVrShell = mVrClassesWrapper.createVrShell(this, mActivity.getCompositorViewHolder());
         return mVrShell != null;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
index 31881cd..203ccc7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.vr_shell;
 
 import android.annotation.SuppressLint;
-import android.app.Activity;
 import android.graphics.Point;
 import android.os.StrictMode;
 import android.view.MotionEvent;
@@ -23,13 +22,20 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.WebContentsFactory;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
+import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
+import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content_public.browser.WebContents;
@@ -61,11 +67,17 @@
     private static final float DEFAULT_UI_WIDTH = 1920f;
     private static final float DEFAULT_UI_HEIGHT = 1080f;
 
-    private final Activity mActivity;
+    private final ChromeActivity mActivity;
+    private final VrShellDelegate mDelegate;
     private final CompositorViewHolder mCompositorViewHolder;
     private final VirtualDisplayAndroid mContentVirtualDisplay;
     private final VirtualDisplayAndroid mUiVirtualDisplay;
     private final TabRedirectHandler mTabRedirectHandler;
+    private final TabObserver mTabObserver;
+    private final TabModelSelectorObserver mTabModelSelectorObserver;
+    private final View.OnTouchListener mTouchListener;
+    private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
+
 
     private long mNativeVrShell;
 
@@ -92,9 +104,11 @@
     private float mLastContentHeight;
     private float mLastContentDpr;
 
-    public VrShellImpl(Activity activity, CompositorViewHolder compositorViewHolder) {
+    public VrShellImpl(ChromeActivity activity, VrShellDelegate delegate,
+            CompositorViewHolder compositorViewHolder) {
         super(activity);
         mActivity = activity;
+        mDelegate = delegate;
         mCompositorViewHolder = compositorViewHolder;
         mTabModelSelector = mCompositorViewHolder.detachForVR();
         mUiCVCContainer = new FrameLayout(getContext()) {
@@ -122,6 +136,13 @@
 
         setPresentationView(mPresentationView);
 
+        getUiLayout().setCloseButtonListener(new Runnable() {
+            @Override
+            public void run() {
+                mDelegate.shutdownVR(false /* isPausing */, false /* showTransition */);
+            }
+        });
+
         DisplayAndroid primaryDisplay = DisplayAndroid.getNonMultiDisplay(activity);
         mContentVirtualDisplay = VirtualDisplayAndroid.createVirtualDisplay();
         mContentVirtualDisplay.setTo(primaryDisplay);
@@ -134,10 +155,59 @@
                 return true;
             }
         };
+
+        mTabObserver = new EmptyTabObserver() {
+            @Override
+            public void onContentChanged(Tab tab) {
+                if (tab.getNativePage() != null || tab.isShowingSadTab()) {
+                    // For now we don't handle native pages. crbug.com/661609.
+                    forceExitVr();
+                }
+            }
+
+            @Override
+            public void onWebContentsSwapped(
+                    Tab tab, boolean didStartLoad, boolean didFinishLoad) {
+                nativeSwapContents(mNativeVrShell, mContentCVC.getWebContents());
+                setContentCssSize(mLastContentWidth, mLastContentHeight, mLastContentDpr);
+            }
+
+            @Override
+            public void onLoadProgressChanged(Tab tab, int progress) {
+                if (mNativeVrShell == 0) return;
+                nativeOnLoadProgressChanged(mNativeVrShell, progress / 100.0);
+            }
+        };
+
+        mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
+            @Override
+            public void onChange() {
+                swapToForegroundTab();
+            }
+
+            @Override
+            public void onNewTabCreated(Tab tab) {
+                if (mNativeVrShell == 0) return;
+                nativeOnTabUpdated(mNativeVrShell, tab.isIncognito(), tab.getId(), tab.getTitle());
+            }
+        };
+
+        mTouchListener = new View.OnTouchListener() {
+            @Override
+            @SuppressLint("ClickableViewAccessibility")
+            public boolean onTouch(View v, MotionEvent event) {
+                if (!CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_VR_SHELL_DEV)
+                        && event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+                    nativeOnTriggerEvent(mNativeVrShell);
+                    return true;
+                }
+                return false;
+            }
+        };
     }
 
     @Override
-    public void initializeNative(Tab currentTab, VrShellDelegate delegate, boolean forWebVR) {
+    public void initializeNative(Tab currentTab, boolean forWebVR) {
         assert currentTab.getContentViewCore() != null;
         mTab = currentTab;
         mContentCVC = mTab.getContentViewCore();
@@ -152,7 +222,7 @@
 
         mNativeVrShell = nativeInit(mContentCVC.getWebContents(),
                 mContentVrWindowAndroid.getNativePointer(), mUiContents,
-                mUiVrWindowAndroid.getNativePointer(), forWebVR, delegate,
+                mUiVrWindowAndroid.getNativePointer(), forWebVR, mDelegate,
                 getGvrApi().getNativeGvrContext(), mReprojectedRendering);
 
         // Set the UI and content sizes before we load the UI.
@@ -167,18 +237,7 @@
 
         nativeLoadUIContent(mNativeVrShell);
 
-        mPresentationView.setOnTouchListener(new View.OnTouchListener() {
-            @Override
-            @SuppressLint("ClickableViewAccessibility")
-            public boolean onTouch(View v, MotionEvent event) {
-                if (!CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_VR_SHELL_DEV)
-                        && event.getActionMasked() == MotionEvent.ACTION_DOWN) {
-                    nativeOnTriggerEvent(mNativeVrShell);
-                    return true;
-                }
-                return false;
-            }
-        });
+        mPresentationView.setOnTouchListener(mTouchListener);
 
         uiContentView.setVisibility(View.VISIBLE);
         mUiCVC.onShow();
@@ -190,6 +249,48 @@
         mUiVrWindowAndroid.onVisibilityChanged(true);
 
         initializeTabForVR();
+        mTab.addObserver(mTabObserver);
+        mTab.updateFullscreenEnabledState();
+        createTabList();
+        mActivity.getTabModelSelector().addObserver(mTabModelSelectorObserver);
+        createTabModelSelectorTabObserver();
+    }
+
+    private void createTabList() {
+        assert mNativeVrShell != 0;
+        TabModel main = mTabModelSelector.getModel(false);
+        int count = main.getCount();
+        Tab[] mainTabs = new Tab[count];
+        for (int i = 0; i < count; ++i) {
+            mainTabs[i] = main.getTabAt(i);
+        }
+        TabModel incognito = mTabModelSelector.getModel(true);
+        count = incognito.getCount();
+        Tab[] incognitoTabs = new Tab[count];
+        for (int i = 0; i < count; ++i) {
+            incognitoTabs[i] = incognito.getTabAt(i);
+        }
+        nativeOnTabListCreated(mNativeVrShell, mainTabs, incognitoTabs);
+    }
+
+    private void swapToForegroundTab() {
+        Tab tab = mActivity.getActivityTab();
+        if (tab == mTab) return;
+        if (!mDelegate.canEnterVR(tab)) {
+            forceExitVr();
+            return;
+        }
+        mTab.removeObserver(mTabObserver);
+        restoreTabFromVR();
+        mTab.updateFullscreenEnabledState();
+
+        mTab = tab;
+        mContentCVC = mTab.getContentViewCore();
+        initializeTabForVR();
+        nativeSwapContents(mNativeVrShell, mContentCVC.getWebContents());
+        setContentCssSize(mLastContentWidth, mLastContentHeight, mLastContentDpr);
+        mTab.addObserver(mTabObserver);
+        mTab.updateFullscreenEnabledState();
     }
 
     private void initializeTabForVR() {
@@ -210,15 +311,10 @@
         mNonVrTabRedirectHandler = null;
     }
 
-    @Override
-    public void swapTab(final Tab newTab) {
-        restoreTabFromVR();
-        mTab = newTab;
-        mContentCVC = mTab.getContentViewCore();
-        initializeTabForVR();
-
-        nativeSwapContents(mNativeVrShell, mContentCVC.getWebContents());
-        setContentCssSize(mLastContentWidth, mLastContentHeight, mLastContentDpr);
+    // Exits VR, telling the user to remove their headset, and returning to Chromium.
+    @CalledByNative
+    public void forceExitVr() {
+        mDelegate.shutdownVR(false /* isPausing */, true /* showTransition */);
     }
 
     @CalledByNative
@@ -290,18 +386,14 @@
     }
 
     @Override
-    public void onLoadProgressChanged(double progress) {
-        if (mNativeVrShell != 0) {
-            nativeOnLoadProgressChanged(mNativeVrShell, progress);
-        }
-    }
-
-    @Override
     public void shutdown() {
         if (mNativeVrShell != 0) {
             nativeDestroy(mNativeVrShell);
             mNativeVrShell = 0;
         }
+        mTabModelSelector.removeObserver(mTabModelSelectorObserver);
+        mTabModelSelectorTabObserver.destroy();
+        mTab.removeObserver(mTabObserver);
         restoreTabFromVR();
         mUiContents.destroy();
         mContentVirtualDisplay.destroy();
@@ -336,11 +428,6 @@
     }
 
     @Override
-    public void setCloseButtonListener(Runnable runner) {
-        getUiLayout().setCloseButtonListener(runner);
-    }
-
-    @Override
     public void surfaceCreated(SurfaceHolder holder) {
         nativeSetSurface(mNativeVrShell, holder.getSurface());
     }
@@ -358,19 +445,32 @@
         // multiple times.
     }
 
-    @Override
-    public void onTabListCreated(Tab[] mainTabs, Tab[] incognitoTabs) {
-        nativeOnTabListCreated(mNativeVrShell, mainTabs, incognitoTabs);
-    }
+    private void createTabModelSelectorTabObserver() {
+        assert mTabModelSelectorTabObserver == null;
+        mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(mTabModelSelector) {
+            @Override
+            public void onTitleUpdated(Tab tab) {
+                if (mNativeVrShell == 0) return;
+                nativeOnTabUpdated(mNativeVrShell, tab.isIncognito(), tab.getId(), tab.getTitle());
+            }
 
-    @Override
-    public void onTabUpdated(boolean incognito, int id, String title) {
-        nativeOnTabUpdated(mNativeVrShell, incognito, id, title);
-    }
+            @Override
+            public void onClosingStateChanged(Tab tab, boolean closing) {
+                if (mNativeVrShell == 0) return;
+                if (closing) {
+                    nativeOnTabRemoved(mNativeVrShell, tab.isIncognito(), tab.getId());
+                } else {
+                    nativeOnTabUpdated(mNativeVrShell, tab.isIncognito(), tab.getId(),
+                            tab.getTitle());
+                }
+            }
 
-    @Override
-    public void onTabRemoved(boolean incognito, int id) {
-        nativeOnTabRemoved(mNativeVrShell, incognito, id);
+            @Override
+            public void onDestroyed(Tab tab) {
+                if (mNativeVrShell == 0) return;
+                nativeOnTabRemoved(mNativeVrShell, tab.isIncognito(), tab.getId());
+            }
+        };
     }
 
     private native long nativeInit(WebContents contentWebContents,
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index d11ff6a9..1dd39073 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -331,10 +331,10 @@
         Edit
       </message>
       <message name="IDS_AUTOFILL_MANAGE_WALLET_CARDS_URL" desc="URL for managing wallet credit cards" translateable="false">
-        https://wallet.google.com/manage/paymentMethods
+        https://payments.google.com/#paymentMethods
       </message>
       <message name="IDS_AUTOFILL_MANAGE_WALLET_ADDRESSES_URL" desc="URL for managing wallet addresses" translateable="false">
-        https://wallet.google.com/manage/addressBook
+        https://payments.google.com/#paymentMethods
       </message>
       <message name="IDS_AUTOFILL_FROM_GOOGLE_ACCOUNT_LONG" desc="Text that indicates an address or credit card came from Google servers.">
         From Google Payments
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index f3fe5c9..d0038dde 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -636,8 +636,6 @@
   "java/src/org/chromium/chrome/browser/omaha/MarketURLGetter.java",
   "java/src/org/chromium/chrome/browser/omaha/OmahaBase.java",
   "java/src/org/chromium/chrome/browser/omaha/OmahaClient.java",
-  "java/src/org/chromium/chrome/browser/omaha/OmahaDelegate.java",
-  "java/src/org/chromium/chrome/browser/omaha/OmahaDelegateImpl.java",
   "java/src/org/chromium/chrome/browser/omaha/RequestData.java",
   "java/src/org/chromium/chrome/browser/omaha/RequestFailureException.java",
   "java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java",
@@ -960,6 +958,7 @@
   "java/src/org/chromium/chrome/browser/tab/TabRedirectHandler.java",
   "java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java",
   "java/src/org/chromium/chrome/browser/tab/TabUma.java",
+  "java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java",
   "java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java",
   "java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java",
   "java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParams.java",
@@ -1317,6 +1316,7 @@
   "javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/media/router/MockMediaRouteProvider.java",
   "javatests/src/org/chromium/chrome/browser/media/ui/AutoplayMutedNotificationTest.java",
+  "javatests/src/org/chromium/chrome/browser/media/ui/NotificationActionsUpdatedTest.java",
   "javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java",
   "javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java",
   "javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationActionsUpdatedTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationActionsUpdatedTest.java
new file mode 100644
index 0000000..105203e8
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationActionsUpdatedTest.java
@@ -0,0 +1,163 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.media.ui;
+
+import android.support.test.filters.SmallTest;
+
+import org.chromium.base.ObserverList;
+import org.chromium.base.ThreadUtils;
+import org.chromium.blink.mojom.MediaSessionAction;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.test.ChromeActivityTestCaseBase;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
+import org.chromium.content_public.browser.MediaSession;
+import org.chromium.content_public.browser.MediaSessionObserver;
+import org.chromium.net.test.EmbeddedTestServer;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Test of media notifications to see whether the control buttons update when MediaSessionActions
+ * change or the tab navigates.
+ */
+public class NotificationActionsUpdatedTest extends ChromeActivityTestCaseBase<ChromeActivity> {
+    private static final int NOTIFICATION_ID = R.id.media_playback_notification;
+    private static final String SIMPLE_PAGE_URL = "/simple_page.html";
+
+    private Tab mTab;
+    private EmbeddedTestServer mTestServer;
+
+    public NotificationActionsUpdatedTest() {
+        super(ChromeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mTab = getActivity().getActivityTab();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mTestServer != null) mTestServer.stopAndDestroyServer();
+        super.tearDown();
+    }
+
+    @SmallTest
+    public void testActionsDefaultToNull() throws Throwable {
+        simulateMediaSessionStateChanged(mTab, true, false);
+        assertActionsMatch(new HashSet<Integer>());
+    }
+
+    @SmallTest
+    public void testActionPropagateProperly() throws Throwable {
+        simulateMediaSessionActionsChanged(mTab, buildActions());
+        simulateMediaSessionStateChanged(mTab, true, false);
+        assertActionsMatch(buildActions());
+    }
+
+    @SmallTest
+    public void testActionsResetAfterNavigation() throws Throwable {
+        loadUrl("about:blank");
+        simulateMediaSessionActionsChanged(mTab, buildActions());
+        simulateMediaSessionStateChanged(mTab, true, false);
+        assertActionsMatch(buildActions());
+
+        loadUrl("data:text/html;charset=utf-8,"
+                + "<html><head><title>title1</title></head><body/></html>");
+        assertActionsMatch(new HashSet<Integer>());
+    }
+
+    @SmallTest
+    public void testActionsPersistAfterInPageNavigation() throws Throwable {
+        ensureTestServer();
+        loadUrl(mTestServer.getURL(SIMPLE_PAGE_URL));
+        simulateMediaSessionActionsChanged(mTab, buildActions());
+        simulateMediaSessionStateChanged(mTab, true, false);
+        assertActionsMatch(buildActions());
+
+        loadUrl(mTestServer.getURL(SIMPLE_PAGE_URL + "#some-anchor"));
+        assertActionsMatch(buildActions());
+    }
+
+    @Override
+    public void startMainActivity() throws InterruptedException {
+        startMainActivityOnBlankPage();
+    }
+
+    private void simulateMediaSessionStateChanged(
+            final Tab tab, final boolean isControllable, final boolean isSuspended) {
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                @Override
+                public void run() {
+                    ObserverList.RewindableIterator<MediaSessionObserver> observers =
+                            MediaSession.fromWebContents(tab.getWebContents())
+                                    .getObserversForTesting();
+                    while (observers.hasNext()) {
+                        observers.next().mediaSessionStateChanged(isControllable, isSuspended);
+                    }
+                }
+            });
+    }
+
+    private void simulateMediaSessionActionsChanged(final Tab tab, final Set<Integer> actions) {
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                @Override
+                public void run() {
+                    ObserverList.RewindableIterator<MediaSessionObserver> observers =
+                            MediaSession.fromWebContents(tab.getWebContents())
+                            .getObserversForTesting();
+                    while (observers.hasNext()) {
+                        observers.next().mediaSessionActionsChanged(actions);
+                    }
+                }
+            });
+    }
+
+    private void assertActionsMatch(final Set<Integer> expectedActions) {
+        // The service might still not be created which delays the creation of the notification
+        // builder.
+        CriteriaHelper.pollUiThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                return MediaNotificationManager.getNotificationBuilderForTesting(NOTIFICATION_ID)
+                        != null;
+            }
+        });
+
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                @Override
+                public void run() {
+                    Set<Integer> observedActions =
+                            MediaNotificationManager
+                            .getMediaNotificationInfoForTesting(NOTIFICATION_ID)
+                            .mediaSessionActions;
+
+                    assertEquals(expectedActions, observedActions);
+                }
+            });
+    }
+
+    private void ensureTestServer() {
+        try {
+            mTestServer = EmbeddedTestServer.createAndStartServer(
+                getInstrumentation().getContext());
+        } catch (Exception e) {
+            fail("Failed to start test server");
+        }
+    }
+
+    private Set<Integer> buildActions() {
+        HashSet<Integer> actions = new HashSet<>();
+
+        actions.add(MediaSessionAction.PLAY);
+        actions.add(MediaSessionAction.PAUSE);
+        return actions;
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaClientTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaClientTest.java
index 6c40881..cb9e1e3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaClientTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaClientTest.java
@@ -4,14 +4,18 @@
 
 package org.chromium.chrome.browser.omaha;
 
-import android.app.Service;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
 import android.support.test.filters.SmallTest;
 import android.test.InstrumentationTestCase;
 
 import org.chromium.base.test.util.AdvancedMockContext;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.test.omaha.AttributeFinder;
 import org.chromium.chrome.test.omaha.MockRequestGenerator;
 import org.chromium.chrome.test.omaha.MockRequestGenerator.DeviceType;
 
@@ -24,75 +28,475 @@
 import java.net.MalformedURLException;
 import java.net.SocketTimeoutException;
 import java.net.URL;
-import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.LinkedList;
-import java.util.List;
 
 /**
  * Tests for the {@link OmahaClient}.
- * Tests override the original OmahaClient's functions with the MockOmahaClient, which
+ * Tests often override the original OmahaClient's functions with the HookedOmahaClient, which
  * provides a way to hook into functions to return values that would normally be provided by the
  * system, such as whether Chrome was installed through the system image.
  */
 public class OmahaClientTest extends InstrumentationTestCase {
-    private static class TimestampPair {
-        public long timestampNextRequest;
-        public long timestampNextPost;
+    private enum ServerResponse {
+        SUCCESS, FAILURE
+    }
 
-        public TimestampPair(long timestampNextRequest, long timestampNextPost) {
-            this.timestampNextRequest = timestampNextRequest;
-            this.timestampNextPost = timestampNextPost;
+    private enum ConnectionStatus {
+        RESPONDS, TIMES_OUT
+    }
+
+    private enum InstallEvent {
+        SEND, DONT_SEND
+    }
+
+    private enum PostStatus {
+        DUE, NOT_DUE
+    }
+
+    private AdvancedMockContext mContext;
+    private HookedOmahaClient mOmahaClient;
+
+    @Override
+    protected void setUp() {
+        Context targetContext = getInstrumentation().getTargetContext();
+        mContext = new AdvancedMockContext(targetContext);
+        mOmahaClient = HookedOmahaClient.create(mContext);
+    }
+
+    /**
+     * If a request exists during handleInitialize(), a POST Intent should be fired immediately.
+     */
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testInitializeWithRequest() {
+        mOmahaClient.registerNewRequest(10);
+
+        Intent intent = OmahaClient.createInitializeIntent(mContext);
+        mOmahaClient.onHandleIntent(intent);
+        assertTrue("OmahaClient has no registered request", mOmahaClient.hasRequest());
+        assertTrue("Alarm does not have the correct state", mOmahaClient.getRequestAlarmWasSet());
+        assertEquals("OmahaClient didn't post the request",
+                OmahaClient.POST_RESULT_SCHEDULED, mOmahaClient.mPostResult);
+    }
+
+    /**
+     * If a request doesn't exist during handleInitialize(), no intent should be fired.
+     */
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testInitializeWithoutRequest() {
+        Intent intent = OmahaClient.createInitializeIntent(mContext);
+        mOmahaClient.onHandleIntent(intent);
+        assertFalse("OmahaClient has a registered request", mOmahaClient.hasRequest());
+        assertTrue("Alarm does not have the correct state", mOmahaClient.getRequestAlarmWasSet());
+        assertEquals("OmahaClient called handlePostRequest", -1, mOmahaClient.mPostResult);
+    }
+
+    /**
+     * Catch situations where the install source isn't set prior to restoring a saved request.
+     */
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testInstallSourceSetBeforeRestoringRequest() {
+        // Plant a failed request.
+        Context targetContext = getInstrumentation().getTargetContext();
+        AdvancedMockContext mockContext = new AdvancedMockContext(targetContext);
+        SharedPreferences prefs = OmahaBase.getSharedPreferences(mockContext);
+        SharedPreferences.Editor editor = prefs.edit();
+        editor.putLong(OmahaBase.PREF_TIMESTAMP_OF_REQUEST, 0);
+        editor.putString(OmahaBase.PREF_PERSISTED_REQUEST_ID, "persisted_id");
+        editor.apply();
+
+        // Send it off and don't crash when the state is restored and the XML is generated.
+        HookedOmahaClient omahaClient = HookedOmahaClient.create(mockContext);
+        omahaClient.mMockScheduler.setCurrentTime(1000);
+        Intent postIntent = OmahaClient.createPostRequestIntent(mockContext);
+        omahaClient.onHandleIntent(postIntent);
+
+        // Check that the request was actually generated and tried to be sent.
+        MockConnection connection = omahaClient.getLastConnection();
+        assertTrue("Didn't try to make a connection.", connection.getSentRequest());
+        assertFalse("OmahaClient still has a registered request", omahaClient.hasRequest());
+        assertTrue("Failed to send request", omahaClient.getCumulativeFailedAttempts() == 0);
+    }
+
+    /**
+     * Makes sure that we don't generate a request if we don't have to.
+     */
+    @SmallTest
+    @Feature({"Omaha", "Main"})
+    public void testOmahaClientDoesNotGenerateRequest() {
+        // Change the time so the OmahaClient thinks no request is necessary.
+        mOmahaClient.mMockScheduler.setCurrentTime(-1000);
+        Intent intent = OmahaClient.createRegisterRequestIntent(mContext);
+        mOmahaClient.onHandleIntent(intent);
+        assertFalse("OmahaClient has a registered request", mOmahaClient.hasRequest());
+        assertEquals(-1, mOmahaClient.mPostResult);
+    }
+
+    /**
+     * Makes sure that firing a XML request triggers a post intent.
+     */
+    @SmallTest
+    @Feature({"Omaha", "Main"})
+    public void testOmahaClientRequestToPost() {
+        // Change the time so the OmahaClient thinks a request is overdue.
+        mOmahaClient.mMockScheduler.setCurrentTime(1000);
+        Intent intent = OmahaClient.createRegisterRequestIntent(mContext);
+        mOmahaClient.onHandleIntent(intent);
+        assertFalse("OmahaClient has no registered request", mOmahaClient.hasRequest());
+        assertEquals(OmahaClient.POST_RESULT_SENT, mOmahaClient.mPostResult);
+    }
+
+    /**
+     * Makes sure that incorrect timestamps are caught.
+     */
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testIncorrectDelays() {
+        // Set the time to be 2 days past epoch, then generate a request.
+        final long millisecondsPerDay = 86400000;
+        long currentTimestamp = millisecondsPerDay * 2;
+        mOmahaClient.mMockScheduler.setCurrentTime(currentTimestamp);
+        Intent intent = OmahaClient.createRegisterRequestIntent(mContext);
+        mOmahaClient.onHandleIntent(intent);
+
+        // Rewind the clock 2 days.
+        currentTimestamp -= millisecondsPerDay * 2;
+        mOmahaClient.mMockScheduler.setCurrentTime(currentTimestamp);
+
+        // Restore state and confirm that the post timestamp was reset, since it's larger than the
+        // exponential backoff delay.
+        HookedOmahaClient secondClient = HookedOmahaClient.create(mContext);
+        assertEquals("Post timestamp was not cleared.",
+                0, secondClient.getTimestampForNextPostAttempt());
+
+        // Confirm that the request timestamp was reset, since the next timestamp is more than
+        // a day away.
+        assertEquals("Request timestamp was not cleared.",
+                0, secondClient.getTimestampForNewRequest());
+    }
+
+    /**
+     * Checks that reading and writing out the preferences works.
+     */
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientFileIO() {
+        // Register and send a request, which saves timestamps to disk.
+        Intent intent = OmahaClient.createRegisterRequestIntent(mContext);
+        mOmahaClient.onHandleIntent(intent);
+
+        // The second OmahaClient should know the next timestamp.
+        HookedOmahaClient secondClient = HookedOmahaClient.create(mContext);
+        assertEquals("The next timestamp wasn't correct",
+                OmahaClient.MS_BETWEEN_REQUESTS, secondClient.getTimestampForNewRequest());
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostHandsetFailure() {
+        postRequestToServer(DeviceType.HANDSET, ServerResponse.FAILURE, ConnectionStatus.RESPONDS,
+                            InstallEvent.DONT_SEND, PostStatus.DUE);
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostHandsetSuccess() {
+        postRequestToServer(DeviceType.HANDSET, ServerResponse.SUCCESS, ConnectionStatus.RESPONDS,
+                            InstallEvent.DONT_SEND, PostStatus.DUE);
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostTabletFailure() {
+        postRequestToServer(DeviceType.TABLET, ServerResponse.FAILURE, ConnectionStatus.RESPONDS,
+                            InstallEvent.DONT_SEND, PostStatus.DUE);
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostTabletSuccess() {
+        postRequestToServer(DeviceType.TABLET, ServerResponse.SUCCESS, ConnectionStatus.RESPONDS,
+                            InstallEvent.DONT_SEND, PostStatus.DUE);
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostHandsetTimeout() {
+        postRequestToServer(DeviceType.HANDSET, ServerResponse.FAILURE, ConnectionStatus.TIMES_OUT,
+                            InstallEvent.DONT_SEND, PostStatus.DUE);
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostInstallEventSuccess() {
+        postRequestToServer(DeviceType.HANDSET, ServerResponse.SUCCESS, ConnectionStatus.RESPONDS,
+                            InstallEvent.SEND, PostStatus.DUE);
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostInstallEventFailure() {
+        postRequestToServer(DeviceType.HANDSET, ServerResponse.FAILURE, ConnectionStatus.RESPONDS,
+                            InstallEvent.SEND, PostStatus.DUE);
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testOmahaClientPostWhenNotDue() {
+        postRequestToServer(DeviceType.HANDSET, ServerResponse.FAILURE, ConnectionStatus.RESPONDS,
+                            InstallEvent.DONT_SEND, PostStatus.NOT_DUE);
+    }
+
+    /**
+     * Pretends to post a request to the Omaha server.
+     * @param deviceType Whether or not to use an app-ID indicating a tablet.
+     * @param response Whether the server acknowledged the request correctly.
+     * @param connectionStatus Whether the connection times out when it tries to contact the
+     *                         Omaha server.
+     * @param installType Whether we're sending an install event or not.
+     * @param postStatus Whether we're due for a POST or not.
+     */
+    public void postRequestToServer(DeviceType deviceType, ServerResponse response,
+            ConnectionStatus connectionStatus, InstallEvent installType, PostStatus postStatus) {
+        final boolean succeeded = response == ServerResponse.SUCCESS;
+        final boolean sentInstallEvent = installType == InstallEvent.SEND;
+
+        HookedOmahaClient omahaClient = new HookedOmahaClient(mContext, deviceType, response,
+                connectionStatus, false);
+        omahaClient.onCreate();
+        omahaClient.restoreState(mContext);
+
+        // Set whether or not we're sending the install event.
+        assertTrue("Should default to sending install event.", omahaClient.isSendInstallEvent());
+        omahaClient.setSendInstallEvent(installType == InstallEvent.SEND);
+        omahaClient.registerNewRequest(0);
+
+        // Set up the POST request.
+        if (postStatus == PostStatus.NOT_DUE) {
+            // Rewind the clock so that we don't send the request yet.
+            omahaClient.mMockScheduler.setCurrentTime(-1000);
+        }
+        Intent postIntent = OmahaClient.createPostRequestIntent(mContext);
+        omahaClient.onHandleIntent(postIntent);
+
+        assertTrue("hasRequest() returned wrong value", succeeded != omahaClient.hasRequest());
+        if (postStatus == PostStatus.NOT_DUE) {
+            // No POST attempt was made.
+            assertTrue("POST was attempted and failed.",
+                    omahaClient.getCumulativeFailedAttempts() == 0);
+            assertTrue("POST alarm wasn't set for reattempt", omahaClient.getPOSTAlarmWasSet());
+        } else {
+            // Since we start with no failures, the counter incrementing should indicate whether it
+            // succeeded or not.
+            assertEquals("Expected different outcome", succeeded,
+                    omahaClient.getCumulativeFailedAttempts() == 0);
+            assertTrue("Alarm state was changed when it shouldn't have been",
+                    succeeded != omahaClient.getPOSTAlarmWasSet());
+
+            // If we're sending an install event, we will immediately attempt to send a ping in a
+            // follow-up request.
+            int numExpectedRequests = succeeded && sentInstallEvent ? 2 : 1;
+            assertEquals("Didn't send the correct number of XML requests.", numExpectedRequests,
+                            omahaClient.getNumConnectionsMade());
+
+            MockConnection connection = omahaClient.getLastConnection();
+            assertEquals("Didn't try to make a connection.", true, connection.getSentRequest());
+
+            if (connectionStatus == ConnectionStatus.TIMES_OUT) {
+                // Several events shouldn't happen if the connection times out.
+                assertEquals("Retrieved response code when it should have bailed earlier.",
+                        0, connection.getNumTimesResponseCodeRetrieved());
+                assertFalse("Grabbed input stream when it should have bailed earlier.",
+                        connection.getGotInputStream());
+            }
+        }
+
+        // Check that the latest version and market URLs were saved correctly.
+        String expectedVersion = succeeded ? MockConnection.UPDATE_VERSION : "";
+        String expectedURL = succeeded ? MockConnection.STRIPPED_MARKET_URL : "";
+
+        // Make sure we properly parsed out the server's response.
+        assertEquals("Latest version numbers didn't match", expectedVersion,
+                VersionNumberGetter.getInstance().getLatestKnownVersion(mContext));
+        assertEquals(
+                "Market URL didn't match", expectedURL, MarketURLGetter.getMarketUrl(mContext));
+
+        // Check that the install event was sent properly.
+        if (sentInstallEvent) {
+            assertFalse("OmahaPingService is going to send another install <event>.",
+                    succeeded == omahaClient.isSendInstallEvent());
         }
     }
 
-    private static class MockOmahaDelegate extends OmahaDelegate {
-        private final List<Integer> mPostResults = new ArrayList<Integer>();
-        private final List<Boolean> mGenerateAndPostRequestResults = new ArrayList<Boolean>();
+    /**
+     * Test whether we're using request and session IDs properly for POSTs.
+     */
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testRequestAndSessionIDs() {
+        assertTrue("Should default to sending install event.", mOmahaClient.isSendInstallEvent());
 
+        // Send the POST request.
+        mOmahaClient.registerNewRequest(0);
+        Intent postIntent = OmahaClient.createPostRequestIntent(mContext);
+        mOmahaClient.onHandleIntent(postIntent);
+
+        // If we're sending an install event, we will immediately attempt to send a ping in a
+        // follow-up request.  These should have the same session ID, but different request IDs.
+        int numRequests = mOmahaClient.getNumConnectionsMade();
+
+        HashSet<String> sessionIDs = new HashSet<String>();
+        HashSet<String> requestIDs = new HashSet<String>();
+        for (int i = 0; i < numRequests; ++i) {
+            String request = mOmahaClient.getConnection(i).getOutputStreamContents();
+
+            String sessionID =
+                    new AttributeFinder(request, "request", "sessionid").getValue();
+            assertNotNull(sessionID);
+            sessionIDs.add(sessionID);
+
+            String requestID =
+                    new AttributeFinder(request, "request", "requestid").getValue();
+            assertNotNull(requestID);
+            requestIDs.add(requestID);
+        }
+        assertEquals("Session ID was not the same across all requests", 1,
+                sessionIDs.size());
+        assertEquals("Request ID was duplicated", numRequests, requestIDs.size());
+
+        // Send another XML request and make sure the IDs are all different.
+        assertFalse("OmahaPingService is going to send another install <event>.",
+                mOmahaClient.isSendInstallEvent());
+        mOmahaClient.registerNewRequest(0);
+        postIntent = OmahaClient.createPostRequestIntent(mContext);
+        mOmahaClient.onHandleIntent(postIntent);
+
+        assertEquals("Didn't send the correct number of XML requests.", numRequests + 1,
+                        mOmahaClient.getNumConnectionsMade());
+        String newRequest = mOmahaClient.getConnection(numRequests).getOutputStreamContents();
+
+        String newSessionID = new AttributeFinder(newRequest, "request", "sessionid").getValue();
+        assertNotNull(newSessionID);
+        assertFalse("Session ID was reused.", sessionIDs.contains(newSessionID));
+
+        String newRequestID = new AttributeFinder(newRequest, "request", "requestid").getValue();
+        assertNotNull(newRequestID);
+        assertFalse("Request ID was reused.", requestIDs.contains(newRequestID));
+    }
+
+    /**
+     * Checks to see that the header is added only for persisted XML requests.
+     */
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testHTTPHeaderForPersistedXMLRequest() {
+        final String xml = "<lorem ipsum=\"dolor\" />";
+        final long requestTimestamp = 0;
+        final long currentTimestamp = 11684;
+        final long currentTimestampInSeconds = currentTimestamp / 1000;
+
+        mOmahaClient.registerNewRequest(requestTimestamp);
+
+        assertTrue("Should default to sending install event.", mOmahaClient.isSendInstallEvent());
+        assertEquals("Shouldn't have any failed attempts.", 0,
+                mOmahaClient.getCumulativeFailedAttempts());
+
+        MockConnection connection = null;
+        try {
+            mOmahaClient.postRequest(currentTimestamp, xml);
+            connection = mOmahaClient.getLastConnection();
+        } catch (RequestFailureException e) {
+            fail();
+        }
+        assertEquals("Age property field was unexpectedly added.", null,
+                connection.getRequestPropertyField());
+        assertEquals("Age property value was unexpectedly set.", null,
+                connection.getRequestPropertyValue());
+
+        // Fail once, then check that the header is added.
+        mOmahaClient.getBackoffScheduler().increaseFailedAttempts();
+        try {
+            mOmahaClient.postRequest(currentTimestamp, xml);
+            connection = mOmahaClient.getLastConnection();
+        } catch (RequestFailureException e) {
+            fail();
+        }
+        assertEquals("Age property field was not added.", "X-RequestAge",
+                connection.getRequestPropertyField());
+        assertEquals("Age property value was incorrectly set.", currentTimestampInSeconds,
+                Long.parseLong(connection.getRequestPropertyValue()));
+
+        // Make sure the header isn't added if we're not sending an install ping.
+        mOmahaClient.setSendInstallEvent(false);
+        mOmahaClient.registerNewRequest(requestTimestamp);
+        mOmahaClient.getBackoffScheduler().increaseFailedAttempts();
+        try {
+            mOmahaClient.postRequest(currentTimestamp, xml);
+            connection = mOmahaClient.getLastConnection();
+        } catch (RequestFailureException e) {
+            fail();
+        }
+        assertEquals("Age property field was unexpectedly added.", null,
+                connection.getRequestPropertyField());
+        assertEquals("Age property value was unexpectedly set.", null,
+                connection.getRequestPropertyValue());
+    }
+
+    @SmallTest
+    @Feature({"Omaha"})
+    public void testInstallSource() {
+        HookedOmahaClient organicClient = new HookedOmahaClient(mContext, DeviceType.TABLET,
+                ServerResponse.SUCCESS, ConnectionStatus.RESPONDS, false);
+        String organicInstallSource = organicClient.determineInstallSource();
+        assertEquals("Install source should have been treated as organic.",
+                OmahaClient.INSTALL_SOURCE_ORGANIC, organicInstallSource);
+
+        HookedOmahaClient systemImageClient = new HookedOmahaClient(mContext, DeviceType.TABLET,
+                ServerResponse.SUCCESS, ConnectionStatus.RESPONDS, true);
+        String systemImageInstallSource = systemImageClient.determineInstallSource();
+        assertEquals("Install source should have been treated as system image.",
+                OmahaClient.INSTALL_SOURCE_SYSTEM, systemImageInstallSource);
+    }
+
+    /**
+     * OmahaClient that overrides simple methods for testing.
+     */
+    private static class HookedOmahaClient extends OmahaClient {
         private final boolean mIsOnTablet;
+        private final boolean mSendValidResponse;
         private final boolean mIsInForeground;
-        private final boolean mIsInSystemImage;
-        private final MockExponentialBackoffScheduler mMockScheduler;
-        private MockRequestGenerator mMockGenerator;
+        private final boolean mConnectionTimesOut;
+        private final boolean mInstalledOnSystemImage;
 
+        private MockExponentialBackoffScheduler mMockScheduler;
+        private RequestGenerator mMockGenerator;
+        private final LinkedList<MockConnection> mMockConnections;
+
+        private boolean mRequestAlarmWasSet;
         private int mNumUUIDsGenerated;
-        private long mNextScheduledTimestamp = -1;
+        private int mPostResult = -1;
 
-        private boolean mInstallEventWasSent;
-        private TimestampPair mTimestampsOnRegisterNewRequest;
-        private TimestampPair mTimestampsOnSaveState;
+        public static HookedOmahaClient create(Context context) {
+            HookedOmahaClient omahaClient = new HookedOmahaClient(context, DeviceType.TABLET,
+                    ServerResponse.SUCCESS, ConnectionStatus.RESPONDS, false);
+            omahaClient.onCreate();
+            omahaClient.restoreState(context);
+            return omahaClient;
+        }
 
-        MockOmahaDelegate(Context context, DeviceType deviceType, InstallSource installSource) {
-            super(context);
+        public HookedOmahaClient(Context context, DeviceType deviceType,
+                    ServerResponse serverResponse, ConnectionStatus connectionStatus,
+                    boolean installedOnSystemImage) {
+            attachBaseContext(context);
             mIsOnTablet = deviceType == DeviceType.TABLET;
+            mSendValidResponse = serverResponse == ServerResponse.SUCCESS;
             mIsInForeground = true;
-            mIsInSystemImage = installSource == InstallSource.SYSTEM_IMAGE;
-
-            mMockScheduler = new MockExponentialBackoffScheduler(OmahaBase.PREF_PACKAGE, context,
-                    OmahaClient.MS_POST_BASE_DELAY, OmahaClient.MS_POST_MAX_DELAY);
-        }
-
-        @Override
-        protected RequestGenerator createRequestGenerator(Context context) {
-            mMockGenerator = new MockRequestGenerator(
-                    context, mIsOnTablet ? DeviceType.TABLET : DeviceType.HANDSET);
-            return mMockGenerator;
-        }
-
-        @Override
-        public boolean isInSystemImage() {
-            return mIsInSystemImage;
-        }
-
-        @Override
-        MockExponentialBackoffScheduler getScheduler() {
-            return mMockScheduler;
-        }
-
-        @Override
-        protected String generateUUID() {
-            mNumUUIDsGenerated += 1;
-            return "UUID" + mNumUUIDsGenerated;
+            mConnectionTimesOut = connectionStatus == ConnectionStatus.TIMES_OUT;
+            mMockConnections = new LinkedList<MockConnection>();
+            mInstalledOnSystemImage = installedOnSystemImage;
         }
 
         @Override
@@ -101,85 +505,25 @@
         }
 
         @Override
-        void scheduleService(Service service, long nextTimestamp) {
-            mNextScheduledTimestamp = nextTimestamp;
+        public int getApplicationFlags() {
+            return mInstalledOnSystemImage ? ApplicationInfo.FLAG_SYSTEM : 0;
         }
 
         @Override
-        void onHandlePostRequestDone(int result, boolean installEventWasSent) {
-            mPostResults.add(result);
-            mInstallEventWasSent = installEventWasSent;
+        protected int handlePostRequest() {
+            mPostResult = super.handlePostRequest();
+            return mPostResult;
         }
 
-        @Override
-        void onRegisterNewRequestDone(long nextRequestTimestamp, long nextPostTimestamp) {
-            mTimestampsOnRegisterNewRequest =
-                    new TimestampPair(nextRequestTimestamp, nextPostTimestamp);
+        /**
+         * Checks if an alarm was set by the backoff scheduler.
+         */
+        public boolean getPOSTAlarmWasSet() {
+            return mMockScheduler.getAlarmWasSet();
         }
 
-        @Override
-        void onGenerateAndPostRequestDone(boolean result) {
-            mGenerateAndPostRequestResults.add(result);
-        }
-
-        @Override
-        void onSaveStateDone(long nextRequestTimestamp, long nextPostTimestamp) {
-            mTimestampsOnSaveState = new TimestampPair(nextRequestTimestamp, nextPostTimestamp);
-        }
-    }
-
-    private enum InstallSource { SYSTEM_IMAGE, ORGANIC }
-    private enum ServerResponse { SUCCESS, FAILURE }
-    private enum ConnectionStatus { RESPONDS, TIMES_OUT }
-    private enum InstallEvent { SEND, DONT_SEND }
-    private enum PostStatus { DUE, NOT_DUE }
-
-    private AdvancedMockContext mContext;
-    private MockOmahaDelegate mDelegate;
-    private MockOmahaClient mOmahaClient;
-
-    private MockOmahaClient createOmahaClient() {
-        return createOmahaClient(
-                ServerResponse.SUCCESS, ConnectionStatus.RESPONDS, DeviceType.HANDSET);
-    }
-
-    private MockOmahaClient createOmahaClient(
-            ServerResponse response, ConnectionStatus status, DeviceType deviceType) {
-        MockOmahaClient omahaClient = new MockOmahaClient(mContext, response, status, deviceType);
-        omahaClient.onCreate();
-        omahaClient.restoreState(mContext);
-        return omahaClient;
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        Context targetContext = getInstrumentation().getTargetContext();
-        OmahaBase.setIsDisabledForTesting(false);
-        mContext = new AdvancedMockContext(targetContext);
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        OmahaBase.setIsDisabledForTesting(true);
-        super.tearDown();
-    }
-
-    private class MockOmahaClient extends OmahaClient {
-        private final LinkedList<MockConnection> mMockConnections = new LinkedList<>();
-
-        private final boolean mSendValidResponse;
-        private final boolean mConnectionTimesOut;
-        private final boolean mIsOnTablet;
-
-        public MockOmahaClient(Context context, ServerResponse serverResponse,
-                ConnectionStatus connectionStatus, DeviceType deviceType) {
-            attachBaseContext(context);
-            setDelegateForTests(mDelegate);
-
-            mSendValidResponse = serverResponse == ServerResponse.SUCCESS;
-            mConnectionTimesOut = connectionStatus == ConnectionStatus.TIMES_OUT;
-            mIsOnTablet = deviceType == DeviceType.TABLET;
+        public boolean getRequestAlarmWasSet() {
+            return mRequestAlarmWasSet;
         }
 
         /**
@@ -211,11 +555,29 @@
             mSendInstallEvent = state;
         }
 
+        /**
+         * Mocks out the scheduler so that no alarms are really created.
+         */
+        @Override
+        ExponentialBackoffScheduler createBackoffScheduler(
+                String prefPackage, Context context, long base, long max) {
+            mMockScheduler =
+                    new MockExponentialBackoffScheduler(prefPackage, context, base, max);
+            return mMockScheduler;
+        }
+
+        @Override
+        RequestGenerator createRequestGenerator(Context context) {
+            mMockGenerator = new MockRequestGenerator(
+                    context, mIsOnTablet ? DeviceType.TABLET : DeviceType.HANDSET);
+            return mMockGenerator;
+        }
+
         @Override
         protected HttpURLConnection createConnection() throws RequestFailureException {
             MockConnection connection = null;
             try {
-                URL url = new URL(mDelegate.getRequestGenerator().getServerUrl());
+                URL url = new URL(getRequestGenerator().getServerUrl());
                 connection = new MockConnection(url, mIsOnTablet, mSendValidResponse,
                         mSendInstallEvent, mConnectionTimesOut);
                 mMockConnections.addLast(connection);
@@ -224,314 +586,19 @@
             }
             return connection;
         }
+
+        @Override
+        protected void setAlarm(AlarmManager am, PendingIntent operation, long triggerAtTime) {
+            mRequestAlarmWasSet = true;
+        }
+
+        @Override
+        protected String generateRandomUUID() {
+            mNumUUIDsGenerated += 1;
+            return "UUID" + mNumUUIDsGenerated;
+        }
     }
 
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testPipelineFreshInstall() {
-        final long now = 11684;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient();
-        mOmahaClient.run();
-
-        // A fresh install results in two requests to the Omaha server: one for the install request
-        // and one for the ping request.
-        assertTrue(mDelegate.mInstallEventWasSent);
-        assertEquals(1, mDelegate.mPostResults.size());
-        assertEquals(OmahaClient.POST_RESULT_SENT, mDelegate.mPostResults.get(0).intValue());
-        assertEquals(2, mDelegate.mGenerateAndPostRequestResults.size());
-        assertTrue(mDelegate.mGenerateAndPostRequestResults.get(0));
-        assertTrue(mDelegate.mGenerateAndPostRequestResults.get(1));
-
-        // Successful requests mean that the next scheduled event should be checking for when the
-        // user is active.
-        assertEquals(now + OmahaClient.MS_BETWEEN_REQUESTS, mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(now + OmahaClient.MS_BETWEEN_REQUESTS, now + OmahaClient.MS_POST_BASE_DELAY,
-                mDelegate.mTimestampsOnSaveState);
-    }
-
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testPipelineRegularPing() {
-        final long now = 11684;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        // Record that an install event has already been sent and that we're due for a new request.
-        SharedPreferences.Editor editor = OmahaBase.getSharedPreferences(mContext).edit();
-        editor.putBoolean(OmahaBase.PREF_SEND_INSTALL_EVENT, false);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEW_REQUEST, now);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, now);
-        editor.apply();
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient();
-        mOmahaClient.run();
-
-        // Only the regular ping should have been sent.
-        assertFalse(mDelegate.mInstallEventWasSent);
-        assertEquals(1, mDelegate.mPostResults.size());
-        assertEquals(OmahaClient.POST_RESULT_SENT, mDelegate.mPostResults.get(0).intValue());
-        assertEquals(1, mDelegate.mGenerateAndPostRequestResults.size());
-        assertTrue(mDelegate.mGenerateAndPostRequestResults.get(0));
-
-        // Successful requests mean that the next scheduled event should be checking for when the
-        // user is active.
-        assertEquals(now + OmahaClient.MS_BETWEEN_REQUESTS, mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(now + OmahaClient.MS_BETWEEN_REQUESTS, now + OmahaClient.MS_POST_BASE_DELAY,
-                mDelegate.mTimestampsOnSaveState);
-    }
-
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testTooEarlyToPing() {
-        final long now = 0;
-        final long later = 10000;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        // Put the time for the next request in the future.
-        SharedPreferences prefs = OmahaBase.getSharedPreferences(mContext);
-        prefs.edit().putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEW_REQUEST, later).apply();
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient();
-        mOmahaClient.run();
-
-        // Nothing should have been POSTed.
-        assertEquals(0, mDelegate.mPostResults.size());
-        assertEquals(0, mDelegate.mGenerateAndPostRequestResults.size());
-
-        // The next scheduled event is the request generation.  Because there was nothing to POST,
-        // its timestamp should have remained unchanged and shouldn't have been considered when the
-        // new alarm was scheduled.
-        assertEquals(later, mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(later, now, mDelegate.mTimestampsOnSaveState);
-    }
-
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testTooEarlyToPostExistingRequest() {
-        final long timeGeneratedRequest = 0L;
-        final long now = 10000L;
-        final long timeSendNewPost = 20000L;
-        final long timeSendNewRequest = 50000L;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        SharedPreferences prefs = OmahaBase.getSharedPreferences(mContext);
-        SharedPreferences.Editor editor = prefs.edit();
-
-        // Make it so that a request was generated and is just waiting to be sent.
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEW_REQUEST, timeSendNewRequest);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_OF_REQUEST, timeGeneratedRequest);
-        editor.putString(OmahaBase.PREF_PERSISTED_REQUEST_ID, "persisted_id");
-
-        // Put the time for the next post in the future.
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, timeSendNewPost);
-        editor.apply();
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient();
-        mOmahaClient.run();
-
-        // Request generation code should be skipped.
-        assertNull(mDelegate.mTimestampsOnRegisterNewRequest);
-
-        // Should be too early to post, causing it to be rescheduled.
-        assertEquals(1, mDelegate.mPostResults.size());
-        assertEquals(OmahaClient.POST_RESULT_SCHEDULED, mDelegate.mPostResults.get(0).intValue());
-        assertEquals(0, mDelegate.mGenerateAndPostRequestResults.size());
-
-        // The next scheduled event is the POST.  Because request generation code wasn't run, the
-        // timestamp for it shouldn't have changed.
-        assertEquals(timeSendNewPost, mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(timeSendNewRequest, timeSendNewPost, mDelegate.mTimestampsOnSaveState);
-    }
-
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testPostExistingRequestSuccessfully() {
-        final long timeGeneratedRequest = 0L;
-        final long now = 10000L;
-        final long timeSendNewPost = now;
-        final long timeRegisterNewRequest = 20000L;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        SharedPreferences prefs = OmahaBase.getSharedPreferences(mContext);
-        SharedPreferences.Editor editor = prefs.edit();
-
-        // Make it so that a regular <ping> was generated and is just waiting to be sent.
-        editor.putBoolean(OmahaBase.PREF_SEND_INSTALL_EVENT, false);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEW_REQUEST, timeRegisterNewRequest);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_OF_REQUEST, timeGeneratedRequest);
-        editor.putString(OmahaBase.PREF_PERSISTED_REQUEST_ID, "persisted_id");
-
-        // Send the POST now.
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, timeSendNewPost);
-        editor.apply();
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient();
-        mOmahaClient.run();
-
-        // Registering code shouldn't have fired.
-        assertNull(mDelegate.mTimestampsOnRegisterNewRequest);
-
-        // Because we didn't send an install event, only one POST should have occurred.
-        assertEquals(1, mDelegate.mPostResults.size());
-        assertEquals(OmahaClient.POST_RESULT_SENT, mDelegate.mPostResults.get(0).intValue());
-        assertEquals(1, mDelegate.mGenerateAndPostRequestResults.size());
-        assertTrue(mDelegate.mGenerateAndPostRequestResults.get(0));
-
-        // The next scheduled event is the request generation because there is nothing to POST.
-        // A successful POST adjusts all timestamps for the current time.
-        assertEquals(timeRegisterNewRequest, mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(now + OmahaClient.MS_BETWEEN_REQUESTS, now + OmahaClient.MS_POST_BASE_DELAY,
-                mDelegate.mTimestampsOnSaveState);
-    }
-
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testPostExistingButFails() {
-        final long timeGeneratedRequest = 0L;
-        final long now = 10000L;
-        final long timeSendNewPost = now;
-        final long timeRegisterNewRequest = timeGeneratedRequest + OmahaClient.MS_BETWEEN_REQUESTS;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        SharedPreferences prefs = OmahaBase.getSharedPreferences(mContext);
-        SharedPreferences.Editor editor = prefs.edit();
-
-        // Make it so that a regular <ping> was generated and is just waiting to be sent.
-        editor.putBoolean(OmahaBase.PREF_SEND_INSTALL_EVENT, false);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEW_REQUEST, timeRegisterNewRequest);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_OF_REQUEST, timeGeneratedRequest);
-        editor.putString(OmahaBase.PREF_PERSISTED_REQUEST_ID, "persisted_id");
-
-        // Send the POST now.
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, timeSendNewPost);
-        editor.apply();
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient(
-                ServerResponse.FAILURE, ConnectionStatus.RESPONDS, DeviceType.HANDSET);
-        mOmahaClient.run();
-
-        // Registering code shouldn't have fired.
-        assertNull(mDelegate.mTimestampsOnRegisterNewRequest);
-
-        // Because we didn't send an install event, only one POST should have occurred.
-        assertEquals(1, mDelegate.mPostResults.size());
-        assertEquals(OmahaClient.POST_RESULT_FAILED, mDelegate.mPostResults.get(0).intValue());
-        assertEquals(1, mDelegate.mGenerateAndPostRequestResults.size());
-        assertFalse(mDelegate.mGenerateAndPostRequestResults.get(0));
-
-        // The next scheduled event should be the POST event, which is delayed by the base delay
-        // because no failures have happened yet.
-        assertEquals(mDelegate.mTimestampsOnSaveState.timestampNextPost,
-                mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(timeRegisterNewRequest, now + OmahaClient.MS_POST_BASE_DELAY,
-                mDelegate.mTimestampsOnSaveState);
-    }
-
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testTimestampWithinBounds() {
-        final long now = 0L;
-        final long timeRegisterNewRequest = OmahaClient.MS_BETWEEN_REQUESTS + 1;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        SharedPreferences prefs = OmahaBase.getSharedPreferences(mContext);
-        SharedPreferences.Editor editor = prefs.edit();
-
-        // Indicate that the next request should be generated way past an expected timeframe.
-        editor.putBoolean(OmahaBase.PREF_SEND_INSTALL_EVENT, false);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEW_REQUEST, timeRegisterNewRequest);
-        editor.apply();
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient();
-        mOmahaClient.run();
-
-        // Request generation code should fire.
-        assertNotNull(mDelegate.mTimestampsOnRegisterNewRequest);
-
-        // Because we didn't send an install event, only one POST should have occurred.
-        assertEquals(1, mDelegate.mPostResults.size());
-        assertEquals(OmahaClient.POST_RESULT_SENT, mDelegate.mPostResults.get(0).intValue());
-        assertEquals(1, mDelegate.mGenerateAndPostRequestResults.size());
-        assertTrue(mDelegate.mGenerateAndPostRequestResults.get(0));
-
-        // The next scheduled event should be the timestamp for a new request generation.
-        assertEquals(mDelegate.mTimestampsOnSaveState.timestampNextRequest,
-                mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(now + OmahaClient.MS_BETWEEN_REQUESTS, now + OmahaClient.MS_POST_BASE_DELAY,
-                mDelegate.mTimestampsOnSaveState);
-    }
-
-    @SmallTest
-    @Feature({"Omaha"})
-    public void testOverdueRequestCausesNewRegistration() {
-        final long timeGeneratedRequest = 0L;
-        final long now = 10000L;
-        final long timeSendNewPost = now;
-        final long timeRegisterNewRequest =
-                timeGeneratedRequest + OmahaClient.MS_BETWEEN_REQUESTS * 5;
-
-        mDelegate = new MockOmahaDelegate(mContext, DeviceType.HANDSET, InstallSource.ORGANIC);
-        mDelegate.getScheduler().setCurrentTime(now);
-
-        // Record that a regular <ping> was generated, but not sent, then assign it an invalid
-        // timestamp and try to send it now.
-        SharedPreferences prefs = OmahaBase.getSharedPreferences(mContext);
-        SharedPreferences.Editor editor = prefs.edit();
-        editor.putBoolean(OmahaBase.PREF_SEND_INSTALL_EVENT, false);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEW_REQUEST, timeRegisterNewRequest);
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_OF_REQUEST, timeGeneratedRequest);
-        editor.putString(OmahaBase.PREF_PERSISTED_REQUEST_ID, "persisted_id");
-        editor.putLong(OmahaBase.PREF_TIMESTAMP_FOR_NEXT_POST_ATTEMPT, timeSendNewPost);
-        editor.apply();
-
-        // Trigger Omaha.
-        mOmahaClient = createOmahaClient();
-        mOmahaClient.run();
-
-        // Registering code shouldn't have fired.
-        checkTimestamps(now + OmahaClient.MS_BETWEEN_REQUESTS, now,
-                mDelegate.mTimestampsOnRegisterNewRequest);
-
-        // Because we didn't send an install event, only one POST should have occurred.
-        assertEquals(1, mDelegate.mPostResults.size());
-        assertEquals(OmahaClient.POST_RESULT_SENT, mDelegate.mPostResults.get(0).intValue());
-        assertEquals(1, mDelegate.mGenerateAndPostRequestResults.size());
-        assertTrue(mDelegate.mGenerateAndPostRequestResults.get(0));
-
-        // The next scheduled event should be the registration event.
-        assertEquals(mDelegate.mTimestampsOnSaveState.timestampNextRequest,
-                mDelegate.mNextScheduledTimestamp);
-        checkTimestamps(now + OmahaClient.MS_BETWEEN_REQUESTS, now + OmahaClient.MS_POST_BASE_DELAY,
-                mDelegate.mTimestampsOnSaveState);
-    }
-
-    private void checkTimestamps(
-            long expectedRequestTimestamp, long expectedPostTimestamp, TimestampPair timestamps) {
-        assertEquals(expectedRequestTimestamp, timestamps.timestampNextRequest);
-        assertEquals(expectedPostTimestamp, timestamps.timestampNextPost);
-    }
 
     /**
      * Simulates communication with the actual Omaha server.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrUtils.java
index 6c5c104d..0a3ba8e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrUtils.java
@@ -61,7 +61,7 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                vrDelegate.exitVRIfNecessary(false /* isPausing */);
+                vrDelegate.shutdownVR(false /* isPausing */, false /* showTransition */);
             }
         });
     }
diff --git a/chrome/app/chrome_crash_reporter_client_win.cc b/chrome/app/chrome_crash_reporter_client_win.cc
index 8148716..ba0a9b9 100644
--- a/chrome/app/chrome_crash_reporter_client_win.cc
+++ b/chrome/app/chrome_crash_reporter_client_win.cc
@@ -94,7 +94,7 @@
       {kChannel, kSmallSize},
       {kActiveURL, kLargeSize},
       {kNumVariations, kSmallSize},
-      {kVariations, kLargeSize},
+      {kVariations, kHugeSize},
       {kNumExtensionsCount, kSmallSize},
       {kShutdownType, kSmallSize},
       {kBrowserUnpinTrace, kMediumSize},
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 59912e9..64c5e207 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1692,6 +1692,9 @@
   <message name="IDS_OOBE_OK_BUTTON_TEXT" desc="Text on 'OK' button" meaning="This is 'OK' text for all 'OK' buttons on ChromeOS initial device setup screens.">
     OK
   </message>
+  <message name="IDS_LANGUAGE_BUTTON_LABEL" desc="Navigation label attached to the 'Select Language' button on ChromeOS initial device setup screen" meaning="The button itself displays only current language name. But for accessibility mode we need full description of this button. So this label suggests that pressing on a button will allow to change current language and input method. And it should also include the name of currently selected language.">
+    Select language and keyboard button. Currently selected language is <ph name="LANGUAGE">$1<ex>English (United States)</ex></ph>.
+  </message>
   <message name="IDS_LANGUAGE_SECTION_TITLE" desc="Title of language selection screen" meaning="A title of the dialog where user should select ChromeOS UI language and default keyboard layout during initial device setup.">
     Choose your language &amp; keyboard
   </message>
@@ -1761,6 +1764,12 @@
   <message name="IDS_OOBE_CLOSE_ACCESSIBILITY_MENU" desc="Text to be spoken when focus is set to the close button of accessibility options menu.">
     Close accessibility menu
   </message>
+  <message name="IDS_LANGUAGE_DROPDOWN_LABEL" desc="Navigation label attached to the 'List of languages' dropdown menu on ChromeOS Language and keyboard initial device setup screen" meaning="The menu itself displays only current language name. But for accessibility mode we need full description of this menu. So this label suggests that activating a menu will allow to change current language. And it should also include the name of currently selected language.">
+    Language selection menu. Currently selected language is <ph name="LANGUAGE">$1<ex>English (United States)</ex></ph>.
+  </message>
+  <message name="IDS_KEYBOARD_DROPDOWN_LABEL" desc="Navigation label attached to the 'List of keyboards' dropdown menu on ChromeOS Language and keyboard initial device setup screen" meaning="The menu itself displays only current keyboard layout name. But for accessibility mode we need full description of this menu. So this label suggests that activating a menu will allow to change current input method. And it should also include the name of currently selected input method.">
+    Input method selection menu. Currently selected input method is <ph name="KEYBOARD">$1<ex>English (US)</ex></ph>.
+  </message>
   <message name="IDS_OOBE_OTHER_LANGUAGES" desc="Option group name dividing vendor-configured languages from other available languages in out-of-box 'Select language' select control.">
     Other languages
   </message>
@@ -5769,6 +5778,14 @@
     Disable Notifcation when Device is End of Life.
   </message>
 
+  <!-- Stylus strings -->
+  <message name="IDS_FLAGS_FORCE_ENABLE_STYLUS_TOOLS_NAME" desc="Name of the about:flag option to enable stylus tools.">
+    Force enable stylus features
+  </message>
+  <message name="IDS_FLAGS_FORCE_ENABLE_STYLUS_TOOLS_DESCRIPTION" desc="Description of the about:flag option to enable stylus tools.">
+    Forces display of the stylus tools menu in the shelf and the stylus section in settings, even if there is no attached stylus device.
+  </message>
+
   <!-- Genius App -->
   <message name="IDS_GENIUS_APP_NAME" desc="Name of the genius app in the app shelf">
     Get Help
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 18a4170..27375d2 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -8300,23 +8300,23 @@
       <message name="IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST" desc="Template text for a child row in the Geolocation Exceptions page view. Controls the permission setting for the parent page when embedded on the specified site.">
         embedded on <ph name="URL">$1<ex>www.google.com</ex></ph>
       </message>
+      <message name="IDS_PROTECTED_CONTENT_TAB_LABEL" desc="Label for the Protected Content tab on the Content Settings dialog.">
+        Protected content
+      </message>
+      <message name="IDS_PROTECTED_CONTENT_ENABLE_CHECKBOX" desc="The label of the checkbox for enabling protected content.">
+        Allow sites to play protected content (recommended)
+      </message>
       <if expr="chromeos or is_win">
-        <message name="IDS_PROTECTED_CONTENT_TAB_LABEL" desc="Label for the Protected Content tab on the Content Settings dialog.">
-          Protected content
-        </message>
         <message name="IDS_PROTECTED_CONTENT_INFO" desc="Text that is displayed on the Protected Content tab of the Content Settings dialog. This text explains that enabling protected content may require using a uniquely identifiable machine identifier.">
           Some content services use machine identifiers to uniquely identify you for the purposes of authorizing access to protected content.
         </message>
-        <message name="IDS_PROTECTED_CONTENT_ENABLE" desc="The label of the checkbox for enabling protected content.">
+        <message name="IDS_PROTECTED_CONTENT_ENABLE_IDENTIFIERS_CHECKBOX" desc="The label of the checkbox for enabling machine identifiers to uniquely identiy the user for protected content.">
           Allow identifiers for protected content (computer restart may be required)
         </message>
         <message name="IDS_PROTECTED_CONTENT_HEADER" desc="Text label for the managing exceptions of Protected Content.">
           Protected content exceptions
         </message>
       </if>
-      <message name="IDS_PROTECTED_CONTENT_ENABLE_CHECKBOX" desc="The label of the checkbox for enabling protected content.">
-        Allow sites to play protected content (recommended)
-      </message>
       <message name="IDS_PPAPI_BROKER_TAB_LABEL" desc="Label for PPAPI broker tab on Content Settings dialog">
         Unsandboxed plugin access
       </message>
@@ -11144,10 +11144,16 @@
 
       <!-- Signin Email Confirmation tab modal dialog -->
       <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_CREATE_PROFILE_RADIO_BUTTON_TITLE" desc="Title of radio button to create a new profile.">
-        <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>This wasn't me.<ph name="END_BOLD">&lt;/strong&gt;</ph> Create a new profile for <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>
+        This wasn't me.
       </message>
-      <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_START_SYNC_RADIO_BUTTON_TITLE" desc="Title of radio button to create a new profile.">
-        <ph name="BEGIN_BOLD">&lt;strong&gt;</ph>This was me.<ph name="END_BOLD">&lt;/strong&gt;</ph> Add my bookmarks, history, passwords, and other settings to <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>
+      <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_CREATE_PROFILE_RADIO_BUTTON_SUBTITLE" desc="Subtitle of radio button to create a new profile.">
+        Create a new profile for <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>
+      </message>
+      <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_START_SYNC_RADIO_BUTTON_TITLE" desc="Title of radio button to sign in to current profile.">
+        This was me.
+      </message>
+      <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_START_SYNC_RADIO_BUTTON_SUBTITLE" desc="Subtitle of radio button to sign in to current profile.">
+        Add my bookmarks, history, passwords, and other settings to <ph name="USER_EMAIL_ADDRESS">$1<ex>foo@gmail.com</ex></ph>
       </message>
       <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_CLOSE_BUTTON_LABEL" desc="Label of the close button in the signin email confirmation dialog.">
         Cancel
diff --git a/chrome/app/mash/BUILD.gn b/chrome/app/mash/BUILD.gn
index 2e2b7b3..292a1919 100644
--- a/chrome/app/mash/BUILD.gn
+++ b/chrome/app/mash/BUILD.gn
@@ -34,17 +34,7 @@
   ]
 
   if (is_chromeos) {
-    sources += [
-      "mash_crash_reporter_client.cc",
-      "mash_crash_reporter_client.h",
-    ]
-    deps += [
-      "//ash/resources",
-      "//components/crash/content/app",
-      "//components/crash/core/common",
-      "//components/upload_list",
-      "//components/version_info:generate_version_info",
-    ]
+    deps += [ "//ash/resources" ]
   }
 
   if (is_linux && !is_android) {
diff --git a/chrome/app/mash/mash_crash_reporter_client.cc b/chrome/app/mash/mash_crash_reporter_client.cc
deleted file mode 100644
index ab630242..0000000
--- a/chrome/app/mash/mash_crash_reporter_client.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/app/mash/mash_crash_reporter_client.h"
-
-#include <vector>
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/debug/crash_logging.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/sys_info.h"
-#include "components/crash/core/common/crash_keys.h"
-#include "components/upload_list/crash_upload_list.h"
-#include "components/version_info/version_info_values.h"
-
-#if !defined(OS_CHROMEOS)
-#error Unsupported platform
-#endif
-
-MashCrashReporterClient::MashCrashReporterClient() {}
-
-MashCrashReporterClient::~MashCrashReporterClient() {}
-
-void MashCrashReporterClient::GetProductNameAndVersion(
-    const char** product_name,
-    const char** version) {
-  *product_name = "Chrome_ChromeOS";
-  *version = PRODUCT_VERSION;
-}
-
-base::FilePath MashCrashReporterClient::GetReporterLogFilename() {
-  return base::FilePath(CrashUploadList::kReporterLogFilename);
-}
-
-bool MashCrashReporterClient::GetCrashDumpLocation(base::FilePath* crash_dir) {
-  // For development on Linux desktop just use /tmp.
-  if (!base::SysInfo::IsRunningOnChromeOS()) {
-    *crash_dir = base::FilePath("/tmp");
-    return true;
-  }
-
-  // TODO(jamescook): Refactor chrome::DIR_CRASH_DUMPS into //components/crash
-  // and use it here.
-  *crash_dir = base::FilePath("/var/log/chrome/Crash Reports");
-  DCHECK(base::PathExists(*crash_dir));
-  return true;
-}
-
-size_t MashCrashReporterClient::RegisterCrashKeys() {
-  // Register keys used by non-browser processes launched by the service manager
-  // (e.g. the GPU service). See chrome/common/crash_keys.cc.
-  std::vector<base::debug::CrashKey> keys = {
-      {"url-chunk", crash_keys::kLargeSize},
-      {"total-discardable-memory-allocated", crash_keys::kSmallSize},
-      {"discardable-memory-free", crash_keys::kSmallSize},
-  };
-  crash_keys::GetCrashKeysForCommandLineSwitches(&keys);
-  return base::debug::InitCrashKeys(&keys.at(0), keys.size(),
-                                    crash_keys::kChunkMaxLength);
-}
-
-bool MashCrashReporterClient::IsRunningUnattended() {
-  return false;
-}
-
-bool MashCrashReporterClient::GetCollectStatsConsent() {
-#if defined(GOOGLE_CHROME_BUILD)
-  // For development on Linux desktop allow crash reporting to be forced on.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableCrashReporterForTesting)) {
-    return true;
-  }
-  // TODO(jamescook): Refactor this to share code with
-  // chrome/browser/google/google_update_settings_posix.cc.
-  base::FilePath consent_file("/home/chronos/Consent To Send Stats");
-  return base::PathExists(consent_file);
-#else
-  // Crash reporting is only supported in branded builds.
-  return false;
-#endif  // defined(GOOGLE_CHROME_BUILD)
-}
diff --git a/chrome/app/mash/mash_crash_reporter_client.h b/chrome/app/mash/mash_crash_reporter_client.h
deleted file mode 100644
index 6cd8502c..0000000
--- a/chrome/app/mash/mash_crash_reporter_client.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_APP_MASH_MASH_CRASH_REPORTER_CLIENT_H_
-#define CHROME_APP_MASH_MASH_CRASH_REPORTER_CLIENT_H_
-
-#include "base/macros.h"
-#include "components/crash/content/app/crash_reporter_client.h"
-
-#if !defined(OS_CHROMEOS)
-#error Unsupported platform
-#endif
-
-// Crash reporting support for chrome --mash. Used for the root process, ash,
-// and other standalone services. Chrome content_browser handles its own crash
-// reporting via ChromeCrashReporterClient.
-// TODO(jamescook): Eliminate chrome dependencies from ChromeCrashReporterClient
-// and share more code with this class.
-class MashCrashReporterClient : public crash_reporter::CrashReporterClient {
- public:
-  MashCrashReporterClient();
-  ~MashCrashReporterClient() override;
-
-  // crash_reporter::CrashReporterClient implementation.
-  void GetProductNameAndVersion(const char** product_name,
-                                const char** version) override;
-  base::FilePath GetReporterLogFilename() override;
-  bool GetCrashDumpLocation(base::FilePath* crash_dir) override;
-  size_t RegisterCrashKeys() override;
-  bool IsRunningUnattended() override;
-  bool GetCollectStatsConsent() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MashCrashReporterClient);
-};
-
-#endif  // CHROME_APP_MASH_MASH_CRASH_REPORTER_CLIENT_H_
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc
index e05f7ecf..e436fbd 100644
--- a/chrome/app/mash/mash_runner.cc
+++ b/chrome/app/mash/mash_runner.cc
@@ -55,12 +55,6 @@
 #include "ui/base/ui_base_paths.h"
 #include "ui/base/ui_base_switches.h"
 
-#if defined(OS_CHROMEOS)
-#include "base/debug/leak_annotations.h"
-#include "chrome/app/mash/mash_crash_reporter_client.h"
-#include "components/crash/content/app/breakpad_linux.h" // nogncheck
-#endif
-
 using service_manager::mojom::ServiceFactory;
 
 namespace {
@@ -128,26 +122,6 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceProcessLauncherDelegateImpl);
 };
 
-#if defined(OS_CHROMEOS)
-// Initializes breakpad crash reporting. MashCrashReporterClient handles
-// registering crash keys.
-void InitializeCrashReporting() {
-  DCHECK(!breakpad::IsCrashReporterEnabled());
-
-  // Intentionally leaked. The crash client needs to outlive all other code.
-  MashCrashReporterClient* client = new MashCrashReporterClient;
-  ANNOTATE_LEAKING_OBJECT_PTR(client);
-  crash_reporter::SetCrashReporterClient(client);
-
-  // For now all standalone services act like the browser process and write
-  // their own in-process crash dumps. When ash and the window server are
-  // sandboxed we will need to hook up the crash signal file descriptor, make
-  // the root process handle dumping, and pass a process type here.
-  const std::string process_type_unused;
-  breakpad::InitCrashReporter(process_type_unused);
-}
-#endif  // defined(OS_CHROMEOS)
-
 // Quits |run_loop| if the |identity| of the quitting service is critical to the
 // system (e.g. the window manager). Used in the main process.
 void OnInstanceQuitInMain(base::RunLoop* run_loop,
@@ -277,15 +251,11 @@
 #if !defined(OFFICIAL_BUILD)
   // Initialize stack dumping before initializing sandbox to make sure symbol
   // names in all loaded libraries will be cached.
+  // NOTE: On Chrome OS, crash reporting for the root process and non-browser
+  // service processes is handled by the OS-level crash_reporter.
   base::debug::EnableInProcessStackDumping();
 #endif
 
-#if defined(OS_CHROMEOS)
-  // Breakpad installs signal handlers, so crash reporting must be set up after
-  // EnableInProcessStackDumping() resets the signal handlers.
-  InitializeCrashReporting();
-#endif
-
   std::unique_ptr<base::MessageLoop> message_loop;
   if (!IsChild())
     message_loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 5c1a995..55ea29c 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -469,26 +469,29 @@
     <message name="IDS_SETTINGS_BLUETOOTH" desc="Name of the settings page which displays Bluetooth device settings.">
       Bluetooth
     </message>
+    <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_PAIRED" desc="Title of the settings subsection listing paired Bluetooth devices.">
+      Paired devices
+    </message>
+    <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_UNPAIRED" desc="Title of the settings subsection listing unpaired Bluetooth devices.">
+      Unpaired devices
+    </message>
     <message name="IDS_SETTINGS_BLUETOOTH_PAIR" desc="Label for the settings button to pair a previously paired Bluetooth device.">
       Pair
     </message>
-    <message name="IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE" desc="Label for the settings button to add and pair a new Bluetooth device.">
-      Pair device
-    </message>
     <message name="IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE" desc="Title of the settings dialog for adding or pairing Bluetooth a device.">
       Pair Bluetooth device
     </message>
-    <message name="IDS_SETTINGS_BLUETOOTH_SCANNING" desc="Message displayed while scanning for Bluetooth devices.">
-      Scanning for devices...
+    <message name="IDS_SETTINGS_BLUETOOTH_NO_DEVICES" desc="Message displayed when there are no paired Bluetooth devices scan.">
+      No paired devices.
     </message>
-    <message name="IDS_SETTINGS_BLUETOOTH_NO_DEVICES" desc="Message displayed when no Bluetooth devices are found after a scan.">
+    <message name="IDS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND" desc="Message displayed when no Bluetooth devices are found after a scan.">
       No Bluetooth devices found.
     </message>
     <message name="IDS_SETTINGS_BLUETOOTH_ENABLED" desc="Label for Bluetooth section when enabled.">
-      Bluetooth enabled
+      Enabled
     </message>
     <message name="IDS_SETTINGS_BLUETOOTH_DISABLED" desc="Label for Bluetooth section when disabled.">
-      Bluetooth disabled
+      Disabled
     </message>
     <message name="IDS_SETTINGS_BLUETOOTH_EXPAND_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing available Bluetooth devices. Only visible by screen reader software.">
       Show available Bluetooth devices
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index e8fbac0b..edbf9e0 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -246,6 +246,8 @@
     "component_updater/pnacl_component_installer.h",
     "component_updater/recovery_component_installer.cc",
     "component_updater/recovery_component_installer.h",
+    "component_updater/recovery_improved_component_installer.cc",
+    "component_updater/recovery_improved_component_installer.h",
     "component_updater/sth_set_component_installer.cc",
     "component_updater/sth_set_component_installer.h",
     "component_updater/subresource_filter_component_installer.cc",
@@ -2649,6 +2651,8 @@
       "android/download/download_manager_service.h",
       "android/download/duplicate_download_infobar_delegate.cc",
       "android/download/duplicate_download_infobar_delegate.h",
+      "android/download/intercept_download_resource_throttle.cc",
+      "android/download/intercept_download_resource_throttle.h",
       "android/download/mock_download_controller.cc",
       "android/download/mock_download_controller.h",
       "android/download/ui/thumbnail_provider.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 898ab82e..fabc19c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2203,6 +2203,12 @@
      FEATURE_VALUE_TYPE(net::CertVerifyProcAndroid::kAIAFetchingFeature)},
 #endif
 
+#if defined(OS_CHROMEOS)
+    {"force-enable-stylus-tools", IDS_FLAGS_FORCE_ENABLE_STYLUS_TOOLS_NAME,
+     IDS_FLAGS_FORCE_ENABLE_STYLUS_TOOLS_DESCRIPTION, kOsCrOS,
+     SINGLE_VALUE_TYPE(ash::switches::kAshForceEnablePalette)},
+#endif // defined(OS_CHROMEOS)
+
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms.xml. See note in
     // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/download/chrome_download_delegate.cc b/chrome/browser/android/download/chrome_download_delegate.cc
index 0bbb8362..8518349c 100644
--- a/chrome/browser/android/download/chrome_download_delegate.cc
+++ b/chrome/browser/android/download/chrome_download_delegate.cc
@@ -128,6 +128,31 @@
       env, java_ref_, callback_id);
 }
 
+void ChromeDownloadDelegate::EnqueueDownloadManagerRequest(
+    const std::string& url,
+    const std::string& user_agent,
+    const std::string& content_disposition,
+    const std::string& mime_type,
+    const std::string& cookie,
+    const std::string& referer) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> jurl =
+      ConvertUTF8ToJavaString(env, url);
+  ScopedJavaLocalRef<jstring> juser_agent =
+      ConvertUTF8ToJavaString(env, user_agent);
+  ScopedJavaLocalRef<jstring> jcontent_disposition =
+      ConvertUTF8ToJavaString(env, content_disposition);
+  ScopedJavaLocalRef<jstring> jmime_type =
+      ConvertUTF8ToJavaString(env, mime_type);
+  ScopedJavaLocalRef<jstring> jcookie =
+      ConvertUTF8ToJavaString(env, cookie);
+  ScopedJavaLocalRef<jstring> jreferer =
+      ConvertUTF8ToJavaString(env, referer);
+  Java_ChromeDownloadDelegate_enqueueAndroidDownloadManagerRequest(
+      env, java_ref_, jurl, juser_agent, jcontent_disposition, jmime_type,
+      jcookie, jreferer);
+}
+
 void Init(JNIEnv* env,
           const JavaParamRef<jobject>& obj,
           const JavaParamRef<jobject>& jweb_contents) {
diff --git a/chrome/browser/android/download/chrome_download_delegate.h b/chrome/browser/android/download/chrome_download_delegate.h
index 28285f8..8862ad68 100644
--- a/chrome/browser/android/download/chrome_download_delegate.h
+++ b/chrome/browser/android/download/chrome_download_delegate.h
@@ -22,6 +22,14 @@
   void OnDownloadStarted(const std::string& filename);
   void RequestFileAccess(intptr_t callback_id);
 
+  // TODO(qinmin): consolidate this with the static function above.
+  void EnqueueDownloadManagerRequest(const std::string& url,
+                                     const std::string& user_agent,
+                                     const std::string& content_disposition,
+                                     const std::string& mime_type,
+                                     const std::string& cookie,
+                                     const std::string& referer);
+
  private:
   explicit ChromeDownloadDelegate(content::WebContents* contents);
   friend class content::WebContentsUserData<ChromeDownloadDelegate>;
diff --git a/chrome/browser/android/download/download_controller.cc b/chrome/browser/android/download/download_controller.cc
index c77b0f28..2d604ab 100644
--- a/chrome/browser/android/download/download_controller.cc
+++ b/chrome/browser/android/download/download_controller.cc
@@ -219,6 +219,57 @@
       RequestFileAccess(callback_id);
 }
 
+void DownloadController::CreateAndroidDownload(
+    const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+    const DownloadInfo& info) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&DownloadController::StartAndroidDownload,
+                 base::Unretained(this),
+                 wc_getter, info));
+}
+
+void DownloadController::StartAndroidDownload(
+    const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+    const DownloadInfo& info) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  WebContents* web_contents = wc_getter.Run();
+  if (!web_contents) {
+    // The view went away. Can't proceed.
+    LOG(ERROR) << "Tab closed, download failed on URL:" << info.url.spec();
+    return;
+  }
+
+  AcquireFileAccessPermission(
+      web_contents,
+      base::Bind(&DownloadController::StartAndroidDownloadInternal,
+                 base::Unretained(this), wc_getter, info));
+}
+
+void DownloadController::StartAndroidDownloadInternal(
+    const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+    const DownloadInfo& info, bool allowed) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (!allowed)
+    return;
+
+  WebContents* web_contents = wc_getter.Run();
+  if (!web_contents) {
+    // The view went away. Can't proceed.
+    LOG(ERROR) << "Tab closed, download failed on URL:" << info.url.spec();
+    return;
+  }
+
+  ChromeDownloadDelegate::FromWebContents(web_contents)->
+      EnqueueDownloadManagerRequest(
+          info.url.spec(), info.user_agent,
+          info.content_disposition, info.original_mime_type,
+          info.cookie, info.referer);
+}
+
 bool DownloadController::HasFileAccessPermission(
     ui::WindowAndroid* window_android) {
   ScopedJavaLocalRef<jobject> jwindow_android = window_android->GetJavaObject();
diff --git a/chrome/browser/android/download/download_controller.h b/chrome/browser/android/download/download_controller.h
index 4282235..f044b49 100644
--- a/chrome/browser/android/download/download_controller.h
+++ b/chrome/browser/android/download/download_controller.h
@@ -44,6 +44,9 @@
   void AcquireFileAccessPermission(
       content::WebContents* web_contents,
       const AcquireFileAccessPermissionCallback& callback) override;
+  void CreateAndroidDownload(
+      const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+      const DownloadInfo& info) override;
 
   // UMA histogram enum for download cancellation reasons. Keep this
   // in sync with MobileDownloadCancelReason in histograms.xml. This should be
@@ -87,6 +90,14 @@
   base::android::ScopedJavaLocalRef<jobject> GetContentViewCoreFromWebContents(
       content::WebContents* web_contents);
 
+  // Helper methods to start android download on UI thread.
+  void StartAndroidDownload(
+      const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+      const DownloadInfo& info);
+  void StartAndroidDownloadInternal(
+      const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+      const DownloadInfo& info, bool allowed);
+
   // Creates Java object if it is not created already and returns it.
   JavaObject* GetJavaObject();
 
diff --git a/chrome/browser/android/download/download_controller_base.cc b/chrome/browser/android/download/download_controller_base.cc
index bf3d98b..696f1c2 100644
--- a/chrome/browser/android/download/download_controller_base.cc
+++ b/chrome/browser/android/download/download_controller_base.cc
@@ -12,8 +12,7 @@
 
 using content::ResourceRequestInfo;
 
-DownloadInfo::DownloadInfo(const net::URLRequest* request)
-    : has_user_gesture(false) {
+DownloadInfo::DownloadInfo(const net::URLRequest* request) {
   request->GetResponseHeaderByName("content-disposition", &content_disposition);
 
   if (request->response_headers())
@@ -30,10 +29,6 @@
     original_url = request->url_chain().front();
     url = request->url_chain().back();
   }
-
-  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
-  if (info)
-    has_user_gesture = info->HasUserGesture();
 }
 
 DownloadInfo::DownloadInfo(const DownloadInfo& other) = default;
diff --git a/chrome/browser/android/download/download_controller_base.h b/chrome/browser/android/download/download_controller_base.h
index 6a9bf69..e43f1ed 100644
--- a/chrome/browser/android/download/download_controller_base.h
+++ b/chrome/browser/android/download/download_controller_base.h
@@ -36,16 +36,11 @@
   GURL url;
   // The original URL before any redirection by the server for this URL.
   GURL original_url;
-  int64_t total_bytes;
   std::string content_disposition;
   std::string original_mime_type;
   std::string user_agent;
   std::string cookie;
   std::string referer;
-  bool has_user_gesture;
-
-  content::WebContents* web_contents;
-  // Default copy constructor is used for passing this struct by value.
 };
 
 // Interface to request GET downloads and send notifications for POST
@@ -83,6 +78,11 @@
   // Called by unit test to approve or disapprove file access request.
   virtual void SetApproveFileAccessRequestForTesting(bool approve) {}
 
+  // Starts a new download request with Android DownloadManager.
+  virtual void CreateAndroidDownload(
+      const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+      const DownloadInfo& info) = 0;
+
  protected:
   ~DownloadControllerBase() override {}
   static DownloadControllerBase* download_controller_;
diff --git a/chrome/browser/android/download/intercept_download_resource_throttle.cc b/chrome/browser/android/download/intercept_download_resource_throttle.cc
new file mode 100644
index 0000000..1321f2e
--- /dev/null
+++ b/chrome/browser/android/download/intercept_download_resource_throttle.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/download/intercept_download_resource_throttle.h"
+
+#include "base/strings/string_util.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+
+namespace {
+static const char kOMADrmMessageMimeType[] = "application/vnd.oma.drm.message";
+}
+
+InterceptDownloadResourceThrottle::InterceptDownloadResourceThrottle(
+    net::URLRequest* request,
+    const content::ResourceRequestInfo::WebContentsGetter& wc_getter)
+    : request_(request),
+      wc_getter_(wc_getter),
+      weak_factory_(this) {
+}
+
+InterceptDownloadResourceThrottle::~InterceptDownloadResourceThrottle() =
+    default;
+
+void InterceptDownloadResourceThrottle::WillProcessResponse(bool* defer) {
+  if (request_->url_chain().empty())
+    return;
+
+  GURL url = request_->url_chain().back();
+  if (!url.SchemeIsHTTPOrHTTPS())
+    return;
+
+  if (request_->method() != net::HttpRequestHeaders::kGetMethod)
+    return;
+
+  net::HttpRequestHeaders headers;
+  if (!request_->GetFullRequestHeaders(&headers))
+    return;
+
+  std::string mime_type;
+  request_->response_headers()->GetMimeType(&mime_type);
+  if (!base::EqualsCaseInsensitiveASCII(mime_type, kOMADrmMessageMimeType))
+    return;
+
+  net::CookieStore* cookie_store = request_->context()->cookie_store();
+  if (cookie_store) {
+    // Cookie is obtained via asynchonous call. Setting |*defer| to true
+    // keeps the throttle alive in the meantime.
+    *defer = true;
+    net::CookieOptions options;
+    options.set_include_httponly();
+    cookie_store->GetCookieListWithOptionsAsync(
+        request_->url(),
+        options,
+        base::Bind(&InterceptDownloadResourceThrottle::CheckCookiePolicy,
+                   weak_factory_.GetWeakPtr()));
+  } else {
+    // Can't get any cookies, start android download.
+    StartDownload(DownloadInfo(request_));
+  }
+}
+
+const char* InterceptDownloadResourceThrottle::GetNameForLogging() const {
+  return "InterceptDownloadResourceThrottle";
+}
+
+void InterceptDownloadResourceThrottle::CheckCookiePolicy(
+    const net::CookieList& cookie_list) {
+  DownloadInfo info(request_);
+  if (request_->context()->network_delegate()->CanGetCookies(*request_,
+                                                             cookie_list)) {
+    std::string cookie = net::CookieStore::BuildCookieLine(cookie_list);
+    if (!cookie.empty())
+      info.cookie = cookie;
+  }
+  StartDownload(info);
+}
+
+void InterceptDownloadResourceThrottle::StartDownload(
+    const DownloadInfo& info) {
+  DownloadControllerBase::Get()->CreateAndroidDownload(wc_getter_, info);
+  Cancel();
+}
diff --git a/chrome/browser/android/download/intercept_download_resource_throttle.h b/chrome/browser/android/download/intercept_download_resource_throttle.h
new file mode 100644
index 0000000..045a7aa
--- /dev/null
+++ b/chrome/browser/android/download/intercept_download_resource_throttle.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_DOWNLOAD_INTERCEPT_DOWNLOAD_RESOURCE_THROTTLE_H_
+#define CHROME_BROWSER_ANDROID_DOWNLOAD_INTERCEPT_DOWNLOAD_RESOURCE_THROTTLE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/android/download/download_controller_base.h"
+#include "content/public/browser/resource_request_info.h"
+#include "content/public/browser/resource_throttle.h"
+#include "net/cookies/cookie_store.h"
+
+namespace net {
+class URLRequest;
+}
+
+// InterceptDownloadResourceThrottle checks if a download request should be
+// handled by Chrome or passsed to the Android Download Manager.
+class InterceptDownloadResourceThrottle : public content::ResourceThrottle {
+ public:
+  InterceptDownloadResourceThrottle(
+      net::URLRequest* request,
+      const content::ResourceRequestInfo::WebContentsGetter& wc_getter);
+  ~InterceptDownloadResourceThrottle() override;
+
+  // content::ResourceThrottle implementation:
+  void WillProcessResponse(bool* defer) override;
+  const char* GetNameForLogging() const override;
+
+ private:
+  void CheckCookiePolicy(const net::CookieList& cookie_list);
+  void StartDownload(const DownloadInfo& info);
+
+  const net::URLRequest* request_;
+  content::ResourceRequestInfo::WebContentsGetter wc_getter_;
+
+  base::WeakPtrFactory<InterceptDownloadResourceThrottle> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(InterceptDownloadResourceThrottle);
+};
+
+#endif  // CHROME_BROWSER_ANDROID_DOWNLOAD_INTERCEPT_DOWNLOAD_RESOURCE_THROTTLE_H_
diff --git a/chrome/browser/android/download/mock_download_controller.cc b/chrome/browser/android/download/mock_download_controller.cc
index 1df9ec8..a92fd0b 100644
--- a/chrome/browser/android/download/mock_download_controller.cc
+++ b/chrome/browser/android/download/mock_download_controller.cc
@@ -39,5 +39,9 @@
   approve_file_access_request_ = approve;
 }
 
+void MockDownloadController::CreateAndroidDownload(
+    const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+    const DownloadInfo& info) {}
+
 }  // namespace android
 }  // namespace chrome
diff --git a/chrome/browser/android/download/mock_download_controller.h b/chrome/browser/android/download/mock_download_controller.h
index 2913294..4339ea3 100644
--- a/chrome/browser/android/download/mock_download_controller.h
+++ b/chrome/browser/android/download/mock_download_controller.h
@@ -34,7 +34,9 @@
       content::WebContents* web_contents,
       const AcquireFileAccessPermissionCallback& callback) override;
   void SetApproveFileAccessRequestForTesting(bool approve) override;
-
+  void CreateAndroidDownload(
+      const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+      const DownloadInfo& info) override;
  private:
   bool approve_file_access_request_;
   DISALLOW_COPY_AND_ASSIGN(MockDownloadController);
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc
index bfa8416..247962bc 100644
--- a/chrome/browser/android/favicon_helper.cc
+++ b/chrome/browser/android/favicon_helper.cc
@@ -30,7 +30,6 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/android/java_bitmap.h"
 #include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/color_analysis.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_rep.h"
@@ -185,19 +184,6 @@
 
 FaviconHelper::~FaviconHelper() {}
 
-static jint GetDominantColorForBitmap(JNIEnv* env,
-                                      const JavaParamRef<jclass>& clazz,
-                                      const JavaParamRef<jobject>& bitmap) {
-  if (!bitmap)
-    return 0;
-
-  gfx::JavaBitmap bitmap_lock(bitmap);
-  SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(bitmap_lock);
-  return color_utils::CalculateKMeanColorOfBitmap(skbitmap);
-}
-
-// static
-
 // Return the index of |sizes| whose area is largest but not exceeds int type
 // range. If all |sizes|'s area exceed int type range, return the first one.
 size_t FaviconHelper::GetLargestSizeIndex(const std::vector<gfx::Size>& sizes) {
diff --git a/chrome/browser/android/ntp/content_suggestions_notifier_service.cc b/chrome/browser/android/ntp/content_suggestions_notifier_service.cc
index bfc15e8..07745355 100644
--- a/chrome/browser/android/ntp/content_suggestions_notifier_service.cc
+++ b/chrome/browser/android/ntp/content_suggestions_notifier_service.cc
@@ -170,6 +170,12 @@
   }
 
   void AppStatusChanged(base::android::ApplicationState state) {
+    if (variations::GetVariationParamByFeatureAsBool(
+            kContentSuggestionsNotificationsFeature,
+            kContentSuggestionsNotificationsKeepNotificationWhenFrontmostParam,
+            false)) {
+      return;
+    }
     if (!ShouldNotifyInState(state)) {
       ContentSuggestionsNotificationHelper::HideAllNotifications(
           CONTENT_SUGGESTIONS_HIDE_FRONTMOST);
diff --git a/chrome/browser/android/vr_shell/ui_scene.cc b/chrome/browser/android/vr_shell/ui_scene.cc
index 1cfad01..1bb1aa89 100644
--- a/chrome/browser/android/vr_shell/ui_scene.cc
+++ b/chrome/browser/android/vr_shell/ui_scene.cc
@@ -318,6 +318,10 @@
   }
 }
 
+void UiScene::UpdateBackgroundFromDict(const base::DictionaryValue& dict) {
+  ParseColorf(dict, "color", &background_color_);
+}
+
 void UiScene::HandleCommands(std::unique_ptr<base::ListValue> commands,
                              int64_t time_in_micro) {
   for (auto& item : *commands) {
@@ -352,6 +356,9 @@
         RemoveAnimation(element_id, animation_id);
         break;
       }
+      case Command::UPDATE_BACKGROUND:
+        UpdateBackgroundFromDict(*data);
+        break;
     }
   }
 }
@@ -384,6 +391,10 @@
   return content_element_;
 }
 
+const Colorf& UiScene::GetBackgroundColor() {
+  return background_color_;
+}
+
 const std::vector<std::unique_ptr<ContentRectangle>>&
 UiScene::GetUiElements() const {
   return ui_elements_;
diff --git a/chrome/browser/android/vr_shell/ui_scene.h b/chrome/browser/android/vr_shell/ui_scene.h
index 1de52bf2..1b1686f 100644
--- a/chrome/browser/android/vr_shell/ui_scene.h
+++ b/chrome/browser/android/vr_shell/ui_scene.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "chrome/browser/android/vr_shell/vr_math.h"
 
 namespace base {
 class DictionaryValue;
@@ -29,6 +30,7 @@
     REMOVE_ELEMENT,
     ADD_ANIMATION,
     REMOVE_ANIMATION,
+    UPDATE_BACKGROUND,
   };
 
   UiScene();
@@ -54,6 +56,8 @@
   // Remove |animation_id| from element |element_id|.
   void RemoveAnimation(int element_id, int animation_id);
 
+  void UpdateBackgroundFromDict(const base::DictionaryValue& dict);
+
   // Update the positions of all elements in the scene, according to active
   // animations, desired screen tilt and time.  The units of time are
   // arbitrary, but must match the unit used in animations.
@@ -69,6 +73,8 @@
 
   ContentRectangle* GetContentQuad();
 
+  const Colorf& GetBackgroundColor();
+
  private:
   void ApplyRecursiveTransforms(const ContentRectangle& element,
                                 ReversibleTransform* transform,
@@ -78,6 +84,7 @@
 
   std::vector<std::unique_ptr<ContentRectangle>> ui_elements_;
   ContentRectangle* content_element_ = nullptr;
+  Colorf background_color_ = {0.1f, 0.1f, 0.1f, 1.0f};
 
   DISALLOW_COPY_AND_ASSIGN(UiScene);
 };
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc
index e1d6515..d77ea0bc 100644
--- a/chrome/browser/android/vr_shell/vr_shell.cc
+++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -468,7 +468,8 @@
 }
 
 void VrShell::ForceExitVr() {
-  delegate_provider_->ForceExitVr();
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_VrShellImpl_forceExitVr(env, j_vr_shell_.obj());
 }
 
 void VrShell::OnVRVsyncProviderRequest(
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.cc b/chrome/browser/android/vr_shell/vr_shell_delegate.cc
index 6a0cc04..0cbd58ea 100644
--- a/chrome/browser/android/vr_shell/vr_shell_delegate.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_delegate.cc
@@ -157,11 +157,6 @@
   Java_VrShellDelegate_exitWebVR(env, j_vr_shell_delegate_.obj());
 }
 
-void VrShellDelegate::ForceExitVr() {
-  JNIEnv* env = AttachCurrentThread();
-  Java_VrShellDelegate_forceExitVr(env, j_vr_shell_delegate_.obj());
-}
-
 base::WeakPtr<VrShellDelegate> VrShellDelegate::GetWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
 }
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.h b/chrome/browser/android/vr_shell/vr_shell_delegate.h
index de0e2c0..af7b99a7 100644
--- a/chrome/browser/android/vr_shell/vr_shell_delegate.h
+++ b/chrome/browser/android/vr_shell/vr_shell_delegate.h
@@ -42,7 +42,6 @@
   void OnPause(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
   void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
 
-  void ForceExitVr();
   device::GvrDeviceProvider* device_provider() { return device_provider_; }
   void OnVRVsyncProviderRequest(device::mojom::VRVSyncProviderRequest request);
   base::WeakPtr<VrShellDelegate> GetWeakPtr();
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc
index 58c00bb18..0277e5b 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -726,7 +726,9 @@
     glEnable(GL_DEPTH_TEST);
     glDepthMask(GL_TRUE);
 
-    glClearColor(kFogBrightness, kFogBrightness, kFogBrightness, 1.0f);
+    const Colorf& backgroundColor = scene_->GetBackgroundColor();
+    glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b,
+                 backgroundColor.a);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   }
   if (!world_elements.empty()) {
diff --git a/chrome/browser/android/vr_shell/vr_shell_renderer.cc b/chrome/browser/android/vr_shell/vr_shell_renderer.cc
index c30b383f..2d79381 100644
--- a/chrome/browser/android/vr_shell/vr_shell_renderer.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_renderer.cc
@@ -504,6 +504,8 @@
     MakeGridLines(gridline_count);
   }
 
+  glUseProgram(program_handle_);
+
   // Pass in model view project matrix.
   glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false,
                      MatrixToGLArray(view_proj_matrix).data());
@@ -519,9 +521,11 @@
   glUniform1f(opacity_handle_, opacity);
 
   // Draw the grid.
-  glEnableVertexAttribArray(position_handle_);
   glVertexAttribPointer(position_handle_, kPositionDataSize, GL_FLOAT, false, 0,
                         (float*)grid_lines_.data());
+  glEnableVertexAttribArray(position_handle_);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   int verticesNumber = 4 * (gridline_count + 1);
   glDrawArrays(GL_LINES, 0, verticesNumber);
 
diff --git a/chrome/browser/background_sync/PRESUBMIT.py b/chrome/browser/background_sync/PRESUBMIT.py
deleted file mode 100644
index 7df0d54..0000000
--- a/chrome/browser/background_sync/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for src/chrome/browser/background_sync/
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/chrome/browser/budget_service/PRESUBMIT.py b/chrome/browser/budget_service/PRESUBMIT.py
deleted file mode 100644
index c91540dc..0000000
--- a/chrome/browser/budget_service/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +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.
-
-"""Top-level presubmit script for the Budget Service.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/chrome/browser/budget_service/budget_manager.cc b/chrome/browser/budget_service/budget_manager.cc
index 7e07480..a60053e 100644
--- a/chrome/browser/budget_service/budget_manager.cc
+++ b/chrome/browser/budget_service/budget_manager.cc
@@ -13,9 +13,6 @@
 #include "base/time/time.h"
 #include "chrome/browser/engagement/site_engagement_score.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/origin_util.h"
 #include "third_party/WebKit/public/platform/modules/budget_service/budget_service.mojom.h"
@@ -23,17 +20,6 @@
 
 using content::BrowserThread;
 
-namespace {
-
-// Previously, budget information was stored in the prefs. If there is any old
-// information still there, clear it.
-// TODO(harkness): Remove once Chrome 56 has branched.
-void ClearBudgetDataFromPrefs(Profile* profile) {
-  profile->GetPrefs()->ClearPref(prefs::kBackgroundBudgetMap);
-}
-
-}  // namespace
-
 BudgetManager::BudgetManager(Profile* profile)
     : profile_(profile),
       db_(profile,
@@ -43,18 +29,11 @@
                   base::SequencedWorkerPool::GetSequenceToken(),
                   base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)),
       weak_ptr_factory_(this) {
-  ClearBudgetDataFromPrefs(profile);
 }
 
 BudgetManager::~BudgetManager() {}
 
 // static
-void BudgetManager::RegisterProfilePrefs(
-    user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterDictionaryPref(prefs::kBackgroundBudgetMap);
-}
-
-// static
 double BudgetManager::GetCost(blink::mojom::BudgetOperationType type) {
   switch (type) {
     case blink::mojom::BudgetOperationType::SILENT_PUSH:
diff --git a/chrome/browser/budget_service/budget_manager.h b/chrome/browser/budget_service/budget_manager.h
index 0f09631..708648f 100644
--- a/chrome/browser/budget_service/budget_manager.h
+++ b/chrome/browser/budget_service/budget_manager.h
@@ -16,10 +16,6 @@
 
 class Profile;
 
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
 namespace url {
 class Origin;
 }
@@ -33,8 +29,6 @@
   explicit BudgetManager(Profile* profile);
   ~BudgetManager() override;
 
-  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-
   // Query for the base cost for any background processing.
   static double GetCost(blink::mojom::BudgetOperationType type);
 
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc
index a8c8150..47715a06 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.cc
+++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -161,7 +161,7 @@
                                                 &version_number, &special_build,
                                                 &channel_name);
 
-    base::debug::ActivityUserData& global_data = global_tracker->user_data();
+    base::debug::ActivityUserData& global_data = global_tracker->global_data();
     global_data.SetString(browser_watcher::kStabilityProduct, product_name);
     global_data.SetString(browser_watcher::kStabilityVersion, version_number);
     global_data.SetString(browser_watcher::kStabilityChannel, channel_name);
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 4d3d5dd..0a1c5f7a 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -53,6 +53,7 @@
 #include "chrome/browser/component_updater/origin_trials_component_installer.h"
 #include "chrome/browser/component_updater/pepper_flash_component_installer.h"
 #include "chrome/browser/component_updater/recovery_component_installer.h"
+#include "chrome/browser/component_updater/recovery_improved_component_installer.h"
 #include "chrome/browser/component_updater/sth_set_component_installer.h"
 #include "chrome/browser/component_updater/subresource_filter_component_installer.h"
 #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
@@ -475,7 +476,10 @@
   // file IO to know you existing component version.
 #if !defined(OS_ANDROID)
 #if !defined(OS_CHROMEOS)
-  RegisterRecoveryComponent(cus, g_browser_process->local_state());
+  if (base::FeatureList::IsEnabled(features::kImprovedRecoveryComponent))
+    RegisterRecoveryImprovedComponent(cus, g_browser_process->local_state());
+  else
+    RegisterRecoveryComponent(cus, g_browser_process->local_state());
 #endif  // !defined(OS_CHROMEOS)
   RegisterPepperFlashComponent(cus);
 #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 327f3ac..d1a1864 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2518,6 +2518,8 @@
 
   if (!prefs->GetBoolean(prefs::kWebKitPluginsEnabled))
     web_prefs->plugins_enabled = false;
+  web_prefs->encrypted_media_enabled =
+      prefs->GetBoolean(prefs::kWebKitEncryptedMediaEnabled);
   web_prefs->loads_images_automatically =
       prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically);
 
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index c206c0ff..6d382dd 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1196,6 +1196,8 @@
     "printing/printer_pref_manager.h",
     "printing/printer_pref_manager_factory.cc",
     "printing/printer_pref_manager_factory.h",
+    "printing/printers_sync_bridge.cc",
+    "printing/printers_sync_bridge.h",
     "printing/specifics_translation.cc",
     "printing/specifics_translation.h",
     "profiles/avatar_menu_actions_chromeos.cc",
diff --git a/chrome/browser/chromeos/PRESUBMIT.py b/chrome/browser/chromeos/PRESUBMIT.py
deleted file mode 100644
index 64582bf0..0000000
--- a/chrome/browser/chromeos/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for chromeos.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc
index b84c394..b74c3e6 100644
--- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc
+++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc
@@ -4,6 +4,7 @@
 
 #include <chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h>
 
+#include "base/time/time.h"
 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -16,6 +17,10 @@
 
 namespace chromeos {
 
+// Timeout maintenance session after 30 minutes.
+constexpr base::TimeDelta kArcKioskMaintenanceSessionTimeout =
+    base::TimeDelta::FromMinutes(30);
+
 // Blocks all notifications for ARC++ Kiosk
 class ArcKioskNotificationBlocker : public message_center::NotificationBlocker {
  public:
@@ -109,9 +114,17 @@
 void ArcKioskAppService::OnMaintenanceSessionCreated() {
   maintenance_session_running_ = true;
   PreconditionsChanged();
+  // Safe to bind |this| as timer is auto-cancelled on destruction.
+  maintenance_timeout_timer_.Start(
+      FROM_HERE, kArcKioskMaintenanceSessionTimeout,
+      base::Bind(&ArcKioskAppService::OnMaintenanceSessionFinished,
+                 base::Unretained(this)));
 }
 
 void ArcKioskAppService::OnMaintenanceSessionFinished() {
+  if (!maintenance_timeout_timer_.IsRunning())
+    VLOG(1) << "Maintenance session timeout";
+  maintenance_timeout_timer_.Stop();
   maintenance_session_running_ = false;
   PreconditionsChanged();
 }
@@ -137,7 +150,9 @@
   PreconditionsChanged();
 }
 
-ArcKioskAppService::~ArcKioskAppService() = default;
+ArcKioskAppService::~ArcKioskAppService() {
+  maintenance_timeout_timer_.Stop();
+}
 
 void ArcKioskAppService::PreconditionsChanged() {
   app_id_ = GetAppId();
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h
index 2d5687e..ac3bf51 100644
--- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h
+++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_APP_MODE_ARC_ARC_KIOSK_APP_SERVICE_H_
 
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_launcher.h"
 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
@@ -88,6 +89,7 @@
 
   Profile* const profile_;
   bool maintenance_session_running_ = false;
+  base::OneShotTimer maintenance_timeout_timer_;
   ArcKioskAppManager* app_manager_;
   std::string app_id_;
   std::unique_ptr<ArcAppListPrefs::AppInfo> app_info_;
diff --git a/chrome/browser/chromeos/arc/arc_optin_uma.cc b/chrome/browser/chromeos/arc/arc_optin_uma.cc
index dfa391a..cea4e1c4 100644
--- a/chrome/browser/chromeos/arc/arc_optin_uma.cc
+++ b/chrome/browser/chromeos/arc/arc_optin_uma.cc
@@ -56,4 +56,40 @@
                             static_cast<int>(OptInSilentAuthCode::SIZE));
 }
 
+std::ostream& operator<<(std::ostream& os, const ProvisioningResult& result) {
+#define MAP_PROVISIONING_RESULT(name) \
+  case ProvisioningResult::name:      \
+    return os << #name
+
+  switch (result) {
+    MAP_PROVISIONING_RESULT(SUCCESS);
+    MAP_PROVISIONING_RESULT(UNKNOWN_ERROR);
+    MAP_PROVISIONING_RESULT(GMS_NETWORK_ERROR);
+    MAP_PROVISIONING_RESULT(GMS_SERVICE_UNAVAILABLE);
+    MAP_PROVISIONING_RESULT(GMS_BAD_AUTHENTICATION);
+    MAP_PROVISIONING_RESULT(DEVICE_CHECK_IN_FAILED);
+    MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_FAILED);
+    MAP_PROVISIONING_RESULT(MOJO_VERSION_MISMATCH);
+    MAP_PROVISIONING_RESULT(MOJO_CALL_TIMEOUT);
+    MAP_PROVISIONING_RESULT(DEVICE_CHECK_IN_TIMEOUT);
+    MAP_PROVISIONING_RESULT(DEVICE_CHECK_IN_INTERNAL_ERROR);
+    MAP_PROVISIONING_RESULT(GMS_SIGN_IN_FAILED);
+    MAP_PROVISIONING_RESULT(GMS_SIGN_IN_TIMEOUT);
+    MAP_PROVISIONING_RESULT(GMS_SIGN_IN_INTERNAL_ERROR);
+    MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_TIMEOUT);
+    MAP_PROVISIONING_RESULT(CLOUD_PROVISION_FLOW_INTERNAL_ERROR);
+    MAP_PROVISIONING_RESULT(ARC_STOPPED);
+    MAP_PROVISIONING_RESULT(OVERALL_SIGN_IN_TIMEOUT);
+    MAP_PROVISIONING_RESULT(CHROME_SERVER_COMMUNICATION_ERROR);
+    MAP_PROVISIONING_RESULT(SIZE);
+  }
+
+#undef MAP_PROVISIONING_RESULT
+
+  // Some compilers report an error even if all values of an enum-class are
+  // covered exhaustively in a switch statement.
+  NOTREACHED() << "Invalid value " << static_cast<int>(result);
+  return os;
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/arc_optin_uma.h b/chrome/browser/chromeos/arc/arc_optin_uma.h
index c6cd240..4e4f534 100644
--- a/chrome/browser/chromeos/arc/arc_optin_uma.h
+++ b/chrome/browser/chromeos/arc/arc_optin_uma.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_CHROMEOS_ARC_ARC_OPTIN_UMA_H_
 #define CHROME_BROWSER_CHROMEOS_ARC_ARC_OPTIN_UMA_H_
 
+#include <ostream>
+
 namespace base {
 class TimeDelta;
 }
@@ -120,6 +122,9 @@
                               bool managed);
 void UpdateSilentAuthCodeUMA(OptInSilentAuthCode state);
 
+// Outputs the stringified |result| to |os|. This is only for logging purposes.
+std::ostream& operator<<(std::ostream& os, const ProvisioningResult& result);
+
 }  // namespace arc
 
 #endif  // CHROME_BROWSER_CHROMEOS_ARC_ARC_OPTIN_UMA_H_
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index 0582a43..a1a050fc 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -167,6 +167,7 @@
   if (profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
     // This should be always true, but just in case as this is looked at
     // inside RemoveArcData() at first.
+    VLOG(1) << "ARC had previously requested to remove user data.";
     DCHECK(arc_session_runner_->IsStopped());
     RemoveArcData();
   } else {
@@ -196,6 +197,7 @@
     return;
   }
 
+  VLOG(1) << "Starting ARC data removal";
   SetState(State::REMOVING_DATA_DIR);
   chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->RemoveArcData(
       cryptohome::Identification(
@@ -205,7 +207,10 @@
 }
 
 void ArcSessionManager::OnArcDataRemoved(bool success) {
-  LOG_IF(ERROR, !success) << "Required ARC user data wipe failed.";
+  if (success)
+    VLOG(1) << "ARC data removal successful";
+  else
+    LOG(ERROR) << "Request for ARC user data removal failed.";
 
   // TODO(khmel): Browser tests may shutdown profile by itself. Update browser
   // tests and remove this check.
@@ -313,6 +318,7 @@
   }
 
   ArcSupportHost::Error error;
+  VLOG(1) << "ARC provisioning failed: " << result << ".";
   switch (result) {
     case ProvisioningResult::GMS_NETWORK_ERROR:
       error = ArcSupportHost::Error::SIGN_IN_NETWORK_ERROR;
@@ -362,6 +368,7 @@
       result == ProvisioningResult::OVERALL_SIGN_IN_TIMEOUT ||
       // Just to be safe, remove data if we don't know the cause.
       result == ProvisioningResult::UNKNOWN_ERROR) {
+    VLOG(1) << "ARC provisioning failed permanently. Removing user data";
     RemoveArcData();
   }
 
@@ -433,11 +440,13 @@
     // ARC once data removal finishes.
     if (profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) {
       reenable_arc_ = true;
+      VLOG(1) << "ARC previously requested to remove data.";
       RemoveArcData();
     } else {
       OnOptInPreferenceChanged();
     }
   } else {
+    VLOG(1) << "ARC disabled on profile. Removing data.";
     RemoveArcData();
     PrefServiceSyncableFromProfile(profile_)->AddObserver(this);
     OnIsSyncingChanged();
@@ -522,7 +531,8 @@
   }
 
   if (!arc_enabled) {
-    // Reset any pending request to re-enable Arc.
+    // Reset any pending request to re-enable ARC.
+    VLOG(1) << "ARC opt-out. Removing user data.";
     reenable_arc_ = false;
     StopArc();
     RemoveArcData();
@@ -948,24 +958,24 @@
 
 std::ostream& operator<<(std::ostream& os,
                          const ArcSessionManager::State& state) {
+#define MAP_STATE(name)                \
+  case ArcSessionManager::State::name: \
+    return os << #name
+
   switch (state) {
-    case ArcSessionManager::State::NOT_INITIALIZED:
-      return os << "NOT_INITIALIZED";
-    case ArcSessionManager::State::STOPPED:
-      return os << "STOPPED";
-    case ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE:
-      return os << "SHOWING_TERMS_OF_SERVICE";
-    case ArcSessionManager::State::CHECKING_ANDROID_MANAGEMENT:
-      return os << "CHECKING_ANDROID_MANAGEMENT";
-    case ArcSessionManager::State::REMOVING_DATA_DIR:
-      return os << "REMOVING_DATA_DIR";
-    case ArcSessionManager::State::ACTIVE:
-      return os << "ACTIVE";
+    MAP_STATE(NOT_INITIALIZED);
+    MAP_STATE(STOPPED);
+    MAP_STATE(SHOWING_TERMS_OF_SERVICE);
+    MAP_STATE(CHECKING_ANDROID_MANAGEMENT);
+    MAP_STATE(REMOVING_DATA_DIR);
+    MAP_STATE(ACTIVE);
   }
 
-  // Some compiler reports an error even if all values of an enum-class are
-  // covered indivisually in a switch statement.
-  NOTREACHED();
+#undef MAP_STATE
+
+  // Some compilers report an error even if all values of an enum-class are
+  // covered exhaustively in a switch statement.
+  NOTREACHED() << "Invalid value " << static_cast<int>(state);
   return os;
 }
 
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.h b/chrome/browser/chromeos/arc/arc_session_manager.h
index 0503f5f..9675a14f 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.h
+++ b/chrome/browser/chromeos/arc/arc_session_manager.h
@@ -190,7 +190,8 @@
   void StopAndEnableArc();
 
   // Removes the data if ARC is stopped. Otherwise, queue to remove the data
-  // on ARC is stopped.
+  // on ARC is stopped. A log statement with the removal reason must be added
+  // prior to calling RemoveArcData().
   void RemoveArcData();
 
   ArcSupportHost* support_host() { return support_host_.get(); }
diff --git a/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc b/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc
index 009f5ca..834962e 100644
--- a/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc
+++ b/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.cc
@@ -40,6 +40,7 @@
 
   if (state == mojom::ManagementState::MANAGED_DO_LOST) {
     DCHECK(ArcServiceManager::Get());
+    VLOG(1) << "Management state lost. Removing ARC user data.";
     ArcSessionManager::Get()->RemoveArcData();
     ArcSessionManager::Get()->StopAndEnableArc();
   }
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
index c4aad82..b52c9cac 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
@@ -117,18 +117,20 @@
   void SyncRuntimeSettings() const;
   // Send settings that need to be synced only on Android first start to
   // Android.
-  void SyncInitialSettings() const;
+  // Keep these lines ordered lexicographically.
+  void SyncAccessibilityLargeMouseCursorEnabled() const;
+  void SyncAccessibilityVirtualKeyboardEnabled() const;
+  void SyncBackupEnabled() const;
   void SyncFocusHighlightEnabled() const;
   void SyncFontSize() const;
+  void SyncInitialSettings() const;
   void SyncLocale() const;
+  void SyncLocationServiceEnabled() const;
   void SyncProxySettings() const;
   void SyncReportingConsent() const;
   void SyncSpokenFeedbackEnabled() const;
   void SyncTimeZone() const;
   void SyncUse24HourClock() const;
-  void SyncBackupEnabled() const;
-  void SyncLocationServiceEnabled() const;
-  void SyncAccessibilityVirtualKeyboardEnabled() const;
 
   void OnBluetoothAdapterInitialized(
       scoped_refptr<device::BluetoothAdapter> adapter);
@@ -182,15 +184,81 @@
     bluetooth_adapter_->RemoveObserver(this);
 }
 
+void ArcSettingsServiceImpl::OnPrefChanged(const std::string& pref_name) const {
+  VLOG(1) << "OnPrefChanged: " << pref_name;
+  // Keep these lines ordered lexicographically by pref_name.
+  if (pref_name == onc::prefs::kDeviceOpenNetworkConfiguration ||
+      pref_name == onc::prefs::kOpenNetworkConfiguration) {
+    // Only update proxy settings if kProxy pref is not applied.
+    if (IsPrefProxyConfigApplied()) {
+      LOG(ERROR) << "Open Network Configuration proxy settings are not applied,"
+                 << " because kProxy preference is configured.";
+      return;
+    }
+    SyncProxySettings();
+  } else if (pref_name == prefs::kAccessibilityFocusHighlightEnabled) {
+    SyncFocusHighlightEnabled();
+  } else if (pref_name == prefs::kAccessibilityLargeCursorEnabled) {
+    SyncAccessibilityLargeMouseCursorEnabled();
+  } else if (pref_name == prefs::kAccessibilitySpokenFeedbackEnabled) {
+    SyncSpokenFeedbackEnabled();
+  } else if (pref_name == prefs::kAccessibilityVirtualKeyboardEnabled) {
+    SyncAccessibilityVirtualKeyboardEnabled();
+  } else if (pref_name == prefs::kArcLocationServiceEnabled) {
+    const PrefService* const prefs =
+        ProfileManager::GetActiveUserProfile()->GetPrefs();
+    if (prefs->IsManagedPreference(prefs::kArcLocationServiceEnabled))
+      SyncLocationServiceEnabled();
+  } else if (pref_name == prefs::kUse24HourClock) {
+    SyncUse24HourClock();
+  } else if (pref_name == prefs::kWebKitDefaultFixedFontSize ||
+             pref_name == prefs::kWebKitDefaultFontSize ||
+             pref_name == prefs::kWebKitMinimumFontSize) {
+    SyncFontSize();
+  } else if (pref_name == proxy_config::prefs::kProxy) {
+    SyncProxySettings();
+  } else {
+    LOG(ERROR) << "Unknown pref changed.";
+  }
+}
+
+void ArcSettingsServiceImpl::TimezoneChanged(const icu::TimeZone& timezone) {
+  SyncTimeZone();
+}
+
+void ArcSettingsServiceImpl::AdapterPoweredChanged(
+    device::BluetoothAdapter* adapter,
+    bool powered) {
+  base::DictionaryValue extras;
+  extras.SetBoolean("enable", powered);
+  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_BLUETOOTH_STATE",
+                        extras);
+}
+
+void ArcSettingsServiceImpl::OnArcInitialStart() {
+  SyncInitialSettings();
+}
+
+void ArcSettingsServiceImpl::DefaultNetworkChanged(
+    const chromeos::NetworkState* network) {
+  // kProxy pref has more priority than the default network update.
+  // If a default network is changed to the network with ONC policy with proxy
+  // settings, it should be translated here.
+  if (network && !IsPrefProxyConfigApplied())
+    SyncProxySettings();
+}
+
 void ArcSettingsServiceImpl::StartObservingSettingsChanges() {
   Profile* profile = ProfileManager::GetActiveUserProfile();
   registrar_.Init(profile->GetPrefs());
 
   // Keep these lines ordered lexicographically.
   AddPrefToObserve(prefs::kAccessibilityFocusHighlightEnabled);
+  AddPrefToObserve(prefs::kAccessibilityLargeCursorEnabled);
   AddPrefToObserve(prefs::kAccessibilitySpokenFeedbackEnabled);
   AddPrefToObserve(prefs::kAccessibilityVirtualKeyboardEnabled);
   AddPrefToObserve(prefs::kArcBackupRestoreEnabled);
+  AddPrefToObserve(prefs::kArcLocationServiceEnabled);
   AddPrefToObserve(prefs::kUse24HourClock);
   AddPrefToObserve(prefs::kWebKitDefaultFixedFontSize);
   AddPrefToObserve(prefs::kWebKitDefaultFontSize);
@@ -216,21 +284,18 @@
       this, FROM_HERE);
 }
 
-void ArcSettingsServiceImpl::OnBluetoothAdapterInitialized(
-    scoped_refptr<device::BluetoothAdapter> adapter) {
-  DCHECK(adapter);
-  bluetooth_adapter_ = adapter;
-  bluetooth_adapter_->AddObserver(this);
+void ArcSettingsServiceImpl::StopObservingSettingsChanges() {
+  registrar_.RemoveAll();
+  reporting_consent_subscription_.reset();
 
-  AdapterPoweredChanged(adapter.get(), adapter->IsPowered());
-}
-
-void ArcSettingsServiceImpl::OnArcInitialStart() {
-  SyncInitialSettings();
+  TimezoneSettings::GetInstance()->RemoveObserver(this);
+  chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+      this, FROM_HERE);
 }
 
 void ArcSettingsServiceImpl::SyncRuntimeSettings() const {
   // Keep these lines ordered lexicographically.
+  SyncAccessibilityLargeMouseCursorEnabled();
   SyncAccessibilityVirtualKeyboardEnabled();
   SyncFocusHighlightEnabled();
   SyncFontSize();
@@ -249,75 +314,28 @@
     SyncLocationServiceEnabled();
 }
 
-void ArcSettingsServiceImpl::SyncInitialSettings() const {
-  SyncBackupEnabled();
-  SyncLocationServiceEnabled();
+void ArcSettingsServiceImpl::SyncAccessibilityLargeMouseCursorEnabled() const {
+  SendBoolPrefSettingsBroadcast(
+      prefs::kAccessibilityLargeCursorEnabled,
+      "org.chromium.arc.intent_helper.ACCESSIBILITY_LARGE_POINTER_ICON");
 }
 
-void ArcSettingsServiceImpl::StopObservingSettingsChanges() {
-  registrar_.RemoveAll();
-  reporting_consent_subscription_.reset();
-
-  TimezoneSettings::GetInstance()->RemoveObserver(this);
-  chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
-      this, FROM_HERE);
+void ArcSettingsServiceImpl::SyncAccessibilityVirtualKeyboardEnabled() const {
+  SendBoolPrefSettingsBroadcast(
+      prefs::kAccessibilityVirtualKeyboardEnabled,
+      "org.chromium.arc.intent_helper.SET_SHOW_IME_WITH_HARD_KEYBOARD");
 }
 
-void ArcSettingsServiceImpl::AddPrefToObserve(const std::string& pref_name) {
-  registrar_.Add(pref_name, base::Bind(&ArcSettingsServiceImpl::OnPrefChanged,
-                                       base::Unretained(this)));
+void ArcSettingsServiceImpl::SyncBackupEnabled() const {
+  SendBoolPrefSettingsBroadcast(
+      prefs::kArcBackupRestoreEnabled,
+      "org.chromium.arc.intent_helper.SET_BACKUP_ENABLED");
 }
 
-void ArcSettingsServiceImpl::AdapterPoweredChanged(
-    device::BluetoothAdapter* adapter,
-    bool powered) {
-  base::DictionaryValue extras;
-  extras.SetBoolean("enable", powered);
-  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_BLUETOOTH_STATE",
-                        extras);
-}
-
-void ArcSettingsServiceImpl::OnPrefChanged(const std::string& pref_name) const {
-  if (pref_name == prefs::kAccessibilityFocusHighlightEnabled) {
-    SyncFocusHighlightEnabled();
-  } else if (pref_name == prefs::kAccessibilitySpokenFeedbackEnabled) {
-    SyncSpokenFeedbackEnabled();
-  } else if (pref_name == prefs::kWebKitDefaultFixedFontSize ||
-             pref_name == prefs::kWebKitDefaultFontSize ||
-             pref_name == prefs::kWebKitMinimumFontSize) {
-    SyncFontSize();
-  } else if (pref_name == prefs::kUse24HourClock) {
-    SyncUse24HourClock();
-  } else if (pref_name == proxy_config::prefs::kProxy) {
-    SyncProxySettings();
-  } else if (pref_name == onc::prefs::kDeviceOpenNetworkConfiguration ||
-             pref_name == onc::prefs::kOpenNetworkConfiguration) {
-    // Only update proxy settings if kProxy pref is not applied.
-    if (IsPrefProxyConfigApplied()) {
-      LOG(ERROR) << "Open Network Configuration proxy settings are not applied,"
-                 << " because kProxy preference is configured.";
-      return;
-    }
-    SyncProxySettings();
-  } else if (pref_name == prefs::kAccessibilityVirtualKeyboardEnabled) {
-    SyncAccessibilityVirtualKeyboardEnabled();
-  } else {
-    LOG(ERROR) << "Unknown pref changed.";
-  }
-}
-
-void ArcSettingsServiceImpl::TimezoneChanged(const icu::TimeZone& timezone) {
-  SyncTimeZone();
-}
-
-int ArcSettingsServiceImpl::GetIntegerPref(const std::string& pref_name) const {
-  const PrefService::Preference* pref =
-      registrar_.prefs()->FindPreference(pref_name);
-  DCHECK(pref);
-  int val = -1;
-  bool value_exists = pref->GetValue()->GetAsInteger(&val);
-  DCHECK(value_exists);
-  return val;
+void ArcSettingsServiceImpl::SyncFocusHighlightEnabled() const {
+  SendBoolPrefSettingsBroadcast(
+      prefs::kAccessibilityFocusHighlightEnabled,
+      "org.chromium.arc.intent_helper.SET_FOCUS_HIGHLIGHT_ENABLED");
 }
 
 void ArcSettingsServiceImpl::SyncFontSize() const {
@@ -334,31 +352,9 @@
                         extras);
 }
 
-void ArcSettingsServiceImpl::SendBoolPrefSettingsBroadcast(
-    const std::string& pref_name,
-    const std::string& action) const {
-  const PrefService::Preference* pref =
-      registrar_.prefs()->FindPreference(pref_name);
-  DCHECK(pref);
-  bool enabled = false;
-  bool value_exists = pref->GetValue()->GetAsBoolean(&enabled);
-  DCHECK(value_exists);
-  base::DictionaryValue extras;
-  extras.SetBoolean("enabled", enabled);
-  extras.SetBoolean("managed", !pref->IsUserModifiable());
-  SendSettingsBroadcast(action, extras);
-}
-
-void ArcSettingsServiceImpl::SyncFocusHighlightEnabled() const {
-  SendBoolPrefSettingsBroadcast(
-      prefs::kAccessibilityFocusHighlightEnabled,
-      "org.chromium.arc.intent_helper.SET_FOCUS_HIGHLIGHT_ENABLED");
-}
-
-void ArcSettingsServiceImpl::SyncSpokenFeedbackEnabled() const {
-  SendBoolPrefSettingsBroadcast(
-      prefs::kAccessibilitySpokenFeedbackEnabled,
-      "org.chromium.arc.intent_helper.SET_SPOKEN_FEEDBACK_ENABLED");
+void ArcSettingsServiceImpl::SyncInitialSettings() const {
+  SyncBackupEnabled();
+  SyncLocationServiceEnabled();
 }
 
 void ArcSettingsServiceImpl::SyncLocale() const {
@@ -373,34 +369,10 @@
   SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_LOCALE", extras);
 }
 
-void ArcSettingsServiceImpl::SyncReportingConsent() const {
-  bool consent = false;
-  CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref, &consent);
-  base::DictionaryValue extras;
-  extras.SetBoolean("reportingConsent", consent);
-  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_REPORTING_CONSENT",
-                        extras);
-}
-
-void ArcSettingsServiceImpl::SyncTimeZone() const {
-  TimezoneSettings* timezone_settings = TimezoneSettings::GetInstance();
-  base::string16 timezoneID = timezone_settings->GetCurrentTimezoneID();
-  base::DictionaryValue extras;
-  extras.SetString("olsonTimeZone", timezoneID);
-  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_TIME_ZONE", extras);
-}
-
-void ArcSettingsServiceImpl::SyncUse24HourClock() const {
-  const PrefService::Preference* pref =
-      registrar_.prefs()->FindPreference(prefs::kUse24HourClock);
-  DCHECK(pref);
-  bool use24HourClock = false;
-  bool value_exists = pref->GetValue()->GetAsBoolean(&use24HourClock);
-  DCHECK(value_exists);
-  base::DictionaryValue extras;
-  extras.SetBoolean("use24HourClock", use24HourClock);
-  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_USE_24_HOUR_CLOCK",
-                        extras);
+void ArcSettingsServiceImpl::SyncLocationServiceEnabled() const {
+  SendBoolPrefSettingsBroadcast(
+      prefs::kArcLocationServiceEnabled,
+      "org.chromium.arc.intent_helper.SET_LOCATION_SERVICE_ENABLED");
 }
 
 void ArcSettingsServiceImpl::SyncProxySettings() const {
@@ -461,22 +433,79 @@
   SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_PROXY", extras);
 }
 
-void ArcSettingsServiceImpl::SyncBackupEnabled() const {
-  SendBoolPrefSettingsBroadcast(
-      prefs::kArcBackupRestoreEnabled,
-      "org.chromium.arc.intent_helper.SET_BACKUP_ENABLED");
+void ArcSettingsServiceImpl::SyncReportingConsent() const {
+  bool consent = false;
+  CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref, &consent);
+  base::DictionaryValue extras;
+  extras.SetBoolean("reportingConsent", consent);
+  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_REPORTING_CONSENT",
+                        extras);
 }
 
-void ArcSettingsServiceImpl::SyncLocationServiceEnabled() const {
+void ArcSettingsServiceImpl::SyncSpokenFeedbackEnabled() const {
   SendBoolPrefSettingsBroadcast(
-      prefs::kArcLocationServiceEnabled,
-      "org.chromium.arc.intent_helper.SET_LOCATION_SERVICE_ENABLED");
+      prefs::kAccessibilitySpokenFeedbackEnabled,
+      "org.chromium.arc.intent_helper.SET_SPOKEN_FEEDBACK_ENABLED");
 }
 
-void ArcSettingsServiceImpl::SyncAccessibilityVirtualKeyboardEnabled() const {
-  SendBoolPrefSettingsBroadcast(
-      prefs::kAccessibilityVirtualKeyboardEnabled,
-      "org.chromium.arc.intent_helper.SET_SHOW_IME_WITH_HARD_KEYBOARD");
+void ArcSettingsServiceImpl::SyncTimeZone() const {
+  TimezoneSettings* timezone_settings = TimezoneSettings::GetInstance();
+  base::string16 timezoneID = timezone_settings->GetCurrentTimezoneID();
+  base::DictionaryValue extras;
+  extras.SetString("olsonTimeZone", timezoneID);
+  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_TIME_ZONE", extras);
+}
+
+void ArcSettingsServiceImpl::SyncUse24HourClock() const {
+  const PrefService::Preference* pref =
+      registrar_.prefs()->FindPreference(prefs::kUse24HourClock);
+  DCHECK(pref);
+  bool use24HourClock = false;
+  bool value_exists = pref->GetValue()->GetAsBoolean(&use24HourClock);
+  DCHECK(value_exists);
+  base::DictionaryValue extras;
+  extras.SetBoolean("use24HourClock", use24HourClock);
+  SendSettingsBroadcast("org.chromium.arc.intent_helper.SET_USE_24_HOUR_CLOCK",
+                        extras);
+}
+
+void ArcSettingsServiceImpl::OnBluetoothAdapterInitialized(
+    scoped_refptr<device::BluetoothAdapter> adapter) {
+  DCHECK(adapter);
+  bluetooth_adapter_ = adapter;
+  bluetooth_adapter_->AddObserver(this);
+
+  AdapterPoweredChanged(adapter.get(), adapter->IsPowered());
+}
+
+void ArcSettingsServiceImpl::AddPrefToObserve(const std::string& pref_name) {
+  registrar_.Add(pref_name, base::Bind(&ArcSettingsServiceImpl::OnPrefChanged,
+                                       base::Unretained(this)));
+}
+
+int ArcSettingsServiceImpl::GetIntegerPref(const std::string& pref_name) const {
+  const PrefService::Preference* pref =
+      registrar_.prefs()->FindPreference(pref_name);
+  DCHECK(pref);
+  int val = -1;
+  bool value_exists = pref->GetValue()->GetAsInteger(&val);
+  DCHECK(value_exists);
+  return val;
+}
+
+void ArcSettingsServiceImpl::SendBoolPrefSettingsBroadcast(
+    const std::string& pref_name,
+    const std::string& action) const {
+  const PrefService::Preference* pref =
+      registrar_.prefs()->FindPreference(pref_name);
+  DCHECK(pref);
+  bool enabled = false;
+  bool value_exists = pref->GetValue()->GetAsBoolean(&enabled);
+  DCHECK(value_exists);
+  base::DictionaryValue extras;
+  extras.SetBoolean("enabled", enabled);
+  extras.SetBoolean("managed", !pref->IsUserModifiable());
+  SendSettingsBroadcast(action, extras);
 }
 
 void ArcSettingsServiceImpl::SendSettingsBroadcast(
@@ -495,15 +524,6 @@
                           extras_json);
 }
 
-void ArcSettingsServiceImpl::DefaultNetworkChanged(
-    const chromeos::NetworkState* network) {
-  // kProxy pref has more priority than the default network update.
-  // If a default network is changed to the network with ONC policy with proxy
-  // settings, it should be translated here.
-  if (network && !IsPrefProxyConfigApplied())
-    SyncProxySettings();
-}
-
 ArcSettingsService::ArcSettingsService(ArcBridgeService* bridge_service)
     : ArcService(bridge_service) {
   arc_bridge_service()->intent_helper()->AddObserver(this);
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
index 906a70b..bdc2589 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
@@ -174,21 +174,35 @@
 
 constexpr char kONCPacUrl[] = "http://domain.com/x";
 
-// Returns an amount of |broadcasts| matched with |proxy_settings|.
-int CountProxyBroadcasts(
+constexpr char kLocationServiceBroadcastAction[] =
+    "org.chromium.arc.intent_helper.SET_LOCATION_SERVICE_ENABLED";
+constexpr char kSetProxyBroadcastAction[] =
+    "org.chromium.arc.intent_helper.SET_PROXY";
+
+// Returns the number of |broadcasts| having the |action| action, and checks
+// that all their extras match with |extras|.
+int CountBroadcasts(
     const std::vector<FakeIntentHelperInstance::Broadcast>& broadcasts,
-    const base::DictionaryValue* proxy_settings) {
-  size_t count = 0;
+    const std::string& action,
+    const base::DictionaryValue* extras) {
+  int count = 0;
   for (const FakeIntentHelperInstance::Broadcast& broadcast : broadcasts) {
-    if (broadcast.action == "org.chromium.arc.intent_helper.SET_PROXY") {
-      EXPECT_TRUE(
-          base::JSONReader::Read(broadcast.extras)->Equals(proxy_settings));
+    if (broadcast.action == action) {
+      EXPECT_TRUE(base::JSONReader::Read(broadcast.extras)->Equals(extras));
       count++;
     }
   }
   return count;
 }
 
+// Returns the number of |broadcasts| having the proxy action, and checks that
+// all their extras match with |extras|.
+int CountProxyBroadcasts(
+    const std::vector<FakeIntentHelperInstance::Broadcast>& broadcasts,
+    const base::DictionaryValue* proxy_settings) {
+  return CountBroadcasts(broadcasts, kSetProxyBroadcastAction, proxy_settings);
+}
+
 void RunUntilIdle() {
   DCHECK(base::MessageLoop::current());
   base::RunLoop loop;
@@ -303,6 +317,43 @@
   DISALLOW_COPY_AND_ASSIGN(ArcSettingsServiceTest);
 };
 
+IN_PROC_BROWSER_TEST_F(ArcSettingsServiceTest, LocationServicePolicyTest) {
+  fake_intent_helper_instance_->clear_broadcasts();
+
+  // The policy is set to false.
+  policy::PolicyMap policy;
+  policy.Set(policy::key::kArcLocationServiceEnabled,
+             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+             policy::POLICY_SOURCE_CLOUD, base::MakeUnique<base::Value>(false),
+             nullptr);
+  UpdatePolicy(policy);
+
+  // The broadcast is sent which says that the pref is disabled and managed.
+  base::DictionaryValue expected_broadcast_extras;
+  expected_broadcast_extras.SetBoolean("enabled", false);
+  expected_broadcast_extras.SetBoolean("managed", true);
+  EXPECT_EQ(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
+                            kLocationServiceBroadcastAction,
+                            &expected_broadcast_extras),
+            1);
+
+  fake_intent_helper_instance_->clear_broadcasts();
+
+  // The policy is set to true.
+  policy.Set(policy::key::kArcLocationServiceEnabled,
+             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+             policy::POLICY_SOURCE_CLOUD, base::MakeUnique<base::Value>(true),
+             nullptr);
+  UpdatePolicy(policy);
+
+  // The broadcast is sent which says that the pref is enabled and managed.
+  expected_broadcast_extras.SetBoolean("enabled", true);
+  EXPECT_EQ(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
+                            kLocationServiceBroadcastAction,
+                            &expected_broadcast_extras),
+            1);
+}
+
 IN_PROC_BROWSER_TEST_F(ArcSettingsServiceTest, ProxyModePolicyTest) {
   fake_intent_helper_instance_->clear_broadcasts();
 
diff --git a/chrome/browser/chromeos/base/locale_util.cc b/chrome/browser/chromeos/base/locale_util.cc
index e3c68b8..2ee1a76d 100644
--- a/chrome/browser/chromeos/base/locale_util.cc
+++ b/chrome/browser/chromeos/base/locale_util.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
@@ -120,8 +121,10 @@
                              login_layouts_only, callback, profile));
   base::Closure reloader(
       base::Bind(&SwitchLanguageDoReloadLocale, base::Unretained(data.get())));
-  content::BrowserThread::PostBlockingPoolTaskAndReply(
-      FROM_HERE, reloader,
+  base::PostTaskWithTraitsAndReply(
+      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                     base::TaskPriority::BACKGROUND),
+      reloader,
       base::Bind(&FinishSwitchLanguage, base::Passed(std::move(data))));
 }
 
diff --git a/chrome/browser/chromeos/boot_times_recorder.cc b/chrome/browser/chromeos/boot_times_recorder.cc
index af1df594..0d5cd76 100644
--- a/chrome/browser/chromeos/boot_times_recorder.cc
+++ b/chrome/browser/chromeos/boot_times_recorder.cc
@@ -23,6 +23,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_info.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -209,28 +210,26 @@
 }
 
 void BootTimesRecorder::Stats::RecordStats(const std::string& name) const {
-  BrowserThread::PostBlockingPoolTask(
-      FROM_HERE,
-      base::Bind(&BootTimesRecorder::Stats::RecordStatsImpl,
-                 base::Owned(new Stats(*this)),
-                 name));
+  base::PostTaskWithTraits(
+      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                     base::TaskPriority::BACKGROUND),
+      base::Bind(&BootTimesRecorder::Stats::RecordStatsAsync,
+                 base::Owned(new Stats(*this)), name));
 }
 
 void BootTimesRecorder::Stats::RecordStatsWithCallback(
     const std::string& name,
     const base::Closure& callback) const {
-  BrowserThread::PostBlockingPoolTaskAndReply(
-      FROM_HERE,
-      base::Bind(&BootTimesRecorder::Stats::RecordStatsImpl,
-                 base::Owned(new Stats(*this)),
-                 name),
+  base::PostTaskWithTraitsAndReply(
+      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                     base::TaskPriority::BACKGROUND),
+      base::Bind(&BootTimesRecorder::Stats::RecordStatsAsync,
+                 base::Owned(new Stats(*this)), name),
       callback);
 }
 
-void BootTimesRecorder::Stats::RecordStatsImpl(
+void BootTimesRecorder::Stats::RecordStatsAsync(
     const base::FilePath::StringType& name) const {
-  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
-
   const base::FilePath log_path(kLogPath);
   const base::FilePath uptime_output =
       log_path.Append(base::FilePath(kUptimePrefix + name));
diff --git a/chrome/browser/chromeos/boot_times_recorder.h b/chrome/browser/chromeos/boot_times_recorder.h
index 0d633a11..3db8d67 100644
--- a/chrome/browser/chromeos/boot_times_recorder.h
+++ b/chrome/browser/chromeos/boot_times_recorder.h
@@ -130,8 +130,8 @@
                                  const base::Closure& callback) const;
 
    private:
-    // Runs on BlockingPool
-    void RecordStatsImpl(const std::string& name) const;
+    // Runs asynchronously when RecordStats(WithCallback) is called.
+    void RecordStatsAsync(const std::string& name) const;
 
     std::string uptime_;
     std::string disk_;
diff --git a/chrome/browser/chromeos/extensions/PRESUBMIT.py b/chrome/browser/chromeos/extensions/PRESUBMIT.py
deleted file mode 100644
index 627f282..0000000
--- a/chrome/browser/chromeos/extensions/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2014 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.
-
-"""Presubmit script for extensions and apps.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
index 05459124..472707f 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
@@ -131,6 +131,11 @@
     // Special-cased in IsSafeForPublicSession().
     // emk::kApp,
 
+    // Not a real manifest entry (doesn't show up in code search). All legacy
+    // ARC apps have this dictionary (data is stuffed there to be consumed by
+    // the ARC runtime).
+    "arc_metadata",
+
     // Documented in https://developer.chrome.com/extensions/manifest but not
     // implemented anywhere.  Still, a lot of apps use it.
     "author",
@@ -683,8 +688,8 @@
 // Some permissions take the form of a dictionary.  See |kSafePermissionStrings|
 // for permission strings (and for more documentation).
 const char* const kSafePermissionDicts[] = {
-    // TBD
-    // "fileSystem",
+    // Dictionary form of the above "fileSystem" permission string.
+    "fileSystem",
 
     // Just another type of connectivity.
     "socket",
diff --git a/chrome/browser/chromeos/hats/hats_notification_controller.cc b/chrome/browser/chromeos/hats/hats_notification_controller.cc
index 2d952f0..84f1ef7 100644
--- a/chrome/browser/chromeos/hats/hats_notification_controller.cc
+++ b/chrome/browser/chromeos/hats/hats_notification_controller.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/hats/hats_dialog.h"
 #include "chrome/browser/chromeos/hats/hats_finch_helper.h"
@@ -25,7 +26,6 @@
 #include "chromeos/network/network_state.h"
 #include "components/image_fetcher/image_fetcher_impl.h"
 #include "components/prefs/pref_service.h"
-#include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image_skia_rep.h"
@@ -113,8 +113,9 @@
     : profile_(profile),
       image_fetcher_(image_fetcher),
       weak_pointer_factory_(this) {
-  base::PostTaskAndReplyWithResult(
-      content::BrowserThread::GetBlockingPool(), FROM_HERE,
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                     base::TaskPriority::BACKGROUND),
       base::Bind(&IsNewDevice, kHatsNewDeviceThresholdDays),
       base::Bind(&HatsNotificationController::Initialize,
                  weak_pointer_factory_.GetWeakPtr()));
diff --git a/chrome/browser/chromeos/policy/android_management_client_unittest.cc b/chrome/browser/chromeos/policy/android_management_client_unittest.cc
index cfe3843..2d89611 100644
--- a/chrome/browser/chromeos/policy/android_management_client_unittest.cc
+++ b/chrome/browser/chromeos/policy/android_management_client_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/test/mock_callback.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/policy/android_management_client.h"
 #include "components/policy/core/common/cloud/mock_device_management_service.h"
@@ -37,14 +38,6 @@
   return arg.SerializePartialAsString() == expected.SerializePartialAsString();
 }
 
-// A mock class to allow us to set expectations on upload callbacks.
-class MockStatusCallbackObserver {
- public:
-  MockStatusCallbackObserver() {}
-
-  MOCK_METHOD1(OnCallbackComplete, void(AndroidManagementClient::Result));
-};
-
 }  // namespace
 
 class AndroidManagementClientTest : public testing::Test {
@@ -70,7 +63,8 @@
 
   base::MessageLoop loop_;
   MockDeviceManagementService service_;
-  StrictMock<MockStatusCallbackObserver> callback_observer_;
+  StrictMock<base::MockCallback<AndroidManagementClient::StatusCallback>>
+      callback_observer_;
   std::unique_ptr<AndroidManagementClient> client_;
   // Pointer to the client's request context.
   scoped_refptr<net::URLRequestContextGetter> request_context_;
@@ -91,15 +85,11 @@
                        MatchProto(android_management_request_)))
       .WillOnce(SaveArg<4>(&client_id));
   EXPECT_CALL(callback_observer_,
-              OnCallbackComplete(AndroidManagementClient::Result::UNMANAGED))
+              Run(AndroidManagementClient::Result::UNMANAGED))
       .Times(1);
 
-  AndroidManagementClient::StatusCallback callback =
-      base::Bind(&MockStatusCallbackObserver::OnCallbackComplete,
-                 base::Unretained(&callback_observer_));
-
   token_service_.UpdateCredentials(kAccountId, kRefreshToken);
-  client_->StartCheckAndroidManagement(callback);
+  client_->StartCheckAndroidManagement(callback_observer_.Get());
   token_service_.IssueAllTokensForAccount(kAccountId, kOAuthToken,
                                           base::Time::Max());
   ASSERT_LT(client_id.size(), 64U);
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_browsertest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_browsertest.cc
index 481ba2fb..8e8c696 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_browsertest.cc
@@ -86,18 +86,19 @@
 class SigninExtensionsDeviceCloudPolicyBrowserTestBase
     : public DevicePolicyCrosBrowserTest {
  protected:
-  constexpr static const char* kTestExtensionId =
+  static constexpr const char* kTestExtensionId =
       "baogpbmpccplckhhehfipokjaflkmbno";
-  constexpr static const char* kTestExtensionSourceDir =
+  static constexpr const char* kTestExtensionSourceDir =
       "extensions/signin_screen_managed_storage";
-  constexpr static const char* kTestExtensionVersion = "1.0";
-  constexpr static const char* kTestExtensionTestPage = "test.html";
-  constexpr static const char* kFakePolicyUrl =
+  static constexpr const char* kTestExtensionVersion = "1.0";
+  static constexpr const char* kTestExtensionTestPage = "test.html";
+  static constexpr const char* kFakePolicyUrl =
       "http://example.org/test-policy.json";
-  constexpr static const char* kFakePolicy =
+  static constexpr const char* kFakePolicy =
       "{\"string-policy\": {\"Value\": \"value\"}}";
-  constexpr static const char* kPolicyProtoCacheKey = "signinextension-policy";
-  constexpr static const char* kPolicyDataCacheKey =
+  static constexpr int kFakePolicyPublicKeyVersion = 1;
+  static constexpr const char* kPolicyProtoCacheKey = "signinextension-policy";
+  static constexpr const char* kPolicyDataCacheKey =
       "signinextension-policy-data";
 
   SigninExtensionsDeviceCloudPolicyBrowserTestBase() {}
@@ -155,13 +156,14 @@
     return extension;
   }
 
-  enterprise_management::PolicyFetchResponse BuildTestComponentPolicy() {
+  static enterprise_management::PolicyFetchResponse BuildTestComponentPolicy() {
     ComponentPolicyBuilder builder;
     MakeTestComponentPolicyBuilder(&builder);
     return builder.policy();
   }
 
-  enterprise_management::ExternalPolicyData BuildTestComponentPolicyPayload() {
+  static enterprise_management::ExternalPolicyData
+  BuildTestComponentPolicyPayload() {
     ComponentPolicyBuilder builder;
     MakeTestComponentPolicyBuilder(&builder);
     return builder.payload();
@@ -170,21 +172,20 @@
  private:
   void SetFakeDevicePolicy() {
     device_policy()->policy_data().set_username(PolicyBuilder::kFakeUsername);
-    device_policy()->SetDefaultSigningKey();
+    device_policy()->policy_data().set_public_key_version(
+        kFakePolicyPublicKeyVersion);
     device_policy()->Build();
     session_manager_client()->set_device_policy(device_policy()->GetBlob());
   }
 
-  void MakeTestComponentPolicyBuilder(ComponentPolicyBuilder* builder) {
+  static void MakeTestComponentPolicyBuilder(ComponentPolicyBuilder* builder) {
     builder->policy_data().set_policy_type(
         dm_protocol::kChromeSigninExtensionPolicyType);
-    builder->policy_data().set_username(
-        device_policy()->policy_data().username());
+    builder->policy_data().set_username(PolicyBuilder::kFakeUsername);
     builder->policy_data().set_settings_entity_id(kTestExtensionId);
-    builder->policy_data().set_public_key_version(1);
+    builder->policy_data().set_public_key_version(kFakePolicyPublicKeyVersion);
     builder->payload().set_download_url(kFakePolicyUrl);
     builder->payload().set_secure_hash(crypto::SHA256HashString(kFakePolicy));
-    builder->SetDefaultSigningKey();
     builder->Build();
   }
 
@@ -278,10 +279,8 @@
   std::unique_ptr<base::AutoReset<bool>> signin_policy_provided_disabler_;
 };
 
-// DISABLED: see crbug.com/666720, crbug.com/644304. TODO(emaxx): Enable the
-// test back.
 IN_PROC_BROWSER_TEST_F(SigninExtensionsDeviceCloudPolicyBrowserTest,
-                       DISABLED_InstallAndRunInWindow) {
+                       InstallAndRunInWindow) {
   const extensions::Extension* extension = InstallAndLoadTestExtension();
   ASSERT_TRUE(extension);
   Browser* browser = CreateBrowser(GetSigninProfile());
@@ -300,11 +299,9 @@
 class PreinstalledSigninExtensionsDeviceCloudPolicyBrowserTest
     : public SigninExtensionsDeviceCloudPolicyBrowserTestBase {
  protected:
-  constexpr static const char* kFakeProfileSourceDir =
+  static constexpr const char* kFakeProfileSourceDir =
       "extensions/profiles/signin_screen_managed_storage";
 
-  std::unique_ptr<base::AutoReset<bool>> signin_policy_provided_disabler_;
-
   bool SetUpUserDataDirectory() override {
     PrefillSigninProfile();
     PrefillComponentPolicyCache();
@@ -318,6 +315,7 @@
         chromeos::GetScopedSigninScreenPolicyProviderDisablerForTesting();
   }
 
+ private:
   static void PrefillSigninProfile() {
     base::FilePath profile_source_path;
     EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &profile_source_path));
@@ -354,12 +352,12 @@
     EXPECT_TRUE(
         cache.Store(kPolicyDataCacheKey, kTestExtensionId, kFakePolicy));
   }
+
+  std::unique_ptr<base::AutoReset<bool>> signin_policy_provided_disabler_;
 };
 
-// DISABLED: see crbug.com/666720, crbug.com/644304. TODO(emaxx): Enable the
-// test back.
 IN_PROC_BROWSER_TEST_F(PreinstalledSigninExtensionsDeviceCloudPolicyBrowserTest,
-                       DISABLED_OfflineStart) {
+                       OfflineStart) {
   const extensions::Extension* extension = GetTestExtension();
   ASSERT_TRUE(extension);
   Browser* browser = CreateBrowser(GetSigninProfile());
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
index d64288a..ad2336f8 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -243,7 +243,9 @@
   if (ForcedReEnrollmentEnabled())
     client_to_connect->SetStateKeysToUpload(state_keys_broker_->state_keys());
 
-  if (is_component_policy_enabled_) {
+  // Create the component cloud policy service for fetching, caching and
+  // exposing policy for extensions.
+  if (!component_policy_disabled_for_testing_) {
     base::FilePath component_policy_cache_dir;
     CHECK(PathService::Get(chromeos::DIR_SIGNIN_PROFILE_COMPONENT_POLICY,
                            &component_policy_cache_dir));
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
index 7a30322..6d3b351 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
@@ -123,11 +123,12 @@
   // associated with this schema registry.
   void SetSigninProfileSchemaRegistry(SchemaRegistry* schema_registry);
 
-  // Sets whether the component cloud policy service should be created.
-  // Defaults to true.
-  void set_is_component_policy_enabled_for_testing(
-      bool is_component_policy_enabled) {
-    is_component_policy_enabled_ = is_component_policy_enabled;
+  // Sets whether the component cloud policy should be disabled (by skipping
+  // the component cloud policy service creation).
+  void set_component_policy_disabled_for_testing(
+      bool component_policy_disabled_for_testing) {
+    component_policy_disabled_for_testing_ =
+        component_policy_disabled_for_testing;
   }
 
  private:
@@ -175,12 +176,9 @@
   std::unique_ptr<ForwardingSchemaRegistry>
       signin_profile_forwarding_schema_registry_;
 
-  // Whether the component cloud policy service should be created.
-  // TODO(emaxx): Change the default to true once both the client and the
-  // DMServer are ready for handling policy fetches with the
-  // google/chromeos/signinextension type. See crbug.com/666720,
-  // crbug.com/644304 for reference.
-  bool is_component_policy_enabled_ = false;
+  // Whether the component cloud policy should be disabled (by skipping the
+  // component cloud policy service creation).
+  bool component_policy_disabled_for_testing_ = false;
 
   base::ObserverList<Observer, true> observers_;
 
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
index f01ce0c27..342c610 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
@@ -101,7 +101,7 @@
       : DeviceCloudPolicyManagerChromeOS(std::move(store),
                                          task_runner,
                                          state_keys_broker) {
-    set_is_component_policy_enabled_for_testing(false);
+    set_component_policy_disabled_for_testing(true);
   }
 
   ~TestingDeviceCloudPolicyManagerChromeOS() override {}
diff --git a/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto b/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto
index 6c5a9b7..35bcf33 100644
--- a/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto
+++ b/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto
@@ -308,6 +308,12 @@
   // If package and action are specified, but not the class name, runtime may
   // use PackageManager.queryIntentActivity() to find out the class name.
   optional string action = 3;
+
+  // Display name (optional).
+  // User-friendly app name that should be used in Chrome UI where kiosk app
+  // name is shown. Chrome side could override the string with an updated
+  // value that it will get from Google Play when the app will be installed.
+  optional string display_name = 4;
 }
 
 // Describes a single device-local account.
diff --git a/chrome/browser/chromeos/power/cpu_data_collector.cc b/chrome/browser/chromeos/power/cpu_data_collector.cc
index f8867ab..dc4c0cc 100644
--- a/chrome/browser/chromeos/power/cpu_data_collector.cc
+++ b/chrome/browser/chromeos/power/cpu_data_collector.cc
@@ -16,6 +16,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_info.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/chromeos/power/power_data_collector.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -302,7 +303,7 @@
 // index i in |idle_samples| and |freq_samples| correspond to the idle and
 // freq samples of CPU i. This also function reads the number of CPUs from
 // sysfs if *|cpu_count| < 0.
-void SampleCpuStateOnBlockingPool(
+void SampleCpuStateAsync(
     int* cpu_count,
     std::vector<std::string>* cpu_idle_state_names,
     std::vector<CpuDataCollector::StateOccupancySample>* idle_samples,
@@ -351,7 +352,7 @@
 
 }  // namespace
 
-// Set |cpu_count_| to -1 and let SampleCpuStateOnBlockingPool discover the
+// Set |cpu_count_| to -1 and let SampleCpuStateAsync discover the
 // correct number of CPUs.
 CpuDataCollector::CpuDataCollector() : cpu_count_(-1), weak_ptr_factory_(this) {
 }
@@ -377,21 +378,18 @@
   std::vector<StateOccupancySample>* freq_samples =
       new std::vector<StateOccupancySample>;
 
-  content::BrowserThread::PostBlockingPoolTaskAndReply(
-      FROM_HERE,
-      base::Bind(&SampleCpuStateOnBlockingPool,
-                 base::Unretained(cpu_count),
+  base::PostTaskWithTraitsAndReply(
+      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                     base::TaskPriority::BACKGROUND),
+      base::Bind(&SampleCpuStateAsync, base::Unretained(cpu_count),
                  base::Unretained(cpu_idle_state_names),
                  base::Unretained(idle_samples),
                  base::Unretained(cpu_freq_state_names),
                  base::Unretained(freq_samples)),
       base::Bind(&CpuDataCollector::SaveCpuStateSamplesOnUIThread,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 base::Owned(cpu_count),
-                 base::Owned(cpu_idle_state_names),
-                 base::Owned(idle_samples),
-                 base::Owned(cpu_freq_state_names),
-                 base::Owned(freq_samples)));
+                 weak_ptr_factory_.GetWeakPtr(), base::Owned(cpu_count),
+                 base::Owned(cpu_idle_state_names), base::Owned(idle_samples),
+                 base::Owned(cpu_freq_state_names), base::Owned(freq_samples)));
 }
 
 void CpuDataCollector::SaveCpuStateSamplesOnUIThread(
diff --git a/chrome/browser/chromeos/power/cpu_data_collector.h b/chrome/browser/chromeos/power/cpu_data_collector.h
index 8693411..c9b4bcb 100644
--- a/chrome/browser/chromeos/power/cpu_data_collector.h
+++ b/chrome/browser/chromeos/power/cpu_data_collector.h
@@ -77,7 +77,7 @@
   void PostSampleCpuState();
 
   // This function commits the CPU count and samples read by
-  // SampleCpuStateOnBlockingPool to |cpu_idle_state_data_| and
+  // SampleCpuStateAsync to |cpu_idle_state_data_| and
   // |cpu_freq_state_data_|. Since UI is the consumer of CPU idle and freq data,
   // this function should run on the UI thread.
   void SaveCpuStateSamplesOnUIThread(
diff --git a/chrome/browser/chromeos/printing/DEPS b/chrome/browser/chromeos/printing/DEPS
new file mode 100644
index 0000000..84c882c
--- /dev/null
+++ b/chrome/browser/chromeos/printing/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+components/sync/base",
+  "+components/sync/model",
+  "+components/sync/protocol",
+]
diff --git a/chrome/browser/chromeos/printing/printer_pref_manager.cc b/chrome/browser/chromeos/printing/printer_pref_manager.cc
index 3e52bf1e..748fe569 100644
--- a/chrome/browser/chromeos/printing/printer_pref_manager.cc
+++ b/chrome/browser/chromeos/printing/printer_pref_manager.cc
@@ -13,61 +13,48 @@
 #include "base/json/json_reader.h"
 #include "base/md5.h"
 #include "base/memory/ptr_util.h"
+#include "base/optional.h"
 #include "base/values.h"
+#include "chrome/browser/chromeos/printing/printers_sync_bridge.h"
+#include "chrome/browser/chromeos/printing/specifics_translation.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/printing/printer_configuration.h"
 #include "chromeos/printing/printer_translator.h"
 #include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
 
 namespace chromeos {
 
 namespace {
 
-const base::ListValue* GetPrinterList(Profile* profile) {
-  return profile->GetPrefs()->GetList(prefs::kPrintingDevices);
-}
-
-// Returns the printer with the matching |id| from the list |values|.  The
-// returned value is mutable and |values| could be modified.
-base::DictionaryValue* FindPrinterPref(const base::ListValue* values,
-                                       const std::string& id) {
-  for (const auto& value : *values) {
-    base::DictionaryValue* printer_dictionary;
-    if (!value->GetAsDictionary(&printer_dictionary))
-      continue;
-
-    std::string printer_id;
-    if (printer_dictionary->GetString(printing::kPrinterId, &printer_id) &&
-        id == printer_id)
-      return printer_dictionary;
+// Adds |printer| with |id| to prefs.  Returns true if the printer is new,
+// false for an update.
+bool UpdatePrinterPref(PrintersSyncBridge* sync_bridge,
+                       const std::string& id,
+                       const Printer& printer) {
+  base::Optional<sync_pb::PrinterSpecifics> specifics =
+      sync_bridge->GetPrinter(id);
+  if (!specifics.has_value()) {
+    sync_bridge->AddPrinter(printing::PrinterToSpecifics(printer));
+    return true;
   }
 
-  return nullptr;
-}
+  // Preserve fields in the proto which we don't understand.
+  std::unique_ptr<sync_pb::PrinterSpecifics> updated_printer =
+      base::MakeUnique<sync_pb::PrinterSpecifics>(*specifics);
+  printing::MergePrinterToSpecifics(printer, updated_printer.get());
+  sync_bridge->AddPrinter(std::move(updated_printer));
 
-void UpdatePrinterPref(
-    Profile* profile,
-    const std::string& id,
-    std::unique_ptr<base::DictionaryValue> printer_dictionary) {
-  ListPrefUpdate update(profile->GetPrefs(), prefs::kPrintingDevices);
-  base::ListValue* printer_list = update.Get();
-  DCHECK(printer_list) << "Register the printer preference";
-  base::DictionaryValue* printer = FindPrinterPref(printer_list, id);
-  if (!printer) {
-    printer_list->Append(std::move(printer_dictionary));
-    return;
-  }
-
-  printer->MergeDictionary(printer_dictionary.get());
+  return false;
 }
 
 }  // anonymous namespace
 
-PrinterPrefManager::PrinterPrefManager(Profile* profile) : profile_(profile) {
+PrinterPrefManager::PrinterPrefManager(
+    Profile* profile,
+    std::unique_ptr<PrintersSyncBridge> sync_bridge)
+    : profile_(profile), sync_bridge_(std::move(sync_bridge)) {
   pref_change_registrar_.Init(profile->GetPrefs());
   pref_change_registrar_.Add(
       prefs::kRecommendedNativePrinters,
@@ -81,27 +68,18 @@
 // static
 void PrinterPrefManager::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-  // TODO(skau): Change to user_prefs::PrefRegistrySyncable::SYNCABLE_PREF) when
-  // sync is implemented.
   registry->RegisterListPref(prefs::kPrintingDevices,
-                             PrefRegistry::NO_REGISTRATION_FLAGS);
+                             user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
   registry->RegisterListPref(prefs::kRecommendedNativePrinters);
 }
 
 std::vector<std::unique_ptr<Printer>> PrinterPrefManager::GetPrinters() const {
   std::vector<std::unique_ptr<Printer>> printers;
 
-  const base::ListValue* values = GetPrinterList(profile_);
-  for (const auto& value : *values) {
-    const base::DictionaryValue* printer_dictionary = nullptr;
-    value->GetAsDictionary(&printer_dictionary);
-
-    DCHECK(printer_dictionary);
-
-    std::unique_ptr<Printer> printer =
-        printing::PrefToPrinter(*printer_dictionary);
-    if (printer)
-      printers.push_back(std::move(printer));
+  std::vector<sync_pb::PrinterSpecifics> values =
+      sync_bridge_->GetAllPrinters();
+  for (const auto& value : values) {
+    printers.push_back(printing::SpecificsToPrinter(value));
   }
 
   return printers;
@@ -133,30 +111,62 @@
   if (found != policy_printers.end())
     return printing::RecommendedPrinterToPrinter(*(found->second));
 
-  const base::ListValue* values = GetPrinterList(profile_);
-  const base::DictionaryValue* printer = FindPrinterPref(values, printer_id);
-
-  return printer ? printing::PrefToPrinter(*printer) : nullptr;
+  base::Optional<sync_pb::PrinterSpecifics> printer =
+      sync_bridge_->GetPrinter(printer_id);
+  return printer.has_value() ? printing::SpecificsToPrinter(*printer) : nullptr;
 }
 
 void PrinterPrefManager::RegisterPrinter(std::unique_ptr<Printer> printer) {
-  if (printer->id().empty())
+  if (printer->id().empty()) {
     printer->set_id(base::GenerateGUID());
+  }
 
   DCHECK_EQ(Printer::SRC_USER_PREFS, printer->source());
-  std::unique_ptr<base::DictionaryValue> updated_printer =
-      printing::PrinterToPref(*printer);
-  UpdatePrinterPref(profile_, printer->id(), std::move(updated_printer));
+  bool new_printer =
+      UpdatePrinterPref(sync_bridge_.get(), printer->id(), *printer);
+
+  if (new_printer) {
+    for (Observer& obs : observers_) {
+      obs.OnPrinterAdded(*printer);
+    }
+  } else {
+    for (Observer& obs : observers_) {
+      obs.OnPrinterUpdated(*printer);
+    }
+  }
 }
 
 bool PrinterPrefManager::RemovePrinter(const std::string& printer_id) {
   DCHECK(!printer_id.empty());
-  ListPrefUpdate update(profile_->GetPrefs(), prefs::kPrintingDevices);
-  base::ListValue* printer_list = update.Get();
-  DCHECK(printer_list) << "Printer preference not registered";
-  base::DictionaryValue* printer = FindPrinterPref(printer_list, printer_id);
 
-  return printer && printer_list->Remove(*printer, nullptr);
+  base::Optional<sync_pb::PrinterSpecifics> printer =
+      sync_bridge_->GetPrinter(printer_id);
+  bool success = false;
+  if (printer.has_value()) {
+    std::unique_ptr<Printer> p = printing::SpecificsToPrinter(*printer);
+    success = sync_bridge_->RemovePrinter(p->id());
+    if (success) {
+      for (Observer& obs : observers_) {
+        obs.OnPrinterRemoved(*p);
+      }
+    }
+  } else {
+    LOG(WARNING) << "Could not find printer" << printer_id;
+  }
+
+  return success;
+}
+
+void PrinterPrefManager::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void PrinterPrefManager::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+PrintersSyncBridge* PrinterPrefManager::GetSyncBridge() {
+  return sync_bridge_.get();
 }
 
 // This method is not thread safe and could interact poorly with readers of
diff --git a/chrome/browser/chromeos/printing/printer_pref_manager.h b/chrome/browser/chromeos/printing/printer_pref_manager.h
index 222de0d..867ac737 100644
--- a/chrome/browser/chromeos/printing/printer_pref_manager.h
+++ b/chrome/browser/chromeos/printing/printer_pref_manager.h
@@ -10,6 +10,9 @@
 #include <string>
 #include <vector>
 
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "chrome/browser/chromeos/printing/printers_sync_bridge.h"
 #include "chromeos/printing/printer_configuration.h"
 #include "chromeos/printing/printer_translator.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -25,7 +28,15 @@
 
 class PrinterPrefManager : public KeyedService {
  public:
-  explicit PrinterPrefManager(Profile* profile);
+  class Observer {
+   public:
+    virtual void OnPrinterAdded(const Printer& printer) = 0;
+    virtual void OnPrinterUpdated(const Printer& printer) = 0;
+    virtual void OnPrinterRemoved(const Printer& printer) = 0;
+  };
+
+  PrinterPrefManager(Profile* profile,
+                     std::unique_ptr<PrintersSyncBridge> sync_bridge);
   ~PrinterPrefManager() override;
 
   // Register the printing preferences with the |registry|.
@@ -48,6 +59,19 @@
   // the printer was successfully removed.
   bool RemovePrinter(const std::string& printer_id);
 
+  // Attach |observer| for notification of events.  |observer| is expected to
+  // live on the same thread (UI) as this object.  OnPrinter* methods are
+  // invoked inline so calling RegisterPrinter in response to OnPrinterAdded is
+  // forbidden.
+  void AddObserver(PrinterPrefManager::Observer* observer);
+
+  // Remove |observer| so that it no longer receives notifications.  After the
+  // completion of this method, the |observer| can be safely destroyed.
+  void RemoveObserver(PrinterPrefManager::Observer* observer);
+
+  // Returns a ModelTypeSyncBridge for the sync client.
+  PrintersSyncBridge* GetSyncBridge();
+
  private:
   // Updates the in-memory recommended printer list.
   void UpdateRecommendedPrinters();
@@ -55,11 +79,18 @@
   Profile* profile_;
   PrefChangeRegistrar pref_change_registrar_;
 
+  // The backend for profile printers.
+  std::unique_ptr<PrintersSyncBridge> sync_bridge_;
+
   // Contains the keys for all recommended printers in order so we can return
   // the list of recommended printers in the order they were received.
   std::vector<std::string> recommended_printer_ids_;
   std::map<std::string, std::unique_ptr<base::DictionaryValue>>
       recommended_printers_;
+
+  base::ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrinterPrefManager);
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/printer_pref_manager_factory.cc b/chrome/browser/chromeos/printing/printer_pref_manager_factory.cc
index 7baed0e..f8f0078 100644
--- a/chrome/browser/chromeos/printing/printer_pref_manager_factory.cc
+++ b/chrome/browser/chromeos/printing/printer_pref_manager_factory.cc
@@ -4,8 +4,16 @@
 
 #include "chrome/browser/chromeos/printing/printer_pref_manager_factory.h"
 
+#include <memory>
+#include <utility>
+
+#include "base/debug/dump_without_crashing.h"
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/chromeos/printing/printers_sync_bridge.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "components/browser_sync/profile_sync_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
@@ -45,7 +53,21 @@
 PrinterPrefManager* PrinterPrefManagerFactory::BuildServiceInstanceFor(
     content::BrowserContext* browser_context) const {
   Profile* profile = Profile::FromBrowserContext(browser_context);
-  return new PrinterPrefManager(profile);
+
+  browser_sync::ProfileSyncService* sync_service =
+      ProfileSyncServiceFactory::GetForProfile(profile);
+
+  // TODO(skau): --disable-sync and --enable-native-cups are mutually exclusive
+  // until crbug.com/688533 is resolved.
+  DCHECK(sync_service);
+
+  std::unique_ptr<PrintersSyncBridge> sync_bridge =
+      base::MakeUnique<PrintersSyncBridge>(
+          sync_service->GetModelTypeStoreFactory(syncer::PRINTERS),
+          base::BindRepeating(
+              base::IgnoreResult(&base::debug::DumpWithoutCrashing)));
+
+  return new PrinterPrefManager(profile, std::move(sync_bridge));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/printer_pref_manager_unittest.cc b/chrome/browser/chromeos/printing/printer_pref_manager_unittest.cc
index 11ec115..ea3bcad 100644
--- a/chrome/browser/chromeos/printing/printer_pref_manager_unittest.cc
+++ b/chrome/browser/chromeos/printing/printer_pref_manager_unittest.cc
@@ -7,10 +7,17 @@
 #include <memory>
 #include <utility>
 
+#include "base/bind.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
 #include "chrome/browser/chromeos/printing/printer_pref_manager_factory.h"
+#include "chrome/browser/chromeos/printing/printers_sync_bridge.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/sync/model/fake_model_type_change_processor.h"
+#include "components/sync/model/model_type_store.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -34,72 +41,138 @@
         },
       } )json";
 
+// Helper class to record observed events.
+class LoggingObserver : public PrinterPrefManager::Observer {
+ public:
+  void OnPrinterAdded(const Printer& printer) override {
+    last_added_ = printer;
+  }
+
+  void OnPrinterUpdated(const Printer& printer) override {
+    last_updated_ = printer;
+  }
+
+  void OnPrinterRemoved(const Printer& printer) override {
+    last_removed_ = printer;
+  }
+
+  // Returns true if OnPrinterAdded was called.
+  bool AddCalled() const { return last_added_.has_value(); }
+
+  // Returns true if OnPrinterUpdated was called.
+  bool UpdateCalled() const { return last_updated_.has_value(); }
+
+  // Returns true if OnPrinterRemoved was called.
+  bool RemoveCalled() const { return last_removed_.has_value(); }
+
+  // Returns the last printer that was added.  If AddCalled is false, there will
+  // be no printer.
+  base::Optional<Printer> LastAdded() const { return last_added_; }
+  // Returns the last printer that was updated.  If UpdateCalled is false, there
+  // will be no printer.
+  base::Optional<Printer> LastUpdated() const { return last_updated_; }
+  // Returns the last printer that was removed.  If RemoveCalled is false, there
+  // will be no printer.
+  base::Optional<Printer> LastRemoved() const { return last_removed_; }
+
+ private:
+  base::Optional<Printer> last_added_;
+  base::Optional<Printer> last_updated_;
+  base::Optional<Printer> last_removed_;
+};
+
 }  // namespace
 
-TEST(PrinterPrefManagerTest, AddPrinter) {
-  content::TestBrowserThreadBundle thread_bundle;
-  auto profile = base::MakeUnique<TestingProfile>();
-  PrinterPrefManager* manager =
-      PrinterPrefManagerFactory::GetForBrowserContext(profile.get());
+class PrinterPrefManagerTest : public testing::Test {
+ protected:
+  PrinterPrefManagerTest() : profile_(base::MakeUnique<TestingProfile>()) {
+    thread_bundle_ = base::MakeUnique<content::TestBrowserThreadBundle>();
 
-  manager->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
+    auto sync_bridge = base::MakeUnique<PrintersSyncBridge>(
+        base::Bind(&syncer::ModelTypeStore::CreateInMemoryStoreForTest,
+                   syncer::PRINTERS),
+        base::BindRepeating(
+            base::IgnoreResult(&base::debug::DumpWithoutCrashing)));
 
-  auto printers = manager->GetPrinters();
+    manager_ = base::MakeUnique<PrinterPrefManager>(profile_.get(),
+                                                    std::move(sync_bridge));
+
+    base::RunLoop().RunUntilIdle();
+  }
+
+  ~PrinterPrefManagerTest() override {
+    manager_.reset();
+
+    // Explicitly release the profile before the thread_bundle.  Otherwise, the
+    // profile destructor throws an error.
+    profile_.reset();
+    thread_bundle_.reset();
+  }
+
+  std::unique_ptr<TestingProfile> profile_;
+  std::unique_ptr<PrinterPrefManager> manager_;
+
+ private:
+  std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_;
+};
+
+TEST_F(PrinterPrefManagerTest, AddPrinter) {
+  LoggingObserver observer;
+  manager_->AddObserver(&observer);
+  manager_->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
+
+  auto printers = manager_->GetPrinters();
   ASSERT_EQ(1U, printers.size());
   EXPECT_EQ(kPrinterId, printers[0]->id());
   EXPECT_EQ(Printer::Source::SRC_USER_PREFS, printers[0]->source());
+
+  EXPECT_TRUE(observer.AddCalled());
+  EXPECT_FALSE(observer.UpdateCalled());
 }
 
-TEST(PrinterPrefManagerTest, UpdatePrinterAssignsId) {
-  content::TestBrowserThreadBundle thread_bundle;
-  auto profile = base::MakeUnique<TestingProfile>();
-  PrinterPrefManager* manager =
-      PrinterPrefManagerFactory::GetForBrowserContext(profile.get());
+TEST_F(PrinterPrefManagerTest, UpdatePrinterAssignsId) {
+  manager_->RegisterPrinter(base::MakeUnique<Printer>());
 
-  manager->RegisterPrinter(base::MakeUnique<Printer>());
-
-  auto printers = manager->GetPrinters();
+  auto printers = manager_->GetPrinters();
   ASSERT_EQ(1U, printers.size());
   EXPECT_FALSE(printers[0]->id().empty());
 }
 
-TEST(PrinterPrefManagerTest, UpdatePrinter) {
-  content::TestBrowserThreadBundle thread_bundle;
-  auto profile = base::MakeUnique<TestingProfile>();
-  PrinterPrefManager* manager =
-      PrinterPrefManagerFactory::GetForBrowserContext(profile.get());
-
-  manager->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
+TEST_F(PrinterPrefManagerTest, UpdatePrinter) {
+  manager_->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
   auto updated_printer = base::MakeUnique<Printer>(kPrinterId);
   updated_printer->set_uri(kUri);
-  manager->RegisterPrinter(std::move(updated_printer));
 
-  auto printers = manager->GetPrinters();
+  // Register observer so it only receives the update event.
+  LoggingObserver observer;
+  manager_->AddObserver(&observer);
+
+  manager_->RegisterPrinter(std::move(updated_printer));
+
+  auto printers = manager_->GetPrinters();
   ASSERT_EQ(1U, printers.size());
   EXPECT_EQ(kUri, printers[0]->uri());
+
+  EXPECT_TRUE(observer.UpdateCalled());
+  EXPECT_FALSE(observer.AddCalled());
 }
 
-TEST(PrinterPrefManagerTest, RemovePrinter) {
-  content::TestBrowserThreadBundle thread_bundle;
-  auto profile = base::MakeUnique<TestingProfile>();
-  PrinterPrefManager* manager =
-      PrinterPrefManagerFactory::GetForBrowserContext(profile.get());
+TEST_F(PrinterPrefManagerTest, RemovePrinter) {
+  manager_->RegisterPrinter(base::MakeUnique<Printer>("OtherUUID"));
+  manager_->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
+  manager_->RegisterPrinter(base::MakeUnique<Printer>());
 
-  manager->RegisterPrinter(base::MakeUnique<Printer>("OtherUUID"));
-  manager->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
-  manager->RegisterPrinter(base::MakeUnique<Printer>());
+  manager_->RemovePrinter(kPrinterId);
 
-  manager->RemovePrinter(kPrinterId);
-
-  auto printers = manager->GetPrinters();
+  auto printers = manager_->GetPrinters();
   ASSERT_EQ(2U, printers.size());
   EXPECT_NE(kPrinterId, printers.at(0)->id());
   EXPECT_NE(kPrinterId, printers.at(1)->id());
 }
 
-TEST(PrinterPrefManagerTest, RecommendedPrinters) {
-  content::TestBrowserThreadBundle thread_bundle;
+// Tests for policy printers
 
+TEST_F(PrinterPrefManagerTest, RecommendedPrinters) {
   std::string first_printer =
       R"json({
       "display_name": "Color Laser",
@@ -120,42 +193,32 @@
   value->AppendString(first_printer);
   value->AppendString(second_printer);
 
-  TestingProfile profile;
   sync_preferences::TestingPrefServiceSyncable* prefs =
-      profile.GetTestingPrefService();
+      profile_->GetTestingPrefService();
   // TestingPrefSyncableService assumes ownership of |value|.
   prefs->SetManagedPref(prefs::kRecommendedNativePrinters, value.release());
 
-  PrinterPrefManager* manager =
-      PrinterPrefManagerFactory::GetForBrowserContext(&profile);
-
-  auto printers = manager->GetRecommendedPrinters();
+  auto printers = manager_->GetRecommendedPrinters();
   ASSERT_EQ(2U, printers.size());
   EXPECT_EQ("Color Laser", printers[0]->display_name());
   EXPECT_EQ("ipp://192.168.1.5", printers[1]->uri());
   EXPECT_EQ(Printer::Source::SRC_POLICY, printers[1]->source());
 }
 
-TEST(PrinterPrefManagerTest, GetRecommendedPrinter) {
-  content::TestBrowserThreadBundle thread_bundle;
-
+TEST_F(PrinterPrefManagerTest, GetRecommendedPrinter) {
   std::string printer = kLexJson;
   auto value = base::MakeUnique<base::ListValue>();
   value->AppendString(printer);
 
-  TestingProfile profile;
   sync_preferences::TestingPrefServiceSyncable* prefs =
-      profile.GetTestingPrefService();
+      profile_->GetTestingPrefService();
   // TestingPrefSyncableService assumes ownership of |value|.
   prefs->SetManagedPref(prefs::kRecommendedNativePrinters, value.release());
 
-  PrinterPrefManager* manager =
-      PrinterPrefManagerFactory::GetForBrowserContext(&profile);
-
-  auto printers = manager->GetRecommendedPrinters();
+  auto printers = manager_->GetRecommendedPrinters();
 
   const Printer& from_list = *(printers.front());
-  std::unique_ptr<Printer> retrieved = manager->GetPrinter(from_list.id());
+  std::unique_ptr<Printer> retrieved = manager_->GetPrinter(from_list.id());
 
   EXPECT_EQ(from_list.id(), retrieved->id());
   EXPECT_EQ("LexaPrint", from_list.display_name());
diff --git a/chrome/browser/chromeos/printing/printers_sync_bridge.cc b/chrome/browser/chromeos/printing/printers_sync_bridge.cc
new file mode 100644
index 0000000..3fc5cc2
--- /dev/null
+++ b/chrome/browser/chromeos/printing/printers_sync_bridge.cc
@@ -0,0 +1,358 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/printing/printers_sync_bridge.h"
+
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "base/stl_util.h"
+#include "components/sync/base/report_unrecoverable_error.h"
+#include "components/sync/model/model_type_change_processor.h"
+#include "components/sync/model/model_type_store.h"
+#include "components/sync/model/mutable_data_batch.h"
+#include "components/sync/protocol/model_type_state.pb.h"
+#include "components/sync/protocol/sync.pb.h"
+
+namespace chromeos {
+
+namespace {
+
+using Result = syncer::ModelTypeStore::Result;
+
+using syncer::ConflictResolution;
+using syncer::EntityChange;
+using syncer::EntityChangeList;
+using syncer::EntityData;
+using syncer::ModelTypeChangeProcessor;
+using syncer::ModelTypeStore;
+using syncer::MetadataChangeList;
+
+std::unique_ptr<EntityData> CopyToEntityData(
+    const sync_pb::PrinterSpecifics& specifics) {
+  auto entity_data = base::MakeUnique<EntityData>();
+  *entity_data->specifics.mutable_printer() = specifics;
+  entity_data->non_unique_name =
+      specifics.display_name().empty() ? "PRINTER" : specifics.display_name();
+  return entity_data;
+}
+
+// Store |specifics| locally in |data| and record change in |batch|.
+void StoreSpecifics(
+    std::unique_ptr<sync_pb::PrinterSpecifics> specifics,
+    std::map<std::string, std::unique_ptr<sync_pb::PrinterSpecifics>>* data,
+    ModelTypeStore::WriteBatch* batch) {
+  const std::string id = specifics->id();
+  batch->WriteData(id, specifics->SerializeAsString());
+  (*data)[id] = std::move(specifics);
+}
+
+// Remove the specific with |id| from |data| and update |batch| with the change.
+bool DeleteSpecifics(
+    const std::string& id,
+    std::map<std::string, std::unique_ptr<sync_pb::PrinterSpecifics>>* data,
+    ModelTypeStore::WriteBatch* batch) {
+  auto iter = data->find(id);
+  if (iter != data->end()) {
+    batch->DeleteData(id);
+    data->erase(iter);
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace
+
+// Delegate class which helps to manage the ModelTypeStore.
+class PrintersSyncBridge::StoreProxy {
+ public:
+  StoreProxy(PrintersSyncBridge* owner,
+             const syncer::ModelTypeStoreFactory& callback)
+      : owner_(owner), weak_ptr_factory_(this) {
+    callback.Run(base::Bind(&StoreProxy::OnStoreCreated,
+                            weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  // Returns true if the store has been initialized.
+  bool Ready() { return store_.get() != nullptr; }
+
+  // Returns a new WriteBatch.
+  std::unique_ptr<ModelTypeStore::WriteBatch> CreateWriteBatch() {
+    CHECK(store_);
+    return store_->CreateWriteBatch();
+  }
+
+  // Commits writes to the database and updates metadata.
+  void Commit(std::unique_ptr<ModelTypeStore::WriteBatch> batch) {
+    CHECK(store_);
+    store_->CommitWriteBatch(
+        std::move(batch),
+        base::Bind(&StoreProxy::OnCommit, weak_ptr_factory_.GetWeakPtr()));
+  }
+
+ private:
+  // Callback for ModelTypeStore initialization.
+  void OnStoreCreated(Result result, std::unique_ptr<ModelTypeStore> store) {
+    if (result == Result::SUCCESS) {
+      store_ = std::move(store);
+      store_->ReadAllData(base::Bind(&StoreProxy::OnReadAllData,
+                                     weak_ptr_factory_.GetWeakPtr()));
+    } else {
+      owner_->change_processor()->ReportError(
+          FROM_HERE, "ModelTypeStore creation failed.");
+    }
+  }
+
+  void OnReadAllData(Result result,
+                     std::unique_ptr<ModelTypeStore::RecordList> record_list) {
+    if (result != Result::SUCCESS) {
+      owner_->change_processor()->ReportError(FROM_HERE,
+                                              "Initial load of data failed");
+      return;
+    }
+
+    bool error = false;
+    for (const ModelTypeStore::Record& r : *record_list) {
+      auto specifics = base::MakeUnique<sync_pb::PrinterSpecifics>();
+      if (specifics->ParseFromString(r.value)) {
+        owner_->all_data_[specifics->id()] = std::move(specifics);
+      } else {
+        error = true;
+      }
+    }
+
+    if (error) {
+      owner_->change_processor()->ReportError(
+          FROM_HERE, "Failed to deserialize all specifics.");
+      return;
+    }
+
+    // Data loaded.  Load metadata.
+    store_->ReadAllMetadata(base::Bind(&StoreProxy::OnReadAllMetadata,
+                                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  // Callback to handle commit errors.
+  void OnCommit(ModelTypeStore::Result result) {
+    if (result != Result::SUCCESS) {
+      LOG(WARNING) << "Failed to commit operation to store";
+      owner_->change_processor()->ReportError(FROM_HERE,
+                                              "Failed to commit to store");
+    }
+  }
+
+  void OnReadAllMetadata(
+      base::Optional<syncer::ModelError> error,
+      std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
+    if (error) {
+      owner_->change_processor()->ReportError(error.value());
+      return;
+    }
+
+    owner_->change_processor()->ModelReadyToSync(std::move(metadata_batch));
+  }
+
+  PrintersSyncBridge* owner_;
+
+  std::unique_ptr<ModelTypeStore> store_;
+  base::WeakPtrFactory<StoreProxy> weak_ptr_factory_;
+};
+
+PrintersSyncBridge::PrintersSyncBridge(
+    const syncer::ModelTypeStoreFactory& callback,
+    const base::RepeatingClosure& error_callback)
+    : ModelTypeSyncBridge(base::BindRepeating(&ModelTypeChangeProcessor::Create,
+                                              error_callback),
+                          syncer::PRINTERS),
+      store_delegate_(base::MakeUnique<StoreProxy>(this, callback)) {}
+
+PrintersSyncBridge::~PrintersSyncBridge() {}
+
+std::unique_ptr<MetadataChangeList>
+PrintersSyncBridge::CreateMetadataChangeList() {
+  return ModelTypeStore::WriteBatch::CreateMetadataChangeList();
+}
+
+base::Optional<syncer::ModelError> PrintersSyncBridge::MergeSyncData(
+    std::unique_ptr<MetadataChangeList> metadata_change_list,
+    syncer::EntityDataMap entity_data_map) {
+  DCHECK(change_processor()->IsTrackingMetadata());
+
+  std::unique_ptr<ModelTypeStore::WriteBatch> batch =
+      store_delegate_->CreateWriteBatch();
+  for (const auto& entry : entity_data_map) {
+    const sync_pb::PrinterSpecifics& specifics =
+        entry.second.value().specifics.printer();
+
+    DCHECK_EQ(entry.first, specifics.id());
+
+    // Write the update to local storage even if we already have it.
+    StoreSpecifics(base::MakeUnique<sync_pb::PrinterSpecifics>(specifics),
+                   &all_data_, batch.get());
+  }
+
+  // Inform the change processor of the new local entities and generate
+  // appropriate metadata.
+  for (const auto& entry : all_data_) {
+    const std::string& local_entity_id = entry.first;
+    if (!base::ContainsKey(entity_data_map, local_entity_id)) {
+      // Only local objects which were not updated are uploaded.  Objects for
+      // which there was a remote copy are overwritten.
+      change_processor()->Put(local_entity_id, CopyToEntityData(*entry.second),
+                              metadata_change_list.get());
+    }
+  }
+
+  batch->TransferMetadataChanges(std::move(metadata_change_list));
+  store_delegate_->Commit(std::move(batch));
+  return {};
+}
+
+base::Optional<syncer::ModelError> PrintersSyncBridge::ApplySyncChanges(
+    std::unique_ptr<MetadataChangeList> metadata_change_list,
+    EntityChangeList entity_changes) {
+  std::unique_ptr<ModelTypeStore::WriteBatch> batch =
+      store_delegate_->CreateWriteBatch();
+  // For all the entities from the server, apply changes.
+  for (const EntityChange& change : entity_changes) {
+    // We register the entity's storage key as our printer ids since they're
+    // globally unique.
+    const std::string& id = change.storage_key();
+    if (change.type() == EntityChange::ACTION_DELETE) {
+      // Server says delete, try to remove locally.
+      DeleteSpecifics(id, &all_data_, batch.get());
+    } else {
+      // Server says update, overwrite whatever is local.  Conflict resolution
+      // guarantees that this will be the newest version of the object.
+      const sync_pb::PrinterSpecifics& specifics =
+          change.data().specifics.printer();
+      DCHECK_EQ(id, specifics.id());
+      StoreSpecifics(base::MakeUnique<sync_pb::PrinterSpecifics>(specifics),
+                     &all_data_, batch.get());
+    }
+  }
+
+  // Update the local database with metadata for the incoming changes.
+  batch->TransferMetadataChanges(std::move(metadata_change_list));
+
+  store_delegate_->Commit(std::move(batch));
+  return {};
+}
+
+void PrintersSyncBridge::GetData(StorageKeyList storage_keys,
+                                 DataCallback callback) {
+  auto batch = base::MakeUnique<syncer::MutableDataBatch>();
+  for (const auto& key : storage_keys) {
+    auto found = all_data_.find(key);
+    if (found != all_data_.end()) {
+      batch->Put(key, CopyToEntityData(*found->second));
+    }
+  }
+
+  callback.Run(std::move(batch));
+}
+
+void PrintersSyncBridge::GetAllData(DataCallback callback) {
+  auto batch = base::MakeUnique<syncer::MutableDataBatch>();
+  for (const auto& entry : all_data_) {
+    batch->Put(entry.first, CopyToEntityData(*entry.second));
+  }
+
+  callback.Run(std::move(batch));
+}
+
+std::string PrintersSyncBridge::GetClientTag(const EntityData& entity_data) {
+  // Printers were never synced prior to USS so this can match GetStorageKey.
+  return GetStorageKey(entity_data);
+}
+
+std::string PrintersSyncBridge::GetStorageKey(const EntityData& entity_data) {
+  DCHECK(entity_data.specifics.has_printer());
+  return entity_data.specifics.printer().id();
+}
+
+// Picks the entity with the most recent updated time as the canonical version.
+ConflictResolution PrintersSyncBridge::ResolveConflict(
+    const EntityData& local_data,
+    const EntityData& remote_data) const {
+  DCHECK(local_data.specifics.has_printer());
+  DCHECK(remote_data.specifics.has_printer());
+
+  const sync_pb::PrinterSpecifics& local_printer =
+      local_data.specifics.printer();
+  const sync_pb::PrinterSpecifics& remote_printer =
+      remote_data.specifics.printer();
+
+  if (local_printer.updated_timestamp() > remote_printer.updated_timestamp()) {
+    return ConflictResolution::UseLocal();
+  }
+
+  return ConflictResolution::UseRemote();
+}
+
+void PrintersSyncBridge::AddPrinter(
+    std::unique_ptr<sync_pb::PrinterSpecifics> printer) {
+  printer->set_updated_timestamp(base::Time::Now().ToJavaTime());
+
+  std::unique_ptr<ModelTypeStore::WriteBatch> batch =
+      store_delegate_->CreateWriteBatch();
+  if (change_processor()->IsTrackingMetadata()) {
+    change_processor()->Put(printer->id(), CopyToEntityData(*printer),
+                            batch->GetMetadataChangeList());
+  }
+
+  StoreSpecifics(std::move(printer), &all_data_, batch.get());
+  store_delegate_->Commit(std::move(batch));
+}
+
+bool PrintersSyncBridge::RemovePrinter(const std::string& id) {
+  DCHECK(store_delegate_->Ready());
+
+  // Remove from local cache.
+  if (all_data_.erase(id) == 0) {
+    LOG(WARNING) << "Could not find printer" << id;
+    return false;
+  }
+
+  std::unique_ptr<ModelTypeStore::WriteBatch> batch =
+      store_delegate_->CreateWriteBatch();
+  if (change_processor()->IsTrackingMetadata()) {
+    change_processor()->Delete(id, batch->GetMetadataChangeList());
+  }
+
+  // Remove from sync'd data.
+  batch->DeleteData(id);
+  store_delegate_->Commit(std::move(batch));
+
+  return true;
+}
+
+std::vector<sync_pb::PrinterSpecifics> PrintersSyncBridge::GetAllPrinters()
+    const {
+  std::vector<sync_pb::PrinterSpecifics> printers;
+  for (auto& entry : all_data_) {
+    printers.push_back(*entry.second);
+  }
+
+  return printers;
+}
+
+base::Optional<sync_pb::PrinterSpecifics> PrintersSyncBridge::GetPrinter(
+    const std::string& id) const {
+  auto iter = all_data_.find(id);
+  if (iter == all_data_.end()) {
+    return {};
+  }
+
+  return {*iter->second};
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/printers_sync_bridge.h b/chrome/browser/chromeos/printing/printers_sync_bridge.h
new file mode 100644
index 0000000..971b86c0
--- /dev/null
+++ b/chrome/browser/chromeos/printing/printers_sync_bridge.h
@@ -0,0 +1,73 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_PRINTERS_SYNC_BRIDGE_H_
+#define CHROME_BROWSER_CHROMEOS_PRINTING_PRINTERS_SYNC_BRIDGE_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "base/sequenced_task_runner.h"
+#include "components/sync/model/conflict_resolution.h"
+#include "components/sync/model/model_type_store.h"
+#include "components/sync/model/model_type_sync_bridge.h"
+
+namespace sync_pb {
+class PrinterSpecifics;
+}
+
+namespace chromeos {
+
+// Moderates interaction with the backing database and integrates with the User
+// Sync Service for printers.
+class PrintersSyncBridge : public syncer::ModelTypeSyncBridge {
+ public:
+  PrintersSyncBridge(const syncer::ModelTypeStoreFactory& callback,
+                     const base::RepeatingClosure& error_callback);
+  ~PrintersSyncBridge() override;
+
+  // ModelTypeSyncBridge implementation.
+  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+      override;
+  base::Optional<syncer::ModelError> MergeSyncData(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityDataMap entity_data_map) override;
+  base::Optional<syncer::ModelError> ApplySyncChanges(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_changes) override;
+  void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+  void GetAllData(DataCallback callback) override;
+  std::string GetClientTag(const syncer::EntityData& entity_data) override;
+  std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+  syncer::ConflictResolution ResolveConflict(
+      const syncer::EntityData& local_data,
+      const syncer::EntityData& remote_data) const override;
+
+  // Store a new or updated |printer|.
+  void AddPrinter(std::unique_ptr<sync_pb::PrinterSpecifics> printer);
+  // Remove a printer by |id|.
+  bool RemovePrinter(const std::string& id);
+  // Returns all printers stored in the database and synced.
+  std::vector<sync_pb::PrinterSpecifics> GetAllPrinters() const;
+  // Returns the printer with |id| from storage if it could be found.
+  base::Optional<sync_pb::PrinterSpecifics> GetPrinter(
+      const std::string& id) const;
+
+ private:
+  class StoreProxy;
+
+  std::unique_ptr<StoreProxy> store_delegate_;
+
+  // In memory cache of printer information.
+  std::map<std::string, std::unique_ptr<sync_pb::PrinterSpecifics>> all_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrintersSyncBridge);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_PRINTING_PRINTERS_SYNC_BRIDGE_H_
diff --git a/chrome/browser/chromeos/printing/specifics_translation.cc b/chrome/browser/chromeos/printing/specifics_translation.cc
index 78503a1..2a59b419 100644
--- a/chrome/browser/chromeos/printing/specifics_translation.cc
+++ b/chrome/browser/chromeos/printing/specifics_translation.cc
@@ -31,18 +31,15 @@
   return ref;
 }
 
-sync_pb::PrinterPPDReference ReferenceToSpecifics(
-    const Printer::PpdReference& ref) {
-  sync_pb::PrinterPPDReference specifics;
+void MergeReferenceToSpecifics(sync_pb::PrinterPPDReference* specifics,
+                               const Printer::PpdReference& ref) {
   if (!ref.user_supplied_ppd_url.empty()) {
-    specifics.set_user_supplied_ppd_url(ref.user_supplied_ppd_url);
+    specifics->set_user_supplied_ppd_url(ref.user_supplied_ppd_url);
   }
 
   if (!ref.effective_make_and_model.empty()) {
-    specifics.set_effective_make_and_model(ref.effective_make_and_model);
+    specifics->set_effective_make_and_model(ref.effective_make_and_model);
   }
-
-  return specifics;
 }
 
 }  // namespace
@@ -70,6 +67,14 @@
 
   auto specifics = base::MakeUnique<sync_pb::PrinterSpecifics>();
   specifics->set_id(printer.id());
+  MergePrinterToSpecifics(printer, specifics.get());
+  return specifics;
+}
+
+void MergePrinterToSpecifics(const Printer& printer,
+                             sync_pb::PrinterSpecifics* specifics) {
+  // Never update id it needs to be stable.
+  DCHECK_EQ(printer.id(), specifics->id());
 
   if (!printer.display_name().empty())
     specifics->set_display_name(printer.display_name());
@@ -89,10 +94,8 @@
   if (!printer.uuid().empty())
     specifics->set_uuid(printer.uuid());
 
-  *specifics->mutable_ppd_reference() =
-      ReferenceToSpecifics(printer.ppd_reference());
-
-  return specifics;
+  MergeReferenceToSpecifics(specifics->mutable_ppd_reference(),
+                            printer.ppd_reference());
 }
 
 }  // namespace printing
diff --git a/chrome/browser/chromeos/printing/specifics_translation.h b/chrome/browser/chromeos/printing/specifics_translation.h
index fa84491..382f766c 100644
--- a/chrome/browser/chromeos/printing/specifics_translation.h
+++ b/chrome/browser/chromeos/printing/specifics_translation.h
@@ -19,6 +19,10 @@
 std::unique_ptr<sync_pb::PrinterSpecifics> PrinterToSpecifics(
     const Printer& printer);
 
+// Merge fields from |printer| into |specifics|.
+void MergePrinterToSpecifics(const Printer& printer,
+                             sync_pb::PrinterSpecifics* specifics);
+
 }  // namespace printing
 }  // namespace chromeos
 
diff --git a/chrome/browser/component_updater/component_updater_prefs.cc b/chrome/browser/component_updater/component_updater_prefs.cc
index 5fb4eb5..7a6604e 100644
--- a/chrome/browser/component_updater/component_updater_prefs.cc
+++ b/chrome/browser/component_updater/component_updater_prefs.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/component_updater/chrome_component_updater_configurator.h"
 #include "chrome/browser/component_updater/recovery_component_installer.h"
+#include "chrome/browser/component_updater/recovery_improved_component_installer.h"
 #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h"
 
 namespace component_updater {
@@ -13,6 +14,7 @@
 void RegisterPrefs(PrefRegistrySimple* registry) {
   RegisterPrefsForChromeComponentUpdaterConfigurator(registry);
   RegisterPrefsForRecoveryComponent(registry);
+  RegisterPrefsForRecoveryImprovedComponent(registry);
   SupervisedUserWhitelistInstaller::RegisterPrefs(registry);
 }
 
diff --git a/chrome/browser/component_updater/recovery_improved_component_installer.cc b/chrome/browser/component_updater/recovery_improved_component_installer.cc
new file mode 100644
index 0000000..5ec1ff8
--- /dev/null
+++ b/chrome/browser/component_updater/recovery_improved_component_installer.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/recovery_improved_component_installer.h"
+
+#include <iterator>
+#include <utility>
+
+#include "base/callback.h"
+
+namespace component_updater {
+
+// The SHA256 of the SubjectPublicKeyInfo used to sign the component CRX.
+// The extension id is: iddcipcljjhfegcfaaaapdilddpplalp
+constexpr uint8_t kPublicKeySHA256[32] = {
+    0x97, 0xf0, 0xbe, 0xe4, 0x3f, 0x2b, 0x9e, 0xcf, 0x2c, 0x50, 0x61,
+    0xdf, 0xc2, 0x6e, 0x0b, 0x4a, 0x4f, 0x1e, 0xda, 0x71, 0x29, 0x64,
+    0x74, 0x70, 0x15, 0x07, 0x18, 0xb7, 0x92, 0x04, 0xcd, 0x70};
+
+constexpr char kRecoveryImprovedManifestName[] = "Chrome Improved Recovery";
+
+RecoveryImprovedInstallerTraits::RecoveryImprovedInstallerTraits(
+    PrefService* prefs)
+    : prefs_(prefs) {}
+
+RecoveryImprovedInstallerTraits::~RecoveryImprovedInstallerTraits() {}
+
+bool RecoveryImprovedInstallerTraits::
+    SupportsGroupPolicyEnabledComponentUpdates() const {
+  return true;
+}
+
+bool RecoveryImprovedInstallerTraits::RequiresNetworkEncryption() const {
+  return false;
+}
+
+update_client::CrxInstaller::Result
+RecoveryImprovedInstallerTraits::OnCustomInstall(
+    const base::DictionaryValue& manifest,
+    const base::FilePath& install_dir) {
+  return update_client::CrxInstaller::Result(0);
+}
+
+void RecoveryImprovedInstallerTraits::ComponentReady(
+    const base::Version& version,
+    const base::FilePath& install_dir,
+    std::unique_ptr<base::DictionaryValue> manifest) {}
+
+// Called during startup and installation before ComponentReady().
+bool RecoveryImprovedInstallerTraits::VerifyInstallation(
+    const base::DictionaryValue& manifest,
+    const base::FilePath& install_dir) const {
+  return true;
+}
+
+base::FilePath RecoveryImprovedInstallerTraits::GetRelativeInstallDir() const {
+  return base::FilePath(FILE_PATH_LITERAL("RecoveryImproved"));
+}
+
+void RecoveryImprovedInstallerTraits::GetHash(
+    std::vector<uint8_t>* hash) const {
+  hash->assign(std::begin(kPublicKeySHA256), std::end(kPublicKeySHA256));
+}
+
+std::string RecoveryImprovedInstallerTraits::GetName() const {
+  return kRecoveryImprovedManifestName;
+}
+
+update_client::InstallerAttributes
+RecoveryImprovedInstallerTraits::GetInstallerAttributes() const {
+  return update_client::InstallerAttributes();
+}
+
+std::vector<std::string> RecoveryImprovedInstallerTraits::GetMimeTypes() const {
+  return std::vector<std::string>();
+}
+
+void RegisterRecoveryImprovedComponent(ComponentUpdateService* cus,
+                                       PrefService* prefs) {
+  DVLOG(1) << "Registering RecoveryImproved component.";
+
+  std::unique_ptr<ComponentInstallerTraits> traits(
+      new RecoveryImprovedInstallerTraits(prefs));
+  // |cus| will take ownership of |installer| during installer->Register(cus).
+  DefaultComponentInstaller* installer =
+      new DefaultComponentInstaller(std::move(traits));
+  installer->Register(cus, base::Closure());
+}
+
+void RegisterPrefsForRecoveryImprovedComponent(PrefRegistrySimple* registry) {}
+
+}  // namespace component_updater
diff --git a/chrome/browser/component_updater/recovery_improved_component_installer.h b/chrome/browser/component_updater/recovery_improved_component_installer.h
new file mode 100644
index 0000000..207070ce0
--- /dev/null
+++ b/chrome/browser/component_updater/recovery_improved_component_installer.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_RECOVERY_IMPROVED_COMPONENT_INSTALLER_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_RECOVERY_IMPROVED_COMPONENT_INSTALLER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/feature_list.h"
+#include "components/component_updater/default_component_installer.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace component_updater {
+
+class ComponentUpdateService;
+
+class RecoveryImprovedInstallerTraits : public ComponentInstallerTraits {
+ public:
+  explicit RecoveryImprovedInstallerTraits(PrefService* prefs);
+  ~RecoveryImprovedInstallerTraits() override;
+
+ private:
+  friend class RecoveryImprovedInstallerTest;
+
+  // ComponentInstallerTraits implementation.
+  bool SupportsGroupPolicyEnabledComponentUpdates() const override;
+  bool RequiresNetworkEncryption() const override;
+  update_client::CrxInstaller::Result OnCustomInstall(
+      const base::DictionaryValue& manifest,
+      const base::FilePath& install_dir) override;
+  bool VerifyInstallation(const base::DictionaryValue& manifest,
+                          const base::FilePath& install_dir) const override;
+  void ComponentReady(const base::Version& version,
+                      const base::FilePath& install_dir,
+                      std::unique_ptr<base::DictionaryValue> manifest) override;
+  base::FilePath GetRelativeInstallDir() const override;
+  void GetHash(std::vector<uint8_t>* hash) const override;
+  std::string GetName() const override;
+  update_client::InstallerAttributes GetInstallerAttributes() const override;
+  std::vector<std::string> GetMimeTypes() const override;
+
+  PrefService* prefs_;
+
+  DISALLOW_COPY_AND_ASSIGN(RecoveryImprovedInstallerTraits);
+};
+
+void RegisterRecoveryImprovedComponent(ComponentUpdateService* cus,
+                                       PrefService* prefs);
+
+// Registers user preferences related to the recovery component.
+void RegisterPrefsForRecoveryImprovedComponent(PrefRegistrySimple* registry);
+
+}  // namespace component_updater
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_RECOVERY_IMPROVED_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/devtools/device/devtools_device_discovery.h b/chrome/browser/devtools/device/devtools_device_discovery.h
index e89e841..7c35548 100644
--- a/chrome/browser/devtools/device/devtools_device_discovery.h
+++ b/chrome/browser/devtools/device/devtools_device_discovery.h
@@ -18,7 +18,7 @@
 
 class DevToolsDeviceDiscovery {
  public:
-  class RemotePage : public base::RefCounted<RemotePage> {
+  class RemotePage : public base::RefCountedThreadSafe<RemotePage> {
    public:
     scoped_refptr<AndroidDeviceManager::Device> device() { return device_; }
     const std::string& socket() { return browser_id_; }
@@ -26,7 +26,7 @@
     scoped_refptr<content::DevToolsAgentHost> CreateTarget();
 
    private:
-    friend class base::RefCounted<RemotePage>;
+    friend class base::RefCountedThreadSafe<RemotePage>;
     friend class DevToolsDeviceDiscovery;
 
     RemotePage(scoped_refptr<AndroidDeviceManager::Device> device,
@@ -45,7 +45,7 @@
 
   using RemotePages = std::vector<scoped_refptr<RemotePage>>;
 
-  class RemoteBrowser : public base::RefCounted<RemoteBrowser> {
+  class RemoteBrowser : public base::RefCountedThreadSafe<RemoteBrowser> {
    public:
     const std::string& serial() { return serial_; }
     const std::string& socket() { return browser_id_; }
@@ -61,7 +61,7 @@
     ParsedVersion GetParsedVersion();
 
    private:
-    friend class base::RefCounted<RemoteBrowser>;
+    friend class base::RefCountedThreadSafe<RemoteBrowser>;
     friend class DevToolsDeviceDiscovery;
 
     RemoteBrowser(const std::string& serial,
@@ -82,7 +82,7 @@
 
   using RemoteBrowsers = std::vector<scoped_refptr<RemoteBrowser>>;
 
-  class RemoteDevice : public base::RefCounted<RemoteDevice> {
+  class RemoteDevice : public base::RefCountedThreadSafe<RemoteDevice> {
    public:
     std::string serial() { return serial_; }
     std::string model() { return model_; }
@@ -91,7 +91,7 @@
     gfx::Size screen_size() { return screen_size_; }
 
    private:
-    friend class base::RefCounted<RemoteDevice>;
+    friend class base::RefCountedThreadSafe<RemoteDevice>;
     friend class DevToolsDeviceDiscovery;
 
     RemoteDevice(const std::string& serial,
diff --git a/chrome/browser/devtools/device/tcp_device_provider.cc b/chrome/browser/devtools/device/tcp_device_provider.cc
index f71eb2b..4d7a61b 100644
--- a/chrome/browser/devtools/device/tcp_device_provider.cc
+++ b/chrome/browser/devtools/device/tcp_device_provider.cc
@@ -55,8 +55,12 @@
     }
     std::unique_ptr<net::StreamSocket> socket(new net::TCPClientSocket(
         address_list_, NULL, NULL, net::NetLogSource()));
-    socket->Connect(
-        base::Bind(&RunSocketCallback, callback_, base::Passed(&socket)));
+    net::StreamSocket* socket_ptr = socket.get();
+    net::CompletionCallback on_connect =
+        base::Bind(&RunSocketCallback, callback_, base::Passed(&socket));
+    result = socket_ptr->Connect(on_connect);
+    if (result != net::ERR_IO_PENDING)
+      on_connect.Run(result);
     delete this;
   }
 
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
index 6adbbac..72c7af1 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -213,13 +213,13 @@
 
   if (address->address_level1) {
     profile.SetRawInfo(
-        autofill::ADDRESS_HOME_CITY,
+        autofill::ADDRESS_HOME_STATE,
         base::UTF8ToUTF16(*address->address_level1));
   }
 
   if (address->address_level2) {
     profile.SetRawInfo(
-        autofill::ADDRESS_HOME_STATE,
+        autofill::ADDRESS_HOME_CITY,
         base::UTF8ToUTF16(*address->address_level2));
   }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc b/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc
index 687389f..b28de0a 100644
--- a/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc
@@ -20,8 +20,9 @@
 DestroyPartitionsOperation::DestroyPartitionsOperation(
     base::WeakPtr<OperationManager> manager,
     const ExtensionId& extension_id,
-    const std::string& storage_unit_id)
-    : Operation(manager, extension_id, storage_unit_id) {}
+    const std::string& storage_unit_id,
+    const base::FilePath& download_folder)
+    : Operation(manager, extension_id, storage_unit_id, download_folder) {}
 
 DestroyPartitionsOperation::~DestroyPartitionsOperation() {}
 
diff --git a/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.h b/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.h
index b01e513..30b7a961 100644
--- a/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.h
@@ -19,7 +19,8 @@
  public:
   DestroyPartitionsOperation(base::WeakPtr<OperationManager> manager,
                              const ExtensionId& extension_id,
-                             const std::string& storage_unit_id);
+                             const std::string& storage_unit_id,
+                             const base::FilePath& download_folder);
   void StartImpl() override;
 
  private:
diff --git a/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation_unittest.cc b/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation_unittest.cc
index 64e8a5db..491ff82 100644
--- a/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation_unittest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation_unittest.cc
@@ -28,7 +28,8 @@
       new DestroyPartitionsOperation(
           manager.AsWeakPtr(),
           kDummyExtensionId,
-          test_utils_.GetDevicePath().AsUTF8Unsafe()));
+          test_utils_.GetDevicePath().AsUTF8Unsafe(),
+          base::FilePath(FILE_PATH_LITERAL("/var/tmp"))));
 
   EXPECT_CALL(
       manager,
diff --git a/chrome/browser/extensions/api/image_writer_private/operation.cc b/chrome/browser/extensions/api/image_writer_private/operation.cc
index 1d8d74d..f06a7cc7 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -22,12 +22,6 @@
 using content::BrowserThread;
 
 const int kMD5BufferSize = 1024;
-#if defined(OS_CHROMEOS)
-// Chrome OS only has a 1 GB temporary partition.  This is too small to hold our
-// unzipped image. Fortunately we mount part of the temporary partition under
-// /var/tmp.
-const char kChromeOSTempRoot[] = "/var/tmp";
-#endif
 
 #if !defined(OS_CHROMEOS)
 static base::LazyInstance<scoped_refptr<ImageWriterUtilityClient> >
@@ -36,7 +30,8 @@
 
 Operation::Operation(base::WeakPtr<OperationManager> manager,
                      const ExtensionId& extension_id,
-                     const std::string& device_path)
+                     const std::string& device_path,
+                     const base::FilePath& download_folder)
     : manager_(manager),
       extension_id_(extension_id),
 #if defined(OS_WIN)
@@ -46,7 +41,8 @@
 #endif
       stage_(image_writer_api::STAGE_UNKNOWN),
       progress_(0),
-      zip_reader_(new zip::ZipReader) {
+      zip_reader_(new zip::ZipReader),
+      download_folder_(download_folder) {
 }
 
 Operation::~Operation() {}
@@ -81,8 +77,8 @@
 
 void Operation::Start() {
 #if defined(OS_CHROMEOS)
-  if (!temp_dir_.CreateUniqueTempDirUnderPath(
-           base::FilePath(kChromeOSTempRoot))) {
+  if (download_folder_.empty() ||
+      !temp_dir_.CreateUniqueTempDirUnderPath(download_folder_)) {
 #else
   if (!temp_dir_.CreateUniqueTempDir()) {
 #endif
diff --git a/chrome/browser/extensions/api/image_writer_private/operation.h b/chrome/browser/extensions/api/image_writer_private/operation.h
index 98412b7..b6d49387 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/operation.h
@@ -62,7 +62,8 @@
 
   Operation(base::WeakPtr<OperationManager> manager,
             const ExtensionId& extension_id,
-            const std::string& device_path);
+            const std::string& device_path,
+            const base::FilePath& download_folder);
 
   // Starts the operation.
   void Start();
@@ -223,6 +224,11 @@
   // CleanUp operations that must be run.  All these functions are run on the
   // FILE thread.
   std::vector<base::Closure> cleanup_functions_;
+
+  // The download folder on Chrome OS.
+  const base::FilePath download_folder_;
+
+  DISALLOW_COPY_AND_ASSIGN(Operation);
 };
 
 }  // namespace image_writer
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index f8f036d..aaa05ff0 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -25,6 +25,10 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/notification_types.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/file_manager/path_util.h"
+#endif
+
 namespace image_writer_api = extensions::api::image_writer_private;
 
 namespace extensions {
@@ -87,7 +91,8 @@
           GetURLRequestContext(),
       url,
       hash,
-      device_path));
+      device_path,
+      GetAssociatedDownloadFolder()));
   operations_[extension_id] = operation;
   BrowserThread::PostTask(BrowserThread::FILE,
                           FROM_HERE,
@@ -112,7 +117,8 @@
   }
 
   scoped_refptr<Operation> operation(new WriteFromFileOperation(
-      weak_factory_.GetWeakPtr(), extension_id, path, device_path));
+      weak_factory_.GetWeakPtr(), extension_id, path, device_path,
+      GetAssociatedDownloadFolder()));
   operations_[extension_id] = operation;
   BrowserThread::PostTask(BrowserThread::FILE,
                           FROM_HERE,
@@ -147,7 +153,8 @@
   }
 
   scoped_refptr<Operation> operation(new DestroyPartitionsOperation(
-      weak_factory_.GetWeakPtr(), extension_id, device_path));
+      weak_factory_.GetWeakPtr(), extension_id, device_path,
+      GetAssociatedDownloadFolder()));
   operations_[extension_id] = operation;
   BrowserThread::PostTask(BrowserThread::FILE,
                           FROM_HERE,
@@ -213,6 +220,14 @@
   DeleteOperation(extension_id);
 }
 
+base::FilePath OperationManager::GetAssociatedDownloadFolder() {
+#if defined(OS_CHROMEOS)
+  Profile* profile = Profile::FromBrowserContext(browser_context_);
+  return file_manager::util::GetDownloadsFolderForProfile(profile);
+#endif
+  return base::FilePath();
+}
+
 Operation* OperationManager::GetOperation(const ExtensionId& extension_id) {
   OperationMap::iterator existing_operation = operations_.find(extension_id);
 
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.h b/chrome/browser/extensions/api/image_writer_private/operation_manager.h
index 8cf12d8..5243080 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.h
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.h
@@ -104,6 +104,9 @@
   Operation* GetOperation(const ExtensionId& extension_id);
   void DeleteOperation(const ExtensionId& extension_id);
 
+  // Accessor to the associated profile download folder
+  base::FilePath GetAssociatedDownloadFolder();
+
   friend class BrowserContextKeyedAPIFactory<OperationManager>;
   typedef std::map<ExtensionId, scoped_refptr<Operation> > OperationMap;
 
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc b/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
index 55ab362b..c0d6833 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
@@ -35,8 +35,9 @@
  public:
   OperationForTest(base::WeakPtr<OperationManager> manager_,
                    const ExtensionId& extension_id,
-                   const std::string& device_path)
-      : Operation(manager_, extension_id, device_path) {}
+                   const std::string& device_path,
+                   const base::FilePath& download_path)
+      : Operation(manager_, extension_id, device_path, download_path) {}
 
   void StartImpl() override {}
 
@@ -85,7 +86,8 @@
     operation_ =
         new OperationForTest(manager_.AsWeakPtr(),
                              kDummyExtensionId,
-                             test_utils_.GetDevicePath().AsUTF8Unsafe());
+                             test_utils_.GetDevicePath().AsUTF8Unsafe(),
+                             base::FilePath(FILE_PATH_LITERAL("/var/tmp")));
     operation_->SetImagePath(test_utils_.GetImagePath());
   }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc
index a804278..b29feaa 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.cc
@@ -16,8 +16,9 @@
     base::WeakPtr<OperationManager> manager,
     const ExtensionId& extension_id,
     const base::FilePath& user_file_path,
-    const std::string& device_path)
-    : Operation(manager, extension_id, device_path) {
+    const std::string& device_path,
+    const base::FilePath& download_folder)
+    : Operation(manager, extension_id, device_path, download_folder) {
   image_path_ = user_file_path;
 }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h
index 3f567ae..ef82e25 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation.h
@@ -16,7 +16,8 @@
   WriteFromFileOperation(base::WeakPtr<OperationManager> manager,
                          const ExtensionId& extension_id,
                          const base::FilePath& user_file_path,
-                         const std::string& storage_unit_id);
+                         const std::string& storage_unit_id,
+                         const base::FilePath& download_folder);
   void StartImpl() override;
 
  private:
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc
index bb241d0..3c6fb91 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc
@@ -29,7 +29,8 @@
       new WriteFromFileOperation(manager_.AsWeakPtr(),
                                  kDummyExtensionId,
                                  test_utils_.GetImagePath(),
-                                 test_utils_.GetDevicePath().AsUTF8Unsafe());
+                                 test_utils_.GetDevicePath().AsUTF8Unsafe(),
+                                 base::FilePath(FILE_PATH_LITERAL("/var/tmp")));
 
   base::DeleteFile(test_utils_.GetImagePath(), false);
 
@@ -52,7 +53,8 @@
       new WriteFromFileOperation(manager_.AsWeakPtr(),
                                  kDummyExtensionId,
                                  test_utils_.GetImagePath(),
-                                 test_utils_.GetDevicePath().AsUTF8Unsafe());
+                                 test_utils_.GetDevicePath().AsUTF8Unsafe(),
+                                 base::FilePath(FILE_PATH_LITERAL("/var/tmp")));
   EXPECT_CALL(manager_,
               OnProgress(kDummyExtensionId, image_writer_api::STAGE_WRITE, _))
       .Times(AnyNumber());
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
index 911d938..4c619e38 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
@@ -20,8 +20,9 @@
     net::URLRequestContextGetter* request_context,
     GURL url,
     const std::string& hash,
-    const std::string& device_path)
-    : Operation(manager, extension_id, device_path),
+    const std::string& device_path,
+    const base::FilePath& download_folder)
+    : Operation(manager, extension_id, device_path, download_folder),
       request_context_(request_context),
       url_(url),
       hash_(hash),
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
index 99013ce..b653bbfb 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
@@ -29,7 +29,8 @@
                         net::URLRequestContextGetter* request_context,
                         GURL url,
                         const std::string& hash,
-                        const std::string& storage_unit_id);
+                        const std::string& storage_unit_id,
+                        const base::FilePath& download_folder);
   void StartImpl() override;
 
  protected:
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
index ca70690..d26833a 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
@@ -40,7 +40,8 @@
                               request_context,
                               url,
                               hash,
-                              storage_unit_id) {}
+                              storage_unit_id,
+                              base::FilePath(FILE_PATH_LITERAL("/var/tmp"))) {}
 
   void StartImpl() override {}
 
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
index 5e1e31f..1d8bbb7 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
 #include "chrome/common/extensions/wifi_credentials_getter.mojom.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -27,8 +28,9 @@
       network_ = extensions::mojom::WiFiCredentialsGetter::kWiFiTestNetwork;
 
     done_called_ = false;
-    content::BrowserThread::PostBlockingPoolTask(
-        FROM_HERE,
+    base::PostTaskWithTraits(
+        FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                       base::TaskPriority::BACKGROUND),
         base::Bind(&NetworkingPrivateCredentialsGetterTest::GetCredentials,
                    base::Unretained(this)));
     run_loop.Run();
diff --git a/chrome/browser/extensions/component_migration_helper.cc b/chrome/browser/extensions/component_migration_helper.cc
index aa7242f..4c9a8fa 100644
--- a/chrome/browser/extensions/component_migration_helper.cc
+++ b/chrome/browser/extensions/component_migration_helper.cc
@@ -15,7 +15,6 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/extension_registry.h"
-#include "extensions/common/feature_switch.h"
 
 namespace extensions {
 
@@ -60,7 +59,6 @@
 
 void ComponentMigrationHelper::OnFeatureEnabled(
     const std::string& component_action_id) {
-  DCHECK(FeatureSwitch::extension_action_redesign()->IsEnabled());
   std::vector<ExtensionId> extension_ids =
       GetExtensionIdsForActionId(component_action_id);
   DCHECK(!extension_ids.empty());
@@ -102,8 +100,7 @@
   enabled_actions_.erase(component_action_id);
   RemoveComponentActionPref(component_action_id);
 
-  if (FeatureSwitch::extension_action_redesign()->IsEnabled() &&
-      delegate_->HasComponentAction(component_action_id))
+  if (delegate_->HasComponentAction(component_action_id))
     delegate_->RemoveComponentAction(component_action_id);
 }
 
diff --git a/chrome/browser/extensions/component_migration_helper_unittest.cc b/chrome/browser/extensions/component_migration_helper_unittest.cc
index 8168c77..0c6a645 100644
--- a/chrome/browser/extensions/component_migration_helper_unittest.cc
+++ b/chrome/browser/extensions/component_migration_helper_unittest.cc
@@ -15,7 +15,6 @@
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "extensions/browser/extension_registry.h"
-#include "extensions/common/feature_switch.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -60,10 +59,6 @@
   ~ComponentMigrationHelperTest() override {}
 
   void SetUp() override {
-    extension_action_redesign_.reset(new FeatureSwitch::ScopedOverride(
-        FeatureSwitch::extension_action_redesign(),
-        FeatureSwitch::OVERRIDE_ENABLED));
-
     ExtensionServiceTestBase::SetUp();
     InitializeEmptyExtensionService();
 
@@ -97,7 +92,6 @@
 
   StrictMock<MockComponentActionDelegate> mock_delegate_;
   std::unique_ptr<StrictMock<MockComponentMigrationHelper>> mock_helper_;
-  std::unique_ptr<FeatureSwitch::ScopedOverride> extension_action_redesign_;
 
   // Migrated extensions with browser actions.
   scoped_refptr<const Extension> migrated_extension_a_;
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc
index 61863ad..427cc07 100644
--- a/chrome/browser/extensions/extension_context_menu_model.cc
+++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -38,7 +38,6 @@
 #include "extensions/browser/management_policy.h"
 #include "extensions/browser/uninstall_reason.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/feature_switch.h"
 #include "extensions/common/manifest_handlers/options_page_info.h"
 #include "extensions/common/manifest_url_handlers.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -72,35 +71,26 @@
   return false;
 }
 
-// Returns the id for the visibility command for the given |extension|, or -1
-// if none should be shown.
+// Returns the id for the visibility command for the given |extension|.
 int GetVisibilityStringId(
     Profile* profile,
     const Extension* extension,
     ExtensionContextMenuModel::ButtonVisibility button_visibility) {
   DCHECK(profile);
   int string_id = -1;
-  if (!FeatureSwitch::extension_action_redesign()->IsEnabled()) {
-    // Without the toolbar redesign, we only show the visibility toggle for
-    // browser actions, and only give the option to hide.
-    if (ExtensionActionManager::Get(profile)->GetBrowserAction(*extension)) {
-      string_id = IDS_EXTENSIONS_HIDE_BUTTON;
-    }
-  } else {
-    // With the redesign, we display "show" or "hide" based on the icon's
-    // visibility, and can have "transitively shown" buttons that are shown
-    // only while the button has a popup or menu visible.
-    switch (button_visibility) {
-      case (ExtensionContextMenuModel::VISIBLE):
-        string_id = IDS_EXTENSIONS_HIDE_BUTTON_IN_MENU;
-        break;
-      case (ExtensionContextMenuModel::TRANSITIVELY_VISIBLE):
-        string_id = IDS_EXTENSIONS_KEEP_BUTTON_IN_TOOLBAR;
-        break;
-      case (ExtensionContextMenuModel::OVERFLOWED):
-        string_id = IDS_EXTENSIONS_SHOW_BUTTON_IN_TOOLBAR;
-        break;
-    }
+  // We display "show" or "hide" based on the icon's visibility, and can have
+  // "transitively shown" buttons that are shown only while the button has a
+  // popup or menu visible.
+  switch (button_visibility) {
+    case (ExtensionContextMenuModel::VISIBLE):
+      string_id = IDS_EXTENSIONS_HIDE_BUTTON_IN_MENU;
+      break;
+    case (ExtensionContextMenuModel::TRANSITIVELY_VISIBLE):
+      string_id = IDS_EXTENSIONS_KEEP_BUTTON_IN_TOOLBAR;
+      break;
+    case (ExtensionContextMenuModel::OVERFLOWED):
+      string_id = IDS_EXTENSIONS_SHOW_BUTTON_IN_TOOLBAR;
+      break;
   }
   return string_id;
 }
@@ -259,11 +249,6 @@
       break;
     case TOGGLE_VISIBILITY: {
       bool currently_visible = button_visibility_ == VISIBLE;
-      // Without the toolbar redesign turned on, action visibility refers to
-      // any action presence in the toolbar, independent of whether the action
-      // is visible or overflowed. So any action present is considered visible.
-      if (!FeatureSwitch::extension_action_redesign()->IsEnabled())
-        currently_visible = true;
       ToolbarActionsModel::Get(browser_->profile())
           ->SetActionVisibility(extension->id(), !currently_visible);
       break;
@@ -339,8 +324,8 @@
   // toolbar.
   int visibility_string_id =
       GetVisibilityStringId(profile_, extension, button_visibility);
-  if (visibility_string_id != -1)
-    AddItemWithStringId(TOGGLE_VISIBILITY, visibility_string_id);
+  DCHECK_NE(-1, visibility_string_id);
+  AddItemWithStringId(TOGGLE_VISIBILITY, visibility_string_id);
 
   if (!is_component_) {
     AddSeparator(ui::NORMAL_SEPARATOR);
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
index 3ace2ca..fe073222 100644
--- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc
+++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -340,79 +340,8 @@
 }
 
 // Test that the "show" and "hide" menu items appear correctly in the extension
-// context menu without the toolbar redesign.
-TEST_F(ExtensionContextMenuModelTest, ExtensionContextMenuShowAndHideLegacy) {
-  // Start with the toolbar redesign disabled.
-  FeatureSwitch::ScopedOverride toolbar_redesign_override(
-      FeatureSwitch::extension_action_redesign(), false);
-
-  InitializeEmptyExtensionService();
-  Browser* browser = GetBrowser();
-  extension_action_test_util::CreateToolbarModelForProfile(profile());
-
-  const Extension* page_action = AddExtension(
-      "page_action_extension", manifest_keys::kPageAction, Manifest::INTERNAL);
-  const Extension* browser_action =
-      AddExtension("browser_action_extension", manifest_keys::kBrowserAction,
-                   Manifest::INTERNAL);
-
-  // For laziness.
-  const ExtensionContextMenuModel::MenuEntries visibility_command =
-      ExtensionContextMenuModel::TOGGLE_VISIBILITY;
-  base::string16 hide_string =
-      l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_BUTTON);
-
-  {
-    ExtensionContextMenuModel menu(page_action, browser,
-                                   ExtensionContextMenuModel::VISIBLE, nullptr);
-
-    // Without the toolbar redesign switch, page action menus shouldn't have a
-    // visibility option.
-    EXPECT_EQ(-1, menu.GetIndexOfCommandId(visibility_command));
-  }
-
-  {
-    ExtensionContextMenuModel menu(browser_action, browser,
-                                   ExtensionContextMenuModel::VISIBLE, nullptr);
-    int index = menu.GetIndexOfCommandId(visibility_command);
-    // Browser actions should have the visibility option.
-    EXPECT_NE(-1, index);
-    // Since the action is currently visible, it should have the option to hide
-    // it.
-    EXPECT_EQ(hide_string, menu.GetLabelAt(index));
-  }
-
-  {
-    ExtensionContextMenuModel menu(browser_action, browser,
-                                   ExtensionContextMenuModel::OVERFLOWED,
-                                   nullptr);
-    int index = menu.GetIndexOfCommandId(visibility_command);
-    EXPECT_NE(-1, index);
-    // Without the redesign, 'hiding' refers to removing the action from the
-    // toolbar entirely, so even with the action overflowed, the string should
-    // be 'Hide action'.
-    EXPECT_EQ(hide_string, menu.GetLabelAt(index));
-
-    ExtensionActionAPI* action_api = ExtensionActionAPI::Get(profile());
-    // At the start, the action should be visible.
-    EXPECT_TRUE(action_api->GetBrowserActionVisibility(browser_action->id()));
-    menu.ExecuteCommand(visibility_command, 0);
-    // After execution, it should be hidden.
-    EXPECT_FALSE(action_api->GetBrowserActionVisibility(browser_action->id()));
-
-    // Cleanup - make the action visible again.
-    action_api->SetBrowserActionVisibility(browser_action->id(), true);
-  }
-}
-
-// Test that the "show" and "hide" menu items appear correctly in the extension
-// context menu with the toolbar redesign.
-TEST_F(ExtensionContextMenuModelTest, ExtensionContextMenuShowAndHideRedesign) {
-  // Start with the toolbar redesign disabled.
-  std::unique_ptr<FeatureSwitch::ScopedOverride> toolbar_redesign_override(
-      new FeatureSwitch::ScopedOverride(
-          FeatureSwitch::extension_action_redesign(), true));
-
+// context menu.
+TEST_F(ExtensionContextMenuModelTest, ExtensionContextMenuShowAndHide) {
   InitializeEmptyExtensionService();
   Browser* browser = GetBrowser();
   extension_action_test_util::CreateToolbarModelForProfile(profile());
@@ -428,20 +357,20 @@
   // For laziness.
   const ExtensionContextMenuModel::MenuEntries visibility_command =
       ExtensionContextMenuModel::TOGGLE_VISIBILITY;
-  base::string16 redesign_hide_string =
+  base::string16 hide_string =
       l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_BUTTON_IN_MENU);
-  base::string16 redesign_show_string =
+  base::string16 show_string =
       l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON_IN_TOOLBAR);
-  base::string16 redesign_keep_string =
+  base::string16 keep_string =
       l10n_util::GetStringUTF16(IDS_EXTENSIONS_KEEP_BUTTON_IN_TOOLBAR);
 
   {
-    // Even page actions should have a visibility option with the redesign on.
+    // Even page actions should have a visibility option.
     ExtensionContextMenuModel menu(page_action, browser,
                                    ExtensionContextMenuModel::VISIBLE, nullptr);
     int index = menu.GetIndexOfCommandId(visibility_command);
     EXPECT_NE(-1, index);
-    EXPECT_EQ(redesign_hide_string, menu.GetLabelAt(index));
+    EXPECT_EQ(hide_string, menu.GetLabelAt(index));
   }
 
   {
@@ -449,12 +378,13 @@
                                    ExtensionContextMenuModel::VISIBLE, nullptr);
     int index = menu.GetIndexOfCommandId(visibility_command);
     EXPECT_NE(-1, index);
-    EXPECT_EQ(redesign_hide_string, menu.GetLabelAt(index));
+    EXPECT_EQ(hide_string, menu.GetLabelAt(index));
 
     ExtensionActionAPI* action_api = ExtensionActionAPI::Get(profile());
     EXPECT_TRUE(action_api->GetBrowserActionVisibility(browser_action->id()));
-    // Executing the 'hide' command shouldn't modify the prefs with the redesign
-    // turned on (the ordering behavior is tested in ToolbarActionsModel tests).
+    // Executing the 'hide' command shouldn't modify the prefs (the ordering
+    // behavior is tested in ToolbarActionsModel tests).
+    // TODO(devlin): We should be able to get rid of the pref.
     menu.ExecuteCommand(visibility_command, 0);
     EXPECT_TRUE(action_api->GetBrowserActionVisibility(browser_action->id()));
   }
@@ -467,7 +397,7 @@
                                    nullptr);
     int index = menu.GetIndexOfCommandId(visibility_command);
     EXPECT_NE(-1, index);
-    EXPECT_EQ(redesign_show_string, menu.GetLabelAt(index));
+    EXPECT_EQ(show_string, menu.GetLabelAt(index));
   }
 
   {
@@ -478,7 +408,7 @@
         ExtensionContextMenuModel::TRANSITIVELY_VISIBLE, nullptr);
     int index = menu.GetIndexOfCommandId(visibility_command);
     EXPECT_NE(-1, index);
-    EXPECT_EQ(redesign_keep_string, menu.GetLabelAt(index));
+    EXPECT_EQ(keep_string, menu.GetLabelAt(index));
   }
 }
 
@@ -675,10 +605,6 @@
 }
 
 TEST_F(ExtensionContextMenuModelTest, TestInspectPopupPresence) {
-  std::unique_ptr<FeatureSwitch::ScopedOverride> toolbar_redesign_override(
-      new FeatureSwitch::ScopedOverride(
-          FeatureSwitch::extension_action_redesign(), true));
-
   InitializeEmptyExtensionService();
   {
     const Extension* page_action = AddExtension(
@@ -700,9 +626,8 @@
     EXPECT_GE(0, inspect_popup_index);
   }
   {
-    // With the extension toolbar redesign, an extension with no specified
-    // action has one synthesized. However, there will never be a popup to
-    // inspect, so we shouldn't add a menu item.
+    // An extension with no specified action has one synthesized. However,
+    // there will never be a popup to inspect, so we shouldn't add a menu item.
     const Extension* no_action = AddExtension(
         "no_action", nullptr, Manifest::INTERNAL);
     ExtensionContextMenuModel menu(no_action, GetBrowser(),
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 732779d4..8734629 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -678,6 +678,7 @@
     system_->runtime_data()->SetBeingUpgraded(transient_current_extension->id(),
                                               true);
     DisableExtension(extension_id, Extension::DISABLE_RELOAD);
+    DCHECK(registry_->disabled_extensions().Contains(extension_id));
     reloading_extensions_.insert(extension_id);
   } else {
     std::map<std::string, base::FilePath>::const_iterator iter =
@@ -911,24 +912,30 @@
 
   const Extension* extension = GetInstalledExtension(extension_id);
 
-  // Shared modules cannot be disabled, they are just resources used by other
-  // extensions, and are not user controlled.
-  if (extension && SharedModuleInfo::IsSharedModule(extension))
-    return;
+  // Some extensions cannot be disabled by users:
+  // - |extension| can be null if sync disables an extension that is not
+  //   installed yet; allow disablement in this case.
+  // - Shared modules are just resources used by other extensions, and are not
+  //   user-controlled.
+  // - EXTERNAL_COMPONENT extensions are not generally modifiable by users, but
+  //   can be uninstalled by the browser if the user sets extension-specific
+  //   preferences.
+  bool is_controlled_extension =
+      extension && (SharedModuleInfo::IsSharedModule(extension) ||
+                    (!system_->management_policy()->UserMayModifySettings(
+                         extension, nullptr) &&
+                     extension->location() != Manifest::EXTERNAL_COMPONENT));
 
-  // |extension| can be nullptr if sync disables an extension that is not
-  // installed yet.
-  // EXTERNAL_COMPONENT extensions are not generally modifiable by users, but
-  // can be uninstalled by the browser if the user sets extension-specific
-  // preferences.
-  if (extension && !(disable_reasons & Extension::DISABLE_RELOAD) &&
-      !(disable_reasons & Extension::DISABLE_CORRUPTED) &&
-      !(disable_reasons & Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY) &&
-      !system_->management_policy()->UserMayModifySettings(extension,
-                                                           nullptr) &&
-      extension->location() != Manifest::EXTERNAL_COMPONENT) {
+  // Certain disable reasons are always allowed, since they are more internal to
+  // chrome (rather than the user choosing to disable the extension).
+  int internal_disable_reason_mask =
+      Extension::DISABLE_RELOAD | Extension::DISABLE_CORRUPTED |
+      Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY;
+  bool is_internal_disable =
+      (disable_reasons & internal_disable_reason_mask) > 0;
+
+  if (!is_internal_disable && is_controlled_extension)
     return;
-  }
 
   extension_prefs_->SetExtensionDisabled(extension_id, disable_reasons);
 
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 240f6275..30da09b 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -7174,3 +7174,32 @@
   // objects).
   EXPECT_NE(extension, registry()->enabled_extensions().GetByID(kExtensionId));
 }
+
+// Test reloading a shared module. Regression test for crbug.com/676815.
+TEST_F(ExtensionServiceTest, ReloadSharedModule) {
+  InitializeEmptyExtensionService();
+
+  // Add a shared module and an extension that depends on it (the latter is
+  // important to ensure we don't remove the unused shared module).
+  scoped_refptr<const Extension> shared_module =
+      extensions::ChromeTestExtensionLoader(profile()).LoadExtension(
+          data_dir().AppendASCII("api_test/shared_module/shared"));
+  scoped_refptr<const Extension> dependent =
+      extensions::ChromeTestExtensionLoader(profile()).LoadExtension(
+          data_dir().AppendASCII("api_test/shared_module/import_pass"));
+  ASSERT_TRUE(shared_module);
+  ASSERT_TRUE(dependent);
+  const std::string kExtensionId = shared_module->id();
+  ASSERT_TRUE(
+      extensions::Manifest::IsUnpackedLocation(shared_module->location()));
+  ASSERT_EQ(extensions::Manifest::TYPE_SHARED_MODULE,
+            shared_module->manifest()->type());
+  EXPECT_TRUE(registry()->enabled_extensions().Contains(kExtensionId));
+
+  // Reload the extension and wait for it to complete. This previously crashed
+  // (see crbug.com/676815).
+  service()->ReloadExtension(kExtensionId);
+  base::RunLoop().RunUntilIdle();
+  // The shared module should be enabled.
+  EXPECT_TRUE(registry()->enabled_extensions().Contains(kExtensionId));
+}
diff --git a/chrome/browser/extensions/native_bindings_apitest.cc b/chrome/browser/extensions/native_bindings_apitest.cc
index 385e453..c1d5ed9 100644
--- a/chrome/browser/extensions/native_bindings_apitest.cc
+++ b/chrome/browser/extensions/native_bindings_apitest.cc
@@ -34,7 +34,12 @@
 IN_PROC_BROWSER_TEST_F(NativeBindingsApiTest, SimpleEndToEndTest) {
   embedded_test_server()->ServeFilesFromDirectory(test_data_dir_);
   ASSERT_TRUE(StartEmbeddedTestServer());
-  ASSERT_TRUE(RunExtensionTest("native_bindings")) << message_;
+  ASSERT_TRUE(RunExtensionTest("native_bindings/extension")) << message_;
+}
+
+// A simplistic app test for app-specific APIs.
+IN_PROC_BROWSER_TEST_F(NativeBindingsApiTest, SimpleAppTest) {
+  ASSERT_TRUE(RunPlatformAppTest("native_bindings/platform_app")) << message_;
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index e1d7dd2..ca397ec 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -342,7 +342,9 @@
   }
 
   const GURL welcome_page(chrome::kChromeUIWelcomeURL);
-  return contents->GetURL().GetWithEmptyPath() == welcome_page;
+  const GURL welcome_page_win10(chrome::kChromeUIWelcomeWin10URL);
+  const GURL current = contents->GetURL().GetWithEmptyPath();
+  return current == welcome_page || current == welcome_page_win10;
 }
 
 // Show the first run search engine bubble at the first appropriate opportunity.
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
index 154f28f0..32a26c5 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -106,6 +106,7 @@
 #endif
 
 #if defined(OS_ANDROID)
+#include "chrome/browser/android/download/intercept_download_resource_throttle.h"
 #include "chrome/browser/android/offline_pages/downloads/resource_throttle.h"
 #include "chrome/browser/loader/data_reduction_proxy_resource_throttle_android.h"
 #include "components/navigation_interception/intercept_navigation_delegate.h"
@@ -552,6 +553,9 @@
                                     content::RESOURCE_TYPE_MAIN_FRAME,
                                     throttles);
 #if defined(OS_ANDROID)
+    throttles->push_back(
+        base::MakeUnique<InterceptDownloadResourceThrottle>(
+            request, info->GetWebContentsGetterForRequest()));
     // On Android, forward text/html downloads to OfflinePages backend.
     throttles->push_back(
         base::MakeUnique<offline_pages::downloads::ResourceThrottle>(request));
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 4ffa8f4c..09872a7 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -12,10 +12,13 @@
 #include "chrome/browser/media/media_browsertest.h"
 #include "chrome/browser/media/test_license_server.h"
 #include "chrome/browser/media/wv_test_license_server_config.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/test_launcher_utils.h"
+#include "components/prefs/pref_service.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/media_switches.h"
@@ -415,6 +418,11 @@
                               CurrentKeySystem(), query_params, kEnded);
   }
 
+  void DisableEncryptedMedia() {
+    PrefService* pref_service = browser()->profile()->GetPrefs();
+    pref_service->SetBoolean(prefs::kWebKitEncryptedMediaEnabled, false);
+  }
+
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
     EncryptedMediaTestBase::SetUpCommandLine(command_line);
@@ -536,6 +544,14 @@
   TestFrameSizeChange();
 }
 
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, EncryptedMediaDisabled) {
+  DisableEncryptedMedia();
+  RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
+                        kWebMVorbisAudioOnly, CurrentKeySystem(),
+                        CurrentSourceType(), kNoSessionToLoad, false,
+                        PlayCount::ONCE, kEmeNotSupportedError);
+}
+
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
 // Crashes on Mac only.  http://crbug.com/621857
 #if defined(OS_MACOSX)
diff --git a/chrome/browser/media/router/browser_presentation_connection_proxy_unittest.cc b/chrome/browser/media/router/browser_presentation_connection_proxy_unittest.cc
index 4882d73..81a2cdc 100644
--- a/chrome/browser/media/router/browser_presentation_connection_proxy_unittest.cc
+++ b/chrome/browser/media/router/browser_presentation_connection_proxy_unittest.cc
@@ -104,7 +104,7 @@
 
   base::MockCallback<base::Callback<void(bool)>> mock_on_message_callback;
   EXPECT_CALL(*mock_router(), SendRouteBinaryMessageInternal(_, _, _))
-      .WillOnce(::testing::Invoke([this, &expected_data](
+      .WillOnce(::testing::Invoke([&expected_data](
           const MediaRoute::Id& route_id, std::vector<uint8_t>* data,
           const BrowserPresentationConnectionProxy::OnMessageCallback&
               callback) { EXPECT_EQ(expected_data, *data); }));
diff --git a/chrome/browser/media/router/media_router_base_unittest.cc b/chrome/browser/media/router/media_router_base_unittest.cc
index e5300f50..4b942cfc 100644
--- a/chrome/browser/media/router/media_router_base_unittest.cc
+++ b/chrome/browser/media/router/media_router_base_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/test/mock_callback.h"
 #include "chrome/browser/media/router/mock_media_router.h"
 #include "chrome/browser/media/router/test_helper.h"
 #include "content/public/common/presentation_session.h"
@@ -67,18 +68,16 @@
 TEST_F(MediaRouterBaseTest, NotifyCallbacks) {
   MediaRoute::Id route_id1("id1");
   MediaRoute::Id route_id2("id2");
-  MockPresentationConnectionStateChangedCallback callback1;
-  MockPresentationConnectionStateChangedCallback callback2;
+  base::MockCallback<content::PresentationConnectionStateChangedCallback>
+      callback1;
+  base::MockCallback<content::PresentationConnectionStateChangedCallback>
+      callback2;
   std::unique_ptr<PresentationConnectionStateSubscription> subscription1 =
-      router_.AddPresentationConnectionStateChangedCallback(
-          route_id1,
-          base::Bind(&MockPresentationConnectionStateChangedCallback::Run,
-                     base::Unretained(&callback1)));
+      router_.AddPresentationConnectionStateChangedCallback(route_id1,
+                                                            callback1.Get());
   std::unique_ptr<PresentationConnectionStateSubscription> subscription2 =
-      router_.AddPresentationConnectionStateChangedCallback(
-          route_id2,
-          base::Bind(&MockPresentationConnectionStateChangedCallback::Run,
-                     base::Unretained(&callback2)));
+      router_.AddPresentationConnectionStateChangedCallback(route_id2,
+                                                            callback2.Get());
 
   content::PresentationConnectionStateChangeInfo change_info_connected(
       content::PRESENTATION_CONNECTION_STATE_CONNECTED);
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
index 70df1a6..6bab1d0 100644
--- a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
+++ b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/mock_callback.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/media/router/issue.h"
 #include "chrome/browser/media/router/media_route.h"
@@ -1100,12 +1101,11 @@
   const std::string kPresentationId("pid");
   content::PresentationSessionInfo connection(presentation_url,
                                               kPresentationId);
-  MockPresentationConnectionStateChangedCallback callback;
+  base::MockCallback<content::PresentationConnectionStateChangedCallback>
+      callback;
   std::unique_ptr<PresentationConnectionStateSubscription> subscription =
-      router()->AddPresentationConnectionStateChangedCallback(
-          route_id,
-          base::Bind(&MockPresentationConnectionStateChangedCallback::Run,
-                     base::Unretained(&callback)));
+      router()->AddPresentationConnectionStateChangedCallback(route_id,
+                                                              callback.Get());
 
   {
     base::RunLoop run_loop;
@@ -1140,12 +1140,11 @@
 TEST_F(MediaRouterMojoImplTest,
        PresentationConnectionStateChangedCallbackRemoved) {
   MediaRoute::Id route_id("route-id");
-  MockPresentationConnectionStateChangedCallback callback;
+  base::MockCallback<content::PresentationConnectionStateChangedCallback>
+      callback;
   std::unique_ptr<PresentationConnectionStateSubscription> subscription =
-      router()->AddPresentationConnectionStateChangedCallback(
-          route_id,
-          base::Bind(&MockPresentationConnectionStateChangedCallback::Run,
-                     base::Unretained(&callback)));
+      router()->AddPresentationConnectionStateChangedCallback(route_id,
+                                                              callback.Get());
 
   // Callback has been removed, so we don't expect it to be called anymore.
   subscription.reset();
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
index edfdc20..f0ec236 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
@@ -436,10 +436,9 @@
   for (const auto& route_response_callback : route_response_callbacks)
     route_response_callback.Run(*result);
 
-  MockPresentationConnectionStateChangedCallback mock_callback;
-  content::PresentationConnectionStateChangedCallback callback =
-      base::Bind(&MockPresentationConnectionStateChangedCallback::Run,
-                 base::Unretained(&mock_callback));
+  base::MockCallback<content::PresentationConnectionStateChangedCallback>
+      mock_callback;
+  auto callback = mock_callback.Get();
   content::PresentationSessionInfo connection(presentation_url1_,
                                               kPresentationId);
   EXPECT_CALL(router_, OnAddPresentationConnectionStateChangedCallbackInvoked(
diff --git a/chrome/browser/media/router/test_helper.cc b/chrome/browser/media/router/test_helper.cc
index 5d98680..184c87a 100644
--- a/chrome/browser/media/router/test_helper.cc
+++ b/chrome/browser/media/router/test_helper.cc
@@ -26,10 +26,4 @@
 MockMediaRoutesObserver::~MockMediaRoutesObserver() {
 }
 
-MockPresentationConnectionStateChangedCallback::
-    MockPresentationConnectionStateChangedCallback() = default;
-
-MockPresentationConnectionStateChangedCallback::
-    ~MockPresentationConnectionStateChangedCallback() = default;
-
 }  // namespace media_router
diff --git a/chrome/browser/media/router/test_helper.h b/chrome/browser/media/router/test_helper.h
index 80e2ee4..9ab1c5a2 100644
--- a/chrome/browser/media/router/test_helper.h
+++ b/chrome/browser/media/router/test_helper.h
@@ -78,14 +78,6 @@
       const std::vector<MediaRoute::Id>& joinable_route_ids));
 };
 
-class MockPresentationConnectionStateChangedCallback {
- public:
-  MockPresentationConnectionStateChangedCallback();
-  ~MockPresentationConnectionStateChangedCallback();
-  MOCK_METHOD1(Run,
-               void(const content::PresentationConnectionStateChangeInfo&));
-};
-
 }  // namespace media_router
 
 #endif  // CHROME_BROWSER_MEDIA_ROUTER_TEST_HELPER_H_
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index 033f9c9..903d743 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -171,15 +171,15 @@
               base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
   bool is_stable_channel =
       chrome::GetChannel() == version_info::Channel::STABLE;
+  auto suggestions_fetcher = base::MakeUnique<RemoteSuggestionsFetcher>(
+      signin_manager, token_service, request_context, pref_service,
+      language_model, base::Bind(&safe_json::SafeJsonParser::Parse),
+      is_stable_channel ? google_apis::GetAPIKey()
+                        : google_apis::GetNonStableAPIKey(),
+      service->user_classifier());
   auto provider = base::MakeUnique<RemoteSuggestionsProviderImpl>(
       service, pref_service, g_browser_process->GetApplicationLocale(),
-      service->category_ranker(),
-      base::MakeUnique<RemoteSuggestionsFetcher>(
-          signin_manager, token_service, request_context, pref_service,
-          language_model, base::Bind(&safe_json::SafeJsonParser::Parse),
-          is_stable_channel ? google_apis::GetAPIKey()
-                            : google_apis::GetNonStableAPIKey(),
-          service->user_classifier()),
+      service->category_ranker(), std::move(suggestions_fetcher),
       base::MakeUnique<ImageFetcherImpl>(base::MakeUnique<ImageDecoderImpl>(),
                                          request_context.get()),
       base::MakeUnique<ImageDecoderImpl>(),
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_features.cc b/chrome/browser/ntp_snippets/ntp_snippets_features.cc
index 88e281f4..d4afe96 100644
--- a/chrome/browser/ntp_snippets/ntp_snippets_features.cc
+++ b/chrome/browser/ntp_snippets/ntp_snippets_features.cc
@@ -11,5 +11,8 @@
     "always_notify";
 const char kContentSuggestionsNotificationsUseSnippetAsTextParam[] =
     "use_snippet_as_text";
+const char
+    kContentSuggestionsNotificationsKeepNotificationWhenFrontmostParam[] =
+        "keep_notification_when_frontmost";
 const char kContentSuggestionsNotificationsIgnoredLimitParam[] =
     "ignored_limit";
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_features.h b/chrome/browser/ntp_snippets/ntp_snippets_features.h
index 2e67d86..4ce2188 100644
--- a/chrome/browser/ntp_snippets/ntp_snippets_features.h
+++ b/chrome/browser/ntp_snippets/ntp_snippets_features.h
@@ -18,6 +18,11 @@
 // "false": use article's publisher as notification's text
 extern const char kContentSuggestionsNotificationsUseSnippetAsTextParam[];
 
+// "true": when Chrome becomes frontmost, leave notifications open.
+// "false": automatically dismiss notification when Chrome becomes frontmost.
+extern const char
+    kContentSuggestionsNotificationsKeepNotificationWhenFrontmostParam[];
+
 // An integer. The number of notifications that can be ignored. If the user
 // ignores this many notifications or more, we stop sending them.
 extern const char kContentSuggestionsNotificationsIgnoredLimitParam[];
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 36712d08..3cf12b2 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/accessibility/invert_bubble_prefs.h"
 #include "chrome/browser/browser_process_impl.h"
 #include "chrome/browser/browser_shutdown.h"
-#include "chrome/browser/budget_service/budget_manager.h"
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/component_updater/component_updater_prefs.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
@@ -477,7 +476,6 @@
   SCOPED_UMA_HISTOGRAM_TIMER("Settings.RegisterProfilePrefsTime");
   // User prefs. Please keep this list alphabetized.
   autofill::AutofillManager::RegisterProfilePrefs(registry);
-  BudgetManager::RegisterProfilePrefs(registry);
   syncer::SyncPrefs::RegisterProfilePrefs(registry);
   ChromeContentBrowserClient::RegisterProfilePrefs(registry);
   ChromeVersionService::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/push_messaging/PRESUBMIT.py b/chrome/browser/push_messaging/PRESUBMIT.py
deleted file mode 100644
index aa4ae97d..0000000
--- a/chrome/browser/push_messaging/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for Push Messaging.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.html b/chrome/browser/resources/chromeos/login/oobe_a11y_option.html
index 5bd09c0..f008e5e 100644
--- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.html
+++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.html
@@ -17,7 +17,8 @@
           <content select=".unchecked-value"></content>
         </div>
       </div>
-      <paper-toggle-button checked="{{checked}}"></paper-toggle-button>
+      <paper-toggle-button checked="{{checked}}" aria-label$="[[ariaLabel]]">
+      </paper-toggle-button>
     </div>
   </template>
 </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.js b/chrome/browser/resources/chromeos/login/oobe_a11y_option.js
index 6d5fac7d..08a24d8 100644
--- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.js
+++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.js
@@ -19,5 +19,10 @@
     chromeMessage: {
       type: String,
     },
+
+    /**
+     * ARIA-label for the button.
+     */
+    ariaLabel: String,
   },
 });
diff --git a/chrome/browser/resources/chromeos/login/oobe_buttons.html b/chrome/browser/resources/chromeos/login/oobe_buttons.html
index 1455522..31d426b 100644
--- a/chrome/browser/resources/chromeos/login/oobe_buttons.html
+++ b/chrome/browser/resources/chromeos/login/oobe_buttons.html
@@ -37,12 +37,13 @@
   Attributes:
     'disabled' - button is disabled when the attribute is set.
     'inverse' - makes text white and background blue
+    'aria-label' - accessibility label.
 -->
 <dom-module id="oobe-text-button">
   <link rel="stylesheet" href="oobe_text_button.css">
   <template>
     <paper-button id="textButton" on-tap="onClick_" disabled="[[disabled]]"
-        inverse$="[[inverse]]">
+        inverse$="[[inverse]]" aria-label$="[[ariaLabel]]">
       <div id="container"
           class="flex layout horizontal center center-justified self-stretch">
         <content></content>
@@ -61,11 +62,13 @@
 
   Attributes:
     'disabled' - button is disabled when the attribute is set.
+    'aria-label' - accessibility label.
 -->
 <dom-module id="oobe-back-button">
   <link rel="stylesheet" href="oobe_nav_button.css">
   <template>
-    <paper-button id="button" on-tap="onClick_" disabled="[[disabled]]">
+    <paper-button id="button" on-tap="onClick_" disabled="[[disabled]]"
+        aria-label$="[[ariaLabel]]">
       <div class="flex horizontal layout start center">
         <iron-icon icon="oobe-buttons:arrow-back"></iron-icon>
         <div id="text">$i18n{back}</div>
@@ -101,7 +104,7 @@
 <dom-module id="oobe-welcome-secondary-button">
   <link rel="stylesheet" href="oobe_welcome_secondary_button.css">
   <template>
-    <paper-button id="button" aria-label="[[ariaLabel]]">
+    <paper-button id="button" aria-label$="[[ariaLabel]]">
       <div id="container" class="flex layout vertical center self-stretch">
         <div id="subcontainer"
             class="flex layout horizontal center self-stretch">
diff --git a/chrome/browser/resources/chromeos/login/oobe_buttons.js b/chrome/browser/resources/chromeos/login/oobe_buttons.js
index 68650e3..c89ea0d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_buttons.js
+++ b/chrome/browser/resources/chromeos/login/oobe_buttons.js
@@ -9,6 +9,8 @@
     disabled: {type: Boolean, value: false, reflectToAttribute: true},
 
     inverse: Boolean,
+
+    ariaLabel: String,
   },
 
   focus: function() {
@@ -26,6 +28,8 @@
 
   properties: {
     disabled: {type: Boolean, value: false, reflectToAttribute: true},
+
+    ariaLabel: String,
   },
 
   focus: function() {
diff --git a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html
index 5194f0f..67100b00 100644
--- a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html
+++ b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.html
@@ -8,7 +8,8 @@
     <style include="md-select"></style>
     <div id="container"
         class="flex vertical layout center center-justified md-select-wrapper">
-      <select id="select" class="md-select" ></select>
+      <select id="select" aria-label$="[[ariaLabel]]" class="md-select" >
+      </select>
       <span class="md-select-underline"></span>
     </div>
   </template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.js b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.js
index 95cab00..bcd062d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.js
+++ b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.js
@@ -28,12 +28,9 @@
     },
 
     /**
-     * Accessibility label.
-     * @type {!string}
+     * ARIA-label for the selection menu.
      */
-    label: {
-      type: String,
-    },
+    ariaLabel: String,
   },
 
   /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_network.js b/chrome/browser/resources/chromeos/login/oobe_screen_network.js
index b3cc57d00..f63b0be14 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_network.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_network.js
@@ -43,7 +43,6 @@
 
       var languageList = loadTimeData.getValue('languageList');
       welcomeScreen.languages = languageList;
-      welcomeScreen.currentLanguage = Oobe.getSelectedTitle(languageList);
 
       var inputMethodsList = loadTimeData.getValue('inputMethodsList');
       welcomeScreen.keyboards = inputMethodsList;
@@ -184,7 +183,6 @@
       if (useMDOobe) {
         var welcomeScreen = $('oobe-welcome-md');
         var languageList = loadTimeData.getValue('languageList');
-        welcomeScreen.currentLanguage = Oobe.getSelectedTitle(languageList);
         welcomeScreen.languages = languageList;
 
         welcomeScreen.keyboards = loadTimeData.getValue('inputMethodsList');
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html
index 5ab6782..8797fdd 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -81,7 +81,8 @@
             </div>
             <oobe-i18n-dropdown id="languageSelect" items="[[languages]]"
                 on-select-item="onLanguageSelected_"
-                label="$i18n{languageDropdownTitle}">
+                aria-label="[[formatMessage_('languageDropdownLabel',
+                    currentLanguage)]]">
             </oobe-i18n-dropdown>
           </div>
           <div id="keyboardDropdownContainer"
@@ -91,7 +92,8 @@
             </div>
             <oobe-i18n-dropdown id="keyboardSelect" items="[[keyboards]]"
                 on-select-item="onKeyboardSelected_"
-                label="$i18n{keyboardDropdownTitle}">
+                aria-label="[[formatMessage_('keyboardDropdownLabel',
+                    currentKeyboard)]]">
             </oobe-i18n-dropdown>
           </div>
         </template>
@@ -112,35 +114,40 @@
       <div class="footer layout vertical">
         <oobe-a11y-option checked="[[a11yStatus.spokenFeedbackEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableSpokenFeedback">
+            chrome-message="enableSpokenFeedback"
+            aria-label="$i18n{spokenFeedbackOption}">
           <span class="title">$i18n{spokenFeedbackOption}</span>
           <span class="checked-value">$i18n{spokenFeedbackOptionOn}</span>
           <span class="unchecked-value">$i18n{spokenFeedbackOptionOff}</span>
         </oobe-a11y-option>
         <oobe-a11y-option checked="[[a11yStatus.largeCursorEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableLargeCursor">
+            chrome-message="enableLargeCursor"
+            aria-label="$i18n{largeCursorOption}">
           <span class="title">$i18n{largeCursorOption}</span>
           <span class="checked-value">$i18n{largeCursorOptionOn}</span>
           <span class="unchecked-value">$i18n{largeCursorOptionOff}</span>
         </oobe-a11y-option>
         <oobe-a11y-option checked="[[a11yStatus.highContrastEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableHighContrast">
+            chrome-message="enableHighContrast"
+            aria-label="$i18n{highContrastOption}">
           <span class="title">$i18n{highContrastOption}</span>
           <span class="checked-value">$i18n{highContrastOptionOn}</span>
           <span class="unchecked-value">$i18n{highContrastOptionOff}</span>
         </oobe-a11y-option>
         <oobe-a11y-option checked="[[a11yStatus.screenMagnifierEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableScreenMagnifier">
+            chrome-message="enableScreenMagnifier"
+            aria-label="$i18n{screenMagnifierOption}">
           <span class="title">$i18n{screenMagnifierOption}</span>
           <span class="checked-value">$i18n{screenMagnifierOptionOn}</span>
           <span class="unchecked-value">$i18n{screenMagnifierOptionOff}</span>
         </oobe-a11y-option>
         <oobe-a11y-option checked="[[a11yStatus.virtualKeyboardEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableVirtualKeyboard">
+            chrome-message="enableVirtualKeyboard"
+            aria-label="$i18n{virtualKeyboardOption}">
           <span class="title">$i18n{virtualKeyboardOption}</span>
           <span class="checked-value">$i18n{virtualKeyboardOptionOn}</span>
           <span class="unchecked-value">$i18n{virtualKeyboardOptionOff}</span>
@@ -165,7 +172,7 @@
           </div>
           <oobe-i18n-dropdown id="timezoneSelect" items="[[timezones]]"
               on-select-item="onTimezoneSelected_"
-              label="$i18n{timezoneDropdownTitle}">
+              aria-label="$i18n{timezoneDropdownTitle}">
           </oobe-i18n-dropdown>
         </div>
       </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js
index 434a096..b0b048d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.js
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -19,11 +19,20 @@
     },
 
     /**
+     * Currently selected input method (display name).
+     */
+    currentKeyboard: {
+      type: String,
+      value: '',
+    },
+
+    /**
      * List of languages for language selector dropdown.
      * @type {!Array<OobeTypes.LanguageDsc>}
      */
     languages: {
       type: Array,
+      observer: "onLanguagesChanged_",
     },
 
     /**
@@ -32,6 +41,7 @@
      */
     keyboards: {
       type: Array,
+      observer: "onKeyboardsChanged_",
     },
 
     /**
@@ -115,7 +125,7 @@
     isConnected_: {
       type: Boolean,
       value: false,
-    }
+    },
   },
 
   /** @override */
@@ -390,6 +400,7 @@
   onLanguageSelected_: function(event) {
     var item = event.detail;
     var languageId = item.value;
+    this.currentLanguage = item.title;
     this.screen.onLanguageSelected_(languageId);
   },
 
@@ -402,9 +413,18 @@
   onKeyboardSelected_: function(event) {
     var item = event.detail;
     var inputMethodId = item.value;
+    this.currentKeyboard = item.title;
     this.screen.onKeyboardSelected_(inputMethodId);
   },
 
+  onLanguagesChanged_: function() {
+    this.currentLanguage = Oobe.getSelectedTitle(this.languages);
+  },
+
+  onKeyboardsChanged_: function() {
+    this.currentKeyboard = Oobe.getSelectedTitle(this.keyboards);
+  },
+
   /**
    * Handle "OK" button for "LanguageSelection" screen.
    *
@@ -465,4 +485,14 @@
 
     this.screen.onTimezoneSelected_(item.value);
   },
+
+  /**
+    * This function formats message for labels.
+    * @param String label i18n string ID.
+    * @param String parameter i18n string parameter.
+    * @private
+    */
+  formatMessage_: function(label, parameter) {
+    return loadTimeData.getStringF(label, parameter);
+  },
 });
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
index bd86828..6b2eacb05 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.html
@@ -21,7 +21,9 @@
         <div class="flex"></div>
         <div id="buttons" class="layout horizontal center">
           <oobe-welcome-secondary-button icon="icons:language"
-              on-tap="onLanguageClicked_">
+              on-tap="onLanguageClicked_"
+              aria-label="[[formatMessage_('languageButtonLabel',
+                  currentLanguage)]]">
             <div>[[currentLanguage]]</div>
           </oobe-welcome-secondary-button>
           <oobe-welcome-secondary-button icon="icons:accessibility"
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js
index 87cc78a6..da888ec 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.js
@@ -35,5 +35,15 @@
 
   onNextClicked_: function() {
     this.fire('next-button-clicked');
-  }
+  },
+
+  /**
+    * This function formats message for labels.
+    * @param String label i18n string ID.
+    * @param String parameter i18n string parameter.
+    * @private
+    */
+  formatMessage_: function(label, parameter) {
+    return loadTimeData.getStringF(label, parameter);
+  },
 });
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css
index 4333dd2f..40493ba1 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -37,6 +37,10 @@
   width: 272px;
 }
 
+.non-google-page #logo {
+  display: none;
+}
+
 body.alternate-logo #logo {
   -webkit-mask-image:
       url(../../../../ui/webui/resources/images/google_logo.svg);
@@ -63,6 +67,10 @@
   width: 298px;
 }
 
+.non-google-page #fakebox {
+  display: none;
+}
+
 #fakebox:hover {
   border: 1px solid rgb(169, 169, 169);
   border-top-color: rgb(144, 144, 144);
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html
index 8db15c74..954d700 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.html
+++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -13,8 +13,15 @@
 </head>
 <body>
   <div id="ntp-contents">
+    <div id="logo" title="Google"></div>
+    <div id="fakebox">
+      <div id="fakebox-text"></div>
+      <input id="fakebox-input" autocomplete="off" tabIndex="-1" type="url"
+          aria-hidden="true">
+      <div id="cursor"></div>
+    </div>
     <div id="most-visited">
-      <!-- The container for the tiles. The iframe goes in here. -->
+      <!-- The container for the tiles. The MV iframe goes in here. -->
       <div id="mv-tiles"></div>
       <!-- Notification shown when a tile is blacklisted. -->
       <div id="mv-notice" class="mv-notice-hide">
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index 9534ed32..f4b3870 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -124,6 +124,7 @@
   NTP_CONTENTS: 'ntp-contents',
   RESTORE_ALL_LINK: 'mv-restore',
   TILES: 'mv-tiles',
+  TILES_IFRAME: 'mv-single',
   UNDO_LINK: 'mv-undo'
 };
 
@@ -244,15 +245,6 @@
  * @private
  */
 function renderTheme() {
-  var fakeboxText = $(IDS.FAKEBOX_TEXT);
-  if (fakeboxText) {
-    fakeboxText.innerHTML = '';
-    if (configData.translatedStrings.searchboxPlaceholder) {
-      fakeboxText.textContent =
-          configData.translatedStrings.searchboxPlaceholder;
-    }
-  }
-
   var info = ntpApiHandle.themeBackgroundInfo;
   var isThemeDark = getIsThemeDark(info);
   ntpContents.classList.toggle(CLASSES.DARK, isThemeDark);
@@ -271,6 +263,7 @@
   updateThemeAttribution(info.attributionUrl, info.imageHorizontalAlignment);
   setCustomThemeStyle(info);
 
+  // Inform the most visited iframe of the new theme.
   var themeinfo = {cmd: 'updateTheme'};
   if (!info.usingDefaultTheme) {
     themeinfo.tileBorderColor = convertToRGBAColor(info.sectionBorderColorRgba);
@@ -286,7 +279,7 @@
   }
   themeinfo.tileTitleColor = convertToRGBAColor(titleColor);
 
-  $('mv-single').contentWindow.postMessage(themeinfo, '*');
+  $(IDS.TILES_IFRAME).contentWindow.postMessage(themeinfo, '*');
 }
 
 
@@ -423,7 +416,7 @@
   }
   cmds.push({cmd: 'show', maxVisible: numColumnsShown * NUM_ROWS});
 
-  $('mv-single').contentWindow.postMessage(cmds, '*');
+  $(IDS.TILES_IFRAME).contentWindow.postMessage(cmds, '*');
 }
 
 
@@ -514,7 +507,7 @@
  */
 function onResize() {
   updateContentWidth();
-  $('mv-single').contentWindow.postMessage(
+  $(IDS.TILES_IFRAME).contentWindow.postMessage(
     {cmd: 'tilesVisible', maxVisible: numColumnsShown * NUM_ROWS}, '*');
 }
 
@@ -634,21 +627,7 @@
   ntpContents = $(IDS.NTP_CONTENTS);
 
   if (configData.isGooglePage) {
-    var logo = document.createElement('div');
-    logo.id = IDS.LOGO;
-    logo.title = 'Google';
-
-    fakebox = document.createElement('div');
-    fakebox.id = IDS.FAKEBOX;
-    var fakeboxHtml = [];
-    fakeboxHtml.push('<div id="' + IDS.FAKEBOX_TEXT + '"></div>');
-    fakeboxHtml.push('<input id="' + IDS.FAKEBOX_INPUT +
-        '" autocomplete="off" tabindex="-1" type="url" aria-hidden="true">');
-    fakeboxHtml.push('<div id="cursor"></div>');
-    fakebox.innerHTML = fakeboxHtml.join('');
-
-    ntpContents.insertBefore(fakebox, ntpContents.firstChild);
-    ntpContents.insertBefore(logo, ntpContents.firstChild);
+    fakebox = $(IDS.FAKEBOX);
   } else {
     document.body.classList.add(CLASSES.NON_GOOGLE_PAGE);
   }
@@ -656,8 +635,7 @@
   // Hide notifications after fade out, so we can't focus on links via keyboard.
   notification.addEventListener('webkitTransitionEnd', hideNotification);
 
-  var notificationMessage = $(IDS.NOTIFICATION_MESSAGE);
-  notificationMessage.textContent =
+  $(IDS.NOTIFICATION_MESSAGE).textContent =
       configData.translatedStrings.thumbnailRemovedNotification;
 
   var undoLink = $(IDS.UNDO_LINK);
@@ -694,6 +672,9 @@
   searchboxApiHandle = topLevelHandle.searchBox;
 
   if (fakebox) {
+    $(IDS.FAKEBOX_TEXT).textContent =
+        configData.translatedStrings.searchboxPlaceholder;
+
     // Listener for updating the key capture state.
     document.body.onmousedown = function(event) {
       if (isFakeboxClick(event))
@@ -705,29 +686,27 @@
       setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled);
     };
     var inputbox = $(IDS.FAKEBOX_INPUT);
-    if (inputbox) {
-      inputbox.onpaste = function(event) {
-        event.preventDefault();
-        // Send pasted text to Omnibox.
-        var text = event.clipboardData.getData('text/plain');
-        if (text)
-          searchboxApiHandle.paste(text);
-      };
-      inputbox.ondrop = function(event) {
-        event.preventDefault();
-        var text = event.dataTransfer.getData('text/plain');
-        if (text) {
-          searchboxApiHandle.paste(text);
-        }
-        setFakeboxDragFocus(false);
-      };
-      inputbox.ondragenter = function() {
-        setFakeboxDragFocus(true);
-      };
-      inputbox.ondragleave = function() {
-        setFakeboxDragFocus(false);
-      };
-    }
+    inputbox.onpaste = function(event) {
+      event.preventDefault();
+      // Send pasted text to Omnibox.
+      var text = event.clipboardData.getData('text/plain');
+      if (text)
+        searchboxApiHandle.paste(text);
+    };
+    inputbox.ondrop = function(event) {
+      event.preventDefault();
+      var text = event.dataTransfer.getData('text/plain');
+      if (text) {
+        searchboxApiHandle.paste(text);
+      }
+      setFakeboxDragFocus(false);
+    };
+    inputbox.ondragenter = function() {
+      setFakeboxDragFocus(true);
+    };
+    inputbox.ondragleave = function() {
+      setFakeboxDragFocus(false);
+    };
 
     // Update the fakebox style to match the current key capturing state.
     setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled);
@@ -741,11 +720,7 @@
     document.documentElement.classList.add(CLASSES.RTL);
   }
 
-  var iframe = document.createElement('iframe');
-  // Change the order of tabbing the page to start with NTP tiles.
-  iframe.setAttribute('tabindex', '1');
-  iframe.id = 'mv-single';
-
+  // Pass arguments to the most visited iframe.
   var args = [];
 
   if (searchboxApiHandle.rtl)
@@ -756,6 +731,10 @@
   args.push('removeTooltip=' +
       encodeURIComponent(configData.translatedStrings.removeThumbnailTooltip));
 
+  // Create the most visited iframe.
+  var iframe = document.createElement('iframe');
+  iframe.id = IDS.TILES_IFRAME;
+  iframe.tabIndex = 1;
   iframe.src = '//most-visited/single.html?' + args.join('&');
   $(IDS.TILES).appendChild(iframe);
 
diff --git a/chrome/browser/resources/md_bookmarks/PRESUBMIT.py b/chrome/browser/resources/md_bookmarks/PRESUBMIT.py
deleted file mode 100644
index 1b816b29..0000000
--- a/chrome/browser/resources/md_bookmarks/PRESUBMIT.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(
-      input_api, output_api, check_js=True)
diff --git a/chrome/browser/resources/options/content_settings.html b/chrome/browser/resources/options/content_settings.html
index 0f49085..c66fc23e 100644
--- a/chrome/browser/resources/options/content_settings.html
+++ b/chrome/browser/resources/options/content_settings.html
@@ -304,31 +304,39 @@
         </div>
       </div>
     </section>
-<if expr="chromeos or is_win">
     <!-- Protected Content filter -->
     <section guest-visibility="disabled">
       <h3 i18n-content="protectedContentTabLabel"
           class="content-settings-header"></h3>
       <div>
+        <div class="checkbox">
+          <label>
+            <input pref="webkit.webprefs.encrypted_media_enabled"
+                type="checkbox">
+            <span i18n-content="protectedContentEnableCheckbox"></span>
+          </label>
+        </div>
+<if expr="chromeos or is_win">
         <div class="settings-row">
           <p i18n-content="protectedContentInfo"></p>
         </div>
         <div class="checkbox">
           <label>
             <input pref="settings.privacy.drm_enabled" type="checkbox">
-            <span i18n-content="protectedContentEnable"></span>
+            <span i18n-content="protectedContentEnableIdentifiersCheckbox">
+            </span>
           </label>
         </div>
-  <if expr="chromeos">
+</if>
+<if expr="chromeos">
         <div class="settings-row">
           <button id="protected-content-exceptions"
               class="exceptions-list-button" contentType="protectedContent"
               i18n-content="manageExceptions"></button>
         </div>
-  </if>
+</if>
       </div>
     </section>
-</if>
     <!-- Microphone filter -->
     <section id="media-stream-mic">
       <h3 i18n-content="mediaStreamMicTabLabel"></h3>
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js
index d4b57a1d..69ca087366 100644
--- a/chrome/browser/resources/print_preview/native_layer.js
+++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -306,13 +306,13 @@
         'generateDraftData': documentInfo.isModifiable,
         'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
         'scaleFactor': printTicketStore.scaling.getValueAsNumber(),
-        'rasterizePDF': printTicketStore.rasterize.getValue(),
         // NOTE: Even though the following fields don't directly relate to the
         // preview, they still need to be included.
         'duplex': printTicketStore.duplex.getValue() ?
             NativeLayer.DuplexMode.LONG_EDGE : NativeLayer.DuplexMode.SIMPLEX,
         'copies': 1,
         'collate': true,
+        'rasterizePDF': false,
         'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),
         'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue()
       };
diff --git a/chrome/browser/resources/print_preview/preview_generator.js b/chrome/browser/resources/print_preview/preview_generator.js
index 39c6d697..8313ed73 100644
--- a/chrome/browser/resources/print_preview/preview_generator.js
+++ b/chrome/browser/resources/print_preview/preview_generator.js
@@ -86,13 +86,6 @@
     this.colorValue_ = false;
 
     /**
-     * Whether the document should be printed as a raster PDF.
-     * @type {boolean}
-     * @private
-     */
-    this.rasterizeValue_ = false;
-
-    /**
      * Whether the document should be fitted to the page.
      * @type {boolean}
      * @private
@@ -191,7 +184,6 @@
       this.isHeaderFooterEnabled_ =
           this.printTicketStore_.headerFooter.getValue();
       this.colorValue_ = this.printTicketStore_.color.getValue();
-      this.rasterizeValue_ = this.printTicketStore_.rasterize.getValue();
       this.isFitToPageEnabled_ = this.printTicketStore_.fitToPage.getValue();
       this.scalingValue_ = this.printTicketStore_.scaling.getValueAsNumber();
       this.pageRanges_ = this.printTicketStore_.pageRange.getPageRanges();
@@ -292,7 +284,6 @@
           !ticketStore.landscape.isValueEqual(this.isLandscapeEnabled_) ||
           !ticketStore.headerFooter.isValueEqual(this.isHeaderFooterEnabled_) ||
           !ticketStore.color.isValueEqual(this.colorValue_) ||
-          !ticketStore.rasterize.isValueEqual(this.rasterizeValue_) ||
           !ticketStore.scaling.isValueEqual(this.scalingValue_) ||
           !ticketStore.fitToPage.isValueEqual(this.isFitToPageEnabled_) ||
           this.pageRanges_ == null ||
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
index b8d8010..c4790f7f 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
@@ -6,7 +6,6 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
 <link rel="import" href="../bluetooth_page/bluetooth_device_list_item.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -25,11 +24,6 @@
         margin-top: 10px;
       }
 
-      paper-spinner {
-        @apply(--cr-icon-height-width);
-        margin: 0 10px;
-      }
-
       .dialog-message {
         margin-bottom: 10px;
       }
@@ -79,28 +73,6 @@
       <div class="title">$i18n{bluetoothPairDevicePageTitle}</div>
       <div class="body">
         <div class="contents layout vertical center center-justified">
-          <!-- Note: dialog + dom-if + iron-list makes sizing complicated so use
-               hidden here; this is almost always the first dialog shown. -->
-          <div id="dialogDeviceList"
-              hidden$="[[!isDialogType_(dialogId, 'addDevice')]]"
-              class="layout vertical flex start self-stretch">
-            <span class="no-devices"
-                hidden$="[[haveUnpaired_(unpairedDeviceList_)]]">
-              $i18n{bluetoothNoDevices}
-            </span>
-            <div id="container" class="layout vertical flex self-stretch"
-                scrollable>
-              <iron-list id="devices" items="[[unpairedDeviceList_]]"
-                  selection-enabled selected-item="{{selectedItem_}}"
-                  scroll-target="container">
-                <template>
-                  <bluetooth-device-list-item device="[[item]]"
-                      tabindex$="[[tabIndex]]">
-                  </bluetooth-device-list-item>
-                </template>
-              </iron-list>
-            </div>
-          </div>
           <template is="dom-if" if="[[isDialogType_(dialogId, 'pairDevice')]]">
             <div id="pairing" class="settings-box first layout vertical center
                 center-justified">
@@ -141,17 +113,6 @@
         </div>
       </div>
       <div class="button-container">
-        <template is="dom-if" if="[[isDialogType_('addDevice', dialogId)]]">
-          <div id="scanning" class="layout horizontal center flex"
-              hidden$="[[!adapterState.discovering]]">
-            <paper-spinner active="[[adapterState.discovering]]">
-            </paper-spinner>
-            <span>$i18n{bluetoothScanning}</span>
-          </div>
-          <paper-button class="end-justified" on-tap="onCancelTap_">
-            $i18n{cancel}
-          </paper-button>
-        </template>
         <template is="dom-if" if="[[isDialogType_('pairDevice', dialogId)]]">
           <paper-button hidden$="[[!showAcceptReject_(pairingEvent_)]]"
               on-tap="onAcceptTap_">$i18n{bluetoothAccept}</paper-button>
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.js
index 267bf91..5795dce 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.js
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.js
@@ -6,106 +6,10 @@
 
 var PairingEventType = chrome.bluetoothPrivate.PairingEventType;
 
-// NOTE(dbeam): even though these behaviors are only used privately, they must
+// NOTE(dbeam): even though this behavior is only used privately, it must
 // be globally accessible for Closure's --polymer_pass to compile happily.
 
 /** @polymerBehavior */
-settings.BluetoothAddDeviceBehavior = {
-  properties: {
-    /**
-     * The cached bluetooth adapter state.
-     * @type {!chrome.bluetooth.AdapterState|undefined}
-     */
-    adapterState: {
-      type: Object,
-      observer: 'adapterStateChanged_',
-    },
-
-    /**
-     * The ordered list of bluetooth devices.
-     * @type {!Array<!chrome.bluetooth.Device>}
-     */
-    deviceList: {
-      type: Array,
-      value: /** @return {Array} */ function() {
-        return [];
-      },
-    },
-
-    /**
-     * The ordered list of unpaired bluetooth devices.
-     * @type {!Array<!chrome.bluetooth.Device>}
-     */
-    unpairedDeviceList_: {
-      type: Array,
-      value: /** @return {Array} */ function() {
-        return [];
-      },
-    },
-
-    /**
-     * Reflects the iron-list selecteditem property.
-     * @type {!chrome.bluetooth.Device}
-     */
-    selectedItem_: {
-      type: Object,
-      observer: 'selectedItemChanged_',
-    },
-  },
-
-  observers: ['deviceListChanged_(deviceList.*)'],
-
-  /** @type {boolean} */
-  itemWasFocused_: false,
-
-  /** @private */
-  adapterStateChanged_: function() {
-    if (!this.adapterState.powered)
-      this.close();
-  },
-
-  /** @private */
-  deviceListChanged_: function() {
-    this.saveScroll(this.$.devices);
-    this.unpairedDeviceList_ = this.deviceList.filter(function(device) {
-      return !device.paired;
-    });
-    this.updateScrollableContents();
-    this.restoreScroll(this.$.devices);
-
-    if (this.itemWasFocused_ || !this.unpairedDeviceList_.length)
-      return;
-    // If the iron-list is populated with at least one visible item then
-    // focus it.
-    var item = this.$$('iron-list bluetooth-device-list-item');
-    if (item && item.offsetParent != null) {
-      item.focus();
-      this.itemWasFocused_ = true;
-      return;
-    }
-    // Otherwise try again.
-    setTimeout(function() {
-      this.deviceListChanged_();
-    }.bind(this), 100);
-  },
-
-  /** @private */
-  selectedItemChanged_: function() {
-    if (!this.selectedItem_)
-      return;
-    this.fire('device-event', {action: 'connect', device: this.selectedItem_});
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  haveUnpaired_: function() {
-    return this.unpairedDeviceList_.length > 0;
-  },
-};
-
-/** @polymerBehavior */
 settings.BluetoothPairDeviceBehavior = {
   properties: {
     /**
@@ -200,7 +104,8 @@
   /** @private */
   pairingChanged_: function() {
     // Auto-close the dialog when pairing completes.
-    if (this.pairingDevice.connected) {
+    if (this.pairingDevice.paired && !this.pairingDevice.connecting &&
+        this.pairingDevice.connected) {
       this.close();
       return;
     }
@@ -426,14 +331,13 @@
   behaviors: [
     I18nBehavior,
     CrScrollableBehavior,
-    settings.BluetoothAddDeviceBehavior,
     settings.BluetoothPairDeviceBehavior,
   ],
 
   properties: {
     /**
-     * The version of this dialog to show: 'addDevice', 'pairDevice', or
-     * 'connectError'. Must be set before the dialog is opened.
+     * The version of this dialog to show: 'pairDevice', or 'connectError'.
+     * Must be set before the dialog is opened.
      */
     dialogId: String,
   },
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
index 4e67e5e..cdcd55a 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../icons.html">
 <link rel="import" href="../prefs/prefs.html">
@@ -18,29 +19,36 @@
     </style>
     <settings-animated-pages id="pages" section="bluetooth">
       <neon-animatable route-path="default">
-        <div class="settings-box first" actionable on-tap="onTap_">
+        <div class="settings-box two-line" actionable on-tap="onTap_">
           <iron-icon icon="[[getIcon_(bluetoothEnabled_)]]"></iron-icon>
-          <span class="middle">[[getTitle_(bluetoothEnabled_)]]</span>
+          <div class="middle">
+            <div>$i18n{bluetoothPageTitle}</div>
+            <div class="secondary">[[getDescription_(bluetoothEnabled_)]]</div>
+          </div>
           <cr-policy-pref-indicator
               pref="[[prefs.cros.device.allow_bluetooth]]"
-              hidden="[[prefs.cros.device.allow_bluetooth.value]]">
+            hidden="[[prefs.cros.device.allow_bluetooth.value]]">
           </cr-policy-pref-indicator>
           <button class="subpage-arrow" is="paper-icon-button-light"
               on-tap="onSubpageArrowTap_">
           </button>
+          <div class="secondary-action">
+            <paper-toggle-button id="enableBluetooth"
+                checked="{{bluetoothEnabled_}}"
+                disabled="[[!adapterState_.available]]" on-tap="stopTap_">
+            </paper-toggle-button>
+          </div>
         </div>
       </neon-animatable>
 
       <template is="dom-if" route-path="/bluetoothDevices">
         <settings-subpage associated-control="[[$$('#bluetoothDevices')]]"
-            page-title="$i18n{bluetoothPageTitle}"
-            show-spinner="[[showSpinner_]]">
+            page-title="$i18n{bluetoothPageTitle}">
           <settings-bluetooth-subpage 
               adapter-state="[[adapterState_]]"
               bluetooth-enabled="{{bluetoothEnabled_}}"
               bluetooth="[[bluetooth]]"
-              bluetooth-private="[[bluetoothPrivate]]"
-              show-spinner="{{showSpinner_}}">
+              bluetooth-private="[[bluetoothPrivate]]">
           </settings-bluetooth-subpage>
         </settings-subpage>
       </template>
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
index f7759a3..8fbd23c 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -42,16 +42,6 @@
     },
 
     /**
-     * Set by bluetooth-subpage to controll spinner visibilit in the header.
-     * @private
-     */
-    showSpinner_: {
-      type: Boolean,
-      notify: true,
-      value: false,
-    },
-
-    /**
      * The cached bluetooth adapter state.
      * @type {!chrome.bluetooth.AdapterState|undefined}
      * @private
@@ -132,7 +122,7 @@
    * @return {string}
    * @private
    */
-  getTitle_: function() {
+  getDescription_: function() {
     return this.i18n(
         this.bluetoothEnabled_ ? 'bluetoothEnabled' : 'bluetoothDisabled');
   },
@@ -161,6 +151,14 @@
    * @param {Event} e
    * @private
    */
+  stopTap_: function(e) {
+    e.stopPropagation();
+  },
+
+  /**
+   * @param {Event} e
+   * @private
+   */
   onSubpageArrowTap_: function(e) {
     this.openSubpage_();
     e.stopPropagation();
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
index 3b1368f..0517e8b 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
@@ -3,48 +3,52 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
-<link rel="import" href="/icons.html">
-<link rel="import" href="/settings_shared_css.html">
+<link rel="import" href="../icons.html">
+<link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="bluetooth_device_dialog.html">
 <link rel="import" href="bluetooth_device_list_item.html">
 
 <dom-module id="settings-bluetooth-subpage">
   <template>
     <style include="settings-shared">
-      #container {
+      .container {
         @apply(--settings-list-frame-padding);
-        min-height: 100px;
+        min-height: 10px;
         overflow-y: auto;
       }
 
-      #pairButton {
-        margin: 0
+      .header {
+        margin-top: 10px;
       }
 
-      #topRow {
-        margin-bottom: 10px;
+      paper-spinner {
+        @apply(--cr-icon-height-width);
       }
     </style>
 
-    <div id="topRow" class="settings-box first">
+    <div class="settings-box first">
       <div class="start">[[getOffOnString_(bluetoothEnabled)]]</div>
-      <paper-button id="pairButton" class="primary-button"
-          on-tap="onAddDeviceTap_" hidden="[[!bluetoothEnabled]]">
-        $i18n{bluetoothPairDevice}
-      </paper-button>
       <paper-toggle-button id="enableBluetooth" checked="{{bluetoothEnabled}}">
       </paper-toggle-button>
     </div>
 
-    <div id="container" class="layout vertical"
+    <!-- Paired device list -->
+    <div class="settings-box first header" hidden$="[[!bluetoothEnabled]]">
+      <div class="start">$i18n{bluetoothDeviceListPaired}</div>
+    </div>
+    <div id="noPairedDevices" class="list-frame"
+        hidden$="[[!showNoDevices_(bluetoothEnabled, pairedDeviceList_)]]">
+      $i18n{bluetoothNoDevices}
+    </div>
+    <div id="pairedContainer" class="container layout vertical"
         scrollable on-device-event="onDeviceEvent_"
         hidden="[[!showDevices_(bluetoothEnabled, pairedDeviceList_)]]">
-      <iron-list id="devices" class="vertical-list"
+      <iron-list id="pairedDevices" class="vertical-list"
           items="[[pairedDeviceList_]]"
-          selection-enabled selected-item="{{selectedItem_}}"
-          scroll-target="container">
+          selection-enabled selected-item="{{selectedPairedItem_}}"
+          scroll-target="pairedContainer">
         <template>
           <bluetooth-device-list-item device="[[item]]"
               tabindex$="[[tabIndex]]">
@@ -52,15 +56,34 @@
         </template>
       </iron-list>
     </div>
-    <div id="noDevices" class="settings-box continuation"
-        hidden$="[[!showNoDevices_(bluetoothEnabled, pairedDeviceList_)]]">
-      $i18n{bluetoothNoDevices}
+
+    <!-- Unpaired device list -->
+    <div class="settings-box first header" hidden$="[[!bluetoothEnabled]]">
+      <div class="start">$i18n{bluetoothDeviceListUnpaired}</div>
+      <paper-spinner active="[[showSpinner_]]">
+      </paper-spinner>
+    </div>
+    <div id="noUnpairedDevices" class="list-frame"
+        hidden$="[[!showNoDevices_(bluetoothEnabled, unpairedDeviceList_)]]">
+      $i18n{bluetoothNoDevicesFound}
+    </div>
+    <div id="unpairedContainer" class="container layout vertical"
+        scrollable on-device-event="onDeviceEvent_"
+        hidden="[[!showDevices_(bluetoothEnabled, unpairedDeviceList_)]]">
+      <iron-list id="unpairedDevices" class="vertical-list"
+          items="[[unpairedDeviceList_]]"
+          selection-enabled selected-item="{{selectedUnpairedItem_}}"
+          scroll-target="unpairedContainer">
+        <template>
+          <bluetooth-device-list-item device="[[item]]"
+              tabindex$="[[tabIndex]]">
+          </bluetooth-device-list-item>
+        </template>
+      </iron-list>
     </div>
 
     <bluetooth-device-dialog id="deviceDialog"
-        adapter-state="[[adapterState]]"
         bluetooth-private="[[bluetoothPrivate]]"
-        device-list="[[deviceList_]]"
         dialog-id="[[dialogId_]]"
         error-message="[[errorMessage_]]"
         on-close="onDialogClosed_"
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
index d5fbf19..6af3802 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
@@ -8,15 +8,23 @@
  *  properties and devices.
  */
 
+// NOTE(dbeam): even though this behavior is only used privately, it must
+// be globally accessible for Closure's --polymer_pass to compile happily.
+
 Polymer({
   is: 'settings-bluetooth-subpage',
 
-  behaviors: [I18nBehavior, CrScrollableBehavior],
+  behaviors: [
+    I18nBehavior,
+    CrScrollableBehavior,
+    settings.RouteObserverBehavior,
+  ],
 
   properties: {
     /** Reflects the bluetooth-page property. */
     bluetoothEnabled: {
       type: Boolean,
+      observer: 'bluetoothEnabledChanged_',
       notify: true,
     },
 
@@ -27,10 +35,10 @@
     adapterState: Object,
 
     /** Informs bluetooth-page whether to show the spinner in the header. */
-    showSpinner: {
+    showSpinner_: {
       type: Boolean,
       notify: true,
-      computed: 'computeShowSpinner_(bluetoothEnabled, dialogId_)',
+      computed: 'computeShowSpinner_(adapterState.*, dialogId_)',
     },
 
     /**
@@ -61,17 +69,37 @@
      * @type {!chrome.bluetooth.Device}
      * @private
      */
-    selectedItem_: {
+    selectedPairedItem_: {
       type: Object,
-      observer: 'selectedItemChanged_',
+      observer: 'selectedPairedItemChanged_',
+    },
+
+    /**
+     * The ordered list of unpaired bluetooth devices.
+     * @type {!Array<!chrome.bluetooth.Device>}
+     */
+    unpairedDeviceList_: {
+      type: Array,
+      value: /** @return {Array} */ function() {
+        return [];
+      },
+    },
+
+    /**
+     * Reflects the iron-list selecteditem property.
+     * @type {!chrome.bluetooth.Device}
+     */
+    selectedUnpairedItem_: {
+      type: Object,
+      observer: 'selectedUnpairedItemChanged_',
     },
 
     /**
      * Set to the name of the dialog to show. This page uses a single
-     * paper-dialog to host one of three dialog elements, 'addDevice',
-     * 'pairDevice', or 'connectError'. This allows a seamless transition
-     * between dialogs. Note: This property should be set before opening the
-     * dialog and setting the property will not itself cause the dialog to open.
+     * paper-dialog to host one of two dialog elements: 'pairDevice' or
+     * 'connectError'. This allows a seamless transition between dialogs.
+     * Note: This property should be set before opening the dialog and setting
+     * the property will not itself cause the dialog to open.
      * @private
      */
     dialogId_: {
@@ -161,9 +189,23 @@
     }
   },
 
+  /**
+   * settings.RouteObserverBehavior
+   * @param {!settings.Route} route
+   * @protected
+   */
+  currentRouteChanged: function(route) {
+    if (route == settings.Route.BLUETOOTH_DEVICES) {
+      if (this.bluetoothEnabled)
+        this.startDiscovery_();
+    } else {
+      this.stopDiscovery_();
+    }
+  },
+
   /** @private */
   computeShowSpinner_: function() {
-    return this.bluetoothEnabled && !this.dialogId_;
+    return !this.dialogId_ && this.get('adapterState.discovering');
   },
 
   /** @private */
@@ -172,19 +214,40 @@
   },
 
   /** @private */
-  deviceListChanged_: function() {
-    this.saveScroll(this.$.devices);
-    this.pairedDeviceList_ = this.deviceList_.filter(function(device) {
-      return !!device.paired || !!device.connecting;
-    });
-    this.updateScrollableContents();
-    this.restoreScroll(this.$.devices);
+  bluetoothEnabledChanged_: function() {
+    if (settings.getCurrentRoute() == settings.Route.BLUETOOTH_DEVICES &&
+        this.bluetoothEnabled) {
+      this.startDiscovery_();
+    } else {
+      this.stopDiscovery_();
+    }
   },
 
   /** @private */
-  selectedItemChanged_: function() {
-    if (this.selectedItem_)
-      this.connectDevice_(this.selectedItem_);
+  deviceListChanged_: function() {
+    this.saveScroll(this.$.pairedDevices);
+    this.saveScroll(this.$.unpairedDevices);
+    this.pairedDeviceList_ = this.deviceList_.filter(function(device) {
+      return !!device.paired || !!device.connecting;
+    });
+    this.unpairedDeviceList_ = this.deviceList_.filter(function(device) {
+      return !device.paired;
+    });
+    this.updateScrollableContents();
+    this.restoreScroll(this.$.unpairedDevices);
+    this.restoreScroll(this.$.pairedDevices);
+  },
+
+  /** @private */
+  selectedPairedItemChanged_: function() {
+    if (this.selectedPairedItem_)
+      this.connectDevice_(this.selectedPairedItem_);
+  },
+
+  /** @private */
+  selectedUnpairedItemChanged_: function() {
+    if (this.selectedUnpairedItem_)
+      this.connectDevice_(this.selectedUnpairedItem_);
   },
 
   /**
@@ -268,15 +331,6 @@
   },
 
   /**
-   * @param {!Event} e
-   * @private
-   */
-  onAddDeviceTap_: function(e) {
-    e.preventDefault();
-    this.openDialog_('addDevice');
-  },
-
-  /**
    * @param {!{detail: {action: string, device: !chrome.bluetooth.Device}}} e
    * @private
    */
@@ -302,19 +356,23 @@
   },
 
   /**
+   * @param {boolean} bluetoothEnabled
+   * @param {!Array<!chrome.bluetooth.Device>} deviceList
    * @return {boolean}
    * @private
    */
-  showDevices_: function() {
-    return this.bluetoothEnabled && this.pairedDeviceList_.length > 0;
+  showDevices_: function(bluetoothEnabled, deviceList) {
+    return bluetoothEnabled && deviceList.length > 0;
   },
 
   /**
+   * @param {boolean} bluetoothEnabled
+   * @param {!Array<!chrome.bluetooth.Device>} deviceList
    * @return {boolean}
    * @private
    */
-  showNoDevices_: function() {
-    return this.bluetoothEnabled && this.pairedDeviceList_.length == 0;
+  showNoDevices_: function(bluetoothEnabled, deviceList) {
+    return bluetoothEnabled && deviceList.length == 0;
   },
 
   /**
@@ -334,9 +392,10 @@
         error = chrome.runtime.lastError.message;
       } else {
         switch (result) {
+          case chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS:
+            return;  // Do not close the dialog
           case chrome.bluetoothPrivate.ConnectResultType.ALREADY_CONNECTED:
           case chrome.bluetoothPrivate.ConnectResultType.AUTH_CANCELED:
-          case chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS:
           case chrome.bluetoothPrivate.ConnectResultType.SUCCESS:
             break;
           default:
@@ -404,12 +463,10 @@
     // Call flush so that the dialog gets sized correctly before it is opened.
     Polymer.dom.flush();
     this.$.deviceDialog.open();
-    this.startDiscovery_();
   },
 
   /** @private */
   onDialogClosed_: function() {
-    this.stopDiscovery_();
     this.dialogId_ = '';
     this.pairingDevice_ = undefined;
   },
diff --git a/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp b/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp
index 8930c77..0b5e5c8 100644
--- a/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp
@@ -20,6 +20,7 @@
     {
       'target_name': 'bluetooth_subpage',
       'dependencies': [
+        '../compiled_resources2.gyp:route',
         '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_scrollable_behavior',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
diff --git a/chrome/browser/resources/settings/device_page/device_page.html b/chrome/browser/resources/settings/device_page/device_page.html
index c0a6aa5..1665552 100644
--- a/chrome/browser/resources/settings/device_page/device_page.html
+++ b/chrome/browser/resources/settings/device_page/device_page.html
@@ -2,7 +2,6 @@
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="device_page_browser_proxy.html">
@@ -11,7 +10,6 @@
 <link rel="import" href="pointers.html">
 <link rel="import" href="storage.html">
 <link rel="import" href="stylus.html">
-<link rel="import" href="../icons.html">
 <link rel="import" href="../prefs/prefs.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_page/settings_animated_pages.html">
@@ -25,8 +23,6 @@
       <neon-animatable id="main" route-path="default">
         <div id="pointersRow" class="settings-box first"
             on-tap="onPointersTap_" actionable>
-          <iron-icon icon="[[getPointersIcon_(hasMouse_, hasTouchpad_)]]">
-          </iron-icon>
           <div class="middle">
             [[getPointersTitle_(hasMouse_, hasTouchpad_)]]
           </div>
@@ -34,33 +30,28 @@
         </div>
         <div id="keyboardRow" class="settings-box" on-tap="onKeyboardTap_"
             actionable>
-          <iron-icon icon="settings:keyboard"></iron-icon>
           <div class="middle">$i18n{keyboardTitle}</div>
           <button class="subpage-arrow" is="paper-icon-button-light"></button>
         </div>
         <template is="dom-if" if="[[hasStylus_]]">
           <div id="stylusRow" class="settings-box" on-tap="onStylusTap_"
               actionable>
-            <iron-icon icon="settings:note"></iron-icon>
             <div class="middle">$i18n{stylusTitle}</div>
           <button class="subpage-arrow" is="paper-icon-button-light"></button>
           </div>
         </template>
         <div id="displayRow" class="settings-box" on-tap="onDisplayTap_"
             actionable>
-          <iron-icon icon="settings:desktop-windows"></iron-icon>
           <div class="middle">$i18n{displayTitle}</div>
           <button class="subpage-arrow" is="paper-icon-button-light"></button>
         </div>
         <div id="storageRow" class="settings-box" on-tap="onStorageTap_"
             actionable>
-          <iron-icon icon="settings:storage"></iron-icon>
           <div class="middle">$i18n{storageTitle}</div>
           <button class="subpage-arrow" is="paper-icon-button-light"></button>
         </div>
         <template is="dom-if" if="[[enablePowerSettings_]]">
           <div id="powerRow" class="settings-box two-line">
-            <iron-icon icon="[[batteryIcon_]]"></iron-icon>
             <div class="middle">
               <div>[[powerLabel_]]</div>
               <div class="secondary">[[batteryStatus_.statusText]]</div>
diff --git a/chrome/browser/resources/settings/device_page/device_page.js b/chrome/browser/resources/settings/device_page/device_page.js
index 23a004e..ab3ad88 100644
--- a/chrome/browser/resources/settings/device_page/device_page.js
+++ b/chrome/browser/resources/settings/device_page/device_page.js
@@ -71,13 +71,6 @@
     powerSources_: Array,
 
     /** @private */
-    batteryIcon_: {
-      type: String,
-      computed: 'computeBatteryIcon_(batteryStatus_, lowPowerCharger_)',
-      value: 'settings:battery-unknown',
-    },
-
-    /** @private */
     powerLabel_: {
       type: String,
       computed: 'computePowerLabel_(powerSources_, batteryStatus_.calculating)',
@@ -140,18 +133,6 @@
   },
 
   /**
-   * @return {string}
-   * @private
-   */
-  getPointersIcon_: function() {
-    if (this.hasMouse_)
-      return 'settings:mouse';
-    if (this.hasTouchpad_)
-      return 'settings:touch-app';
-    return '';
-  },
-
-  /**
    * @param {*} lhs
    * @param {*} rhs
    * @return {boolean}
@@ -161,43 +142,6 @@
   },
 
   /**
-   * @param {!settings.BatteryStatus} batteryStatus
-   * @param {boolean} lowPowerCharger
-   * @return {string}
-   */
-  computeBatteryIcon_: function(batteryStatus, lowPowerCharger) {
-    var iconPrefix = 'settings:battery-';
-
-    if (batteryStatus.calculating)
-      return iconPrefix + 'unknown';
-
-    if (lowPowerCharger)
-      return iconPrefix + 'unreliable';
-
-    if (!batteryStatus.charging && batteryStatus.percent < 5)
-      return iconPrefix + 'alert';
-
-    // Compute the rest of the icon: iconPrefix + '[charging-]<percent>'.
-    if (batteryStatus.charging)
-      iconPrefix += 'charging-';
-
-    // Show the highest level icon that doesn't go over the actual percentage.
-    if (batteryStatus.percent < 30)
-      return iconPrefix + '20';
-    if (batteryStatus.percent < 50)
-      return iconPrefix + '30';
-    if (batteryStatus.percent < 60)
-      return iconPrefix + '50';
-    if (batteryStatus.percent < 80)
-      return iconPrefix + '60';
-    if (batteryStatus.percent < 90)
-      return iconPrefix + '80';
-    if (batteryStatus.percent < 100)
-      return iconPrefix + '90';
-    return iconPrefix + 'full';
-  },
-
-  /**
    * @param {!Array<!settings.PowerSource>|undefined} powerSources
    * @param {boolean} calculating
    * @return {string} The primary label for the power row.
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index 555db49..6c02d08 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -18,12 +18,6 @@
         <path fill="none" d="M1 1h22v22H1z"></path>
       </g>
 
-      <!-- Battery shell from Polymer plus unreliable badge from Ash. -->
-      <g id="battery-unreliable">
-        <path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"></path>
-        <path fill="#fff" d="M10.755 11.99c-.99.01-1.25.5-1.25.5v-.985S9.775 11 10.76 11c.985 0 1.5.975 2.525.975S14.5 11.5 14.5 11.5v.99s-.19.525-1.22.525-1.535-1.04-2.53-1.025z"></path>
-      </g>
-
       <!--
       These icons are copied from Polymer's iron-icons and kept in sorted order.
       See http://goo.gl/Y1OdAq for instructions on adding additional icons.
@@ -37,22 +31,6 @@
       <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g>
       <g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"></path></g>
 <if expr="chromeos">
-      <g id="battery-20"><path d="M7 17v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17H7z"></path><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h10V5.33z"></path></g>
-      <g id="battery-30"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V15h10V5.33z"></path><path d="M7 15v5.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V15H7z"></path></g>
-      <g id="battery-50"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V13h10V5.33z"></path><path d="M7 13v7.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13H7z"></path></g>
-      <g id="battery-60"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h10V5.33z"></path><path d="M7 11v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11H7z"></path></g>
-      <g id="battery-80"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h10V5.33z"></path><path d="M7 9v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9H7z"></path></g>
-      <g id="battery-90"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h10V5.33z"></path><path d="M7 8v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8H7z"></path></g>
-      <g id="battery-alert"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM13 18h-2v-2h2v2zm0-4h-2V9h2v5z"></path></g>
-      <g id="battery-charging-20"><path d="M11 20v-3H7v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17h-4.4L11 20z"></path><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h4v-2.5H9L13 7v5.5h2L12.6 17H17V5.33C17 4.6 16.4 4 15.67 4z"></path></g>
-      <g id="battery-charging-30"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v9.17h2L13 7v5.5h2l-1.07 2H17V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M11 20v-5.5H7v6.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V14.5h-3.07L11 20z"></path></g>
-      <g id="battery-charging-50"><path d="M14.47 13.5L11 20v-5.5H9l.53-1H7v7.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13.5h-2.53z"></path><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v8.17h2.53L13 7v5.5h2l-.53 1H17V5.33C17 4.6 16.4 4 15.67 4z"></path></g>
-      <g id="battery-charging-60"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h3.87L13 7v4h4V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M13 12.5h2L11 20v-5.5H9l1.87-3.5H7v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11h-4v1.5z"></path></g>
-      <g id="battery-charging-80"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h4.93L13 7v2h4V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M13 12.5h2L11 20v-5.5H9L11.93 9H7v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9h-4v3.5z"></path></g>
-      <g id="battery-charging-90"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h5.47L13 7v1h4V5.33C17 4.6 16.4 4 15.67 4z"></path><path d="M13 12.5h2L11 20v-5.5H9L12.47 8H7v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8h-4v4.5z"></path></g>
-      <g id="battery-charging-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM11 20v-5.5H9L13 7v5.5h2L11 20z"></path></g>
-      <g id="battery-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"></path></g>
-      <g id="battery-unknown"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zm-2.72 13.95h-1.9v-1.9h1.9v1.9zm1.35-5.26s-.38.42-.67.71c-.48.48-.83 1.15-.83 1.6h-1.6c0-.83.46-1.52.93-2l.93-.94c.27-.27.44-.65.44-1.06 0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5H9c0-1.66 1.34-3 3-3s3 1.34 3 3c0 .66-.27 1.26-.7 1.69z"></path></g>
       <g id="bluetooth"><path d="M17.71 7.71L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88z"></path></g>
       <g id="bluetooth-connected"><path d="M7 12l-2-2-2 2 2 2 2-2zm10.71-4.29L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88zM19 10l-2 2 2 2 2-2-2-2z"></path></g>
       <g id="bluetooth-disabled"><path d="M13 5.83l1.88 1.88-1.6 1.6 1.41 1.41 3.02-3.02L12 2h-1v5.03l2 2v-3.2zM5.41 4L4 5.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l4.29-4.29 2.3 2.29L20 18.59 5.41 4zM13 18.17v-3.76l1.88 1.88L13 18.17z"></path></g>
@@ -73,7 +51,6 @@
       <g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"></path></g>
 <if expr="chromeos">
       <g id="computer"><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"></path></g>
-      <g id="desktop-windows"><path d="M21 2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v2H8v2h8v-2h-2v-2h7c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H3V4h18v12z"></path></g>
 </if>
       <g id="done"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path></g>
       <g id="error"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></g>
@@ -100,7 +77,6 @@
 <if expr="chromeos">
       <g id="mouse"><path d="M13 1.07V9h7c0-4.08-3.05-7.44-7-7.93zM4 15c0 4.42 3.58 8 8 8s8-3.58 8-8v-4H4v4zm7-13.93C7.05 1.56 4 4.92 4 9h7V1.07z"></path></g>
       <g id="network-wifi"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"></path><path d="M3.53 10.95l8.46 10.54.01.01.01-.01 8.46-10.54C20.04 10.62 16.81 8 12 8c-4.81 0-8.04 2.62-8.47 2.95z"></path></g>
-      <g id="note"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"></path></g>
 </if>
       <g id="notifications"><path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"></path></g>
       <g id="pdf"><path d="M7 11.5h1v-1H7v1zM19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-9.5 8.5c0 .83-.67 1.5-1.5 1.5H7v2H5.5V9H8c.83 0 1.5.67 1.5 1.5v1zm10-1H17v1h1.5V13H17v2h-1.5V9h4v1.5zm-5 3c0 .83-.67 1.5-1.5 1.5h-2.5V9H13c.83 0 1.5.67 1.5 1.5v3zm-2.5 0h1v-3h-1v3z"></path><path fill="none" d="M0 0h24v24H0z"></path></g>
@@ -117,14 +93,12 @@
       <g id="sim-card-alert"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 15h-2v-2h2v2zm0-4h-2V8h2v5z"></path></g>
       <g id="smartphone"><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"></path></g>
 </if>
-      <g id="storage"><path d="M2 20h20v-4H2v4zm2-3h2v2H4v-2zM2 4v4h20V4H2zm4 3H4V5h2v2zm-4 7h20v-4H2v4zm2-3h2v2H4v-2z"></path></g>
       <g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 16.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.66 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"></path></g>
       <g id="sync"><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"></path></g>
       <g id="sync-disabled"><path d="M10 6.35V4.26c-.8.21-1.55.54-2.23.96l1.46 1.46c.25-.12.5-.24.77-.33zm-7.14-.94l2.36 2.36C4.45 8.99 4 10.44 4 12c0 2.21.91 4.2 2.36 5.64L4 20h6v-6l-2.24 2.24C6.68 15.15 6 13.66 6 12c0-1 .25-1.94.68-2.77l8.08 8.08c-.25.13-.5.25-.77.34v2.09c.8-.21 1.55-.54 2.23-.96l2.36 2.36 1.27-1.27L4.14 4.14 2.86 5.41zM20 4h-6v6l2.24-2.24C17.32 8.85 18 10.34 18 12c0 1-.25 1.94-.68 2.77l1.46 1.46C19.55 15.01 20 13.56 20 12c0-2.21-.91-4.2-2.36-5.64L20 4z"></path></g>
       <g id="sync-problem"><path d="M3 12c0 2.21.91 4.2 2.36 5.64L3 20h6v-6l-2.24 2.24C5.68 15.15 5 13.66 5 12c0-2.61 1.67-4.83 4-5.65V4.26C5.55 5.15 3 8.27 3 12zm8 5h2v-2h-2v2zM21 4h-6v6l2.24-2.24C18.32 8.85 19 10.34 19 12c0 2.61-1.67 4.83-4 5.65v2.09c3.45-.89 6-4.01 6-7.74 0-2.21-.91-4.2-2.36-5.64L21 4zm-10 9h2V7h-2v6z"></path></g>
 <if expr="chromeos">
       <g id="tablet"><path d="M21 4H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 1.99-.9 1.99-2L23 6c0-1.1-.9-2-2-2zm-2 14H5V6h14v12z"></path></g>
-      <g id="touch-app"><path d="M9 11.24V7.5C9 6.12 10.12 5 11.5 5S14 6.12 14 7.5v3.74c1.21-.81 2-2.18 2-3.74C16 5.01 13.99 3 11.5 3S7 5.01 7 7.5c0 1.56.79 2.93 2 3.74zm9.84 4.63l-4.54-2.26c-.17-.07-.35-.11-.54-.11H13v-6c0-.83-.67-1.5-1.5-1.5S10 6.67 10 7.5v10.74l-3.43-.72c-.08-.01-.15-.03-.24-.03-.31 0-.59.13-.79.33l-.79.8 4.94 4.94c.27.27.65.44 1.06.44h6.79c.75 0 1.33-.55 1.44-1.28l.75-5.27c.01-.07.02-.14.02-.2 0-.62-.38-1.16-.91-1.38z"></path></g>
 </if>
       <g id="usb"><path d="M15 7v4h1v2h-3V5h2l-3-4-3 4h2v8H8v-2.07c.7-.37 1.2-1.08 1.2-1.93 0-1.21-.99-2.2-2.2-2.2-1.21 0-2.2.99-2.2 2.2 0 .85.5 1.56 1.2 1.93V13c0 1.11.89 2 2 2h3v3.05c-.71.37-1.2 1.1-1.2 1.95 0 1.22.99 2.2 2.2 2.2 1.21 0 2.2-.98 2.2-2.2 0-.85-.49-1.58-1.2-1.95V15h3c1.11 0 2-.89 2-2v-2h1V7h-4z"></path></g>
       <g id="videocam"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"></path></g>
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html
index 76202229..85b8e7c 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -127,7 +127,7 @@
               </div>
             </template>
             <div class="list-item">
-              <a is="action-link" class="list-button"
+              <a is="action-link" class="list-button" id="addLanguages"
                   on-tap="onAddLanguagesTap_">
                 $i18n{addLanguages}
               </a>
@@ -179,6 +179,7 @@
             </template>
             <div class="list-item">
               <a is="action-link" class="list-button"
+                  id="manageInputMethods"
                   on-tap="onManageInputMethodsTap_">
                 $i18n{manageInputMethods}
               </a>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index c6c14a1e..4bf4624 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -203,6 +203,8 @@
             associated-control="[[$$('#site-settings-subpage-trigger')]]"
             id="site-settings"
             page-title="[[siteSettingsPageTitle_()]]">
+          <button class="icon-help subpage-title-extra"
+              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <settings-site-settings-page></settings-site-settings-page>
         </settings-subpage>
       </template>
@@ -214,8 +216,6 @@
       </template>
       <template is="dom-if" route-path="/content/automaticDownloads" no-search>
         <settings-subpage page-title="$i18n{siteSettingsAutomaticDownloads}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting
               toggle-off-label="$i18n{siteSettingsAutoDownloadBlock}"
               toggle-on-label="$i18n{siteSettingsAutoDownloadAskRecommended}"
@@ -228,8 +228,6 @@
       </template>
       <template is="dom-if" route-path="/content/backgroundSync" no-search>
         <settings-subpage page-title="$i18n{siteSettingsBackgroundSync}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting
               toggle-off-label="$i18n{siteSettingsBackgroundSyncBlocked}"
               toggle-on-label=
@@ -243,8 +241,6 @@
       </template>
       <template is="dom-if" route-path="/content/camera" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryCamera}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <media-picker type="camera"></media-picker>
           <category-default-setting category="{{ContentSettingsTypes.CAMERA}}"
               toggle-off-label="$i18n{siteSettingsBlocked}"
@@ -258,8 +254,6 @@
       </template>
       <template is="dom-if" route-path="/content/cookies" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryCookies}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting category="{{ContentSettingsTypes.COOKIES}}"
               toggle-off-label="$i18n{siteSettingsBlocked}"
               toggle-on-label="$i18n{siteSettingsCookiesAllowedRecommended}"
@@ -281,8 +275,6 @@
       </template>
       <template is="dom-if" route-path="/content/images" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryImages}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting category="{{ContentSettingsTypes.IMAGES}}"
               toggle-off-label="$i18n{siteSettingsDontShowImages}"
               toggle-on-label="$i18n{siteSettingsShowAllRecommended}">
@@ -294,8 +286,6 @@
       </template>
       <template is="dom-if" route-path="/content/location" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryLocation}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting
               toggle-off-label="$i18n{siteSettingsBlocked}"
               toggle-on-label="$i18n{siteSettingsAskBeforeAccessingRecommended}"
@@ -326,8 +316,6 @@
       </template>
       <template is="dom-if" route-path="/content/javascript" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryJavascript}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting
               toggle-off-label="$i18n{siteSettingsBlocked}"
               toggle-on-label="$i18n{siteSettingsAllowedRecommended}"
@@ -340,8 +328,6 @@
       </template>
       <template is="dom-if" route-path="/content/microphone" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryMicrophone}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <media-picker type="mic"></media-picker>
           <category-default-setting category="{{ContentSettingsTypes.MIC}}"
               toggle-off-label="$i18n{siteSettingsBlocked}"
@@ -354,8 +340,6 @@
       </template>
       <template is="dom-if" route-path="/content/notifications" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryNotifications}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting
               toggle-off-label="$i18n{siteSettingsBlocked}"
               toggle-on-label="$i18n{siteSettingsAskBeforeSendingRecommended}"
@@ -368,8 +352,6 @@
       </template>
       <template is="dom-if" route-path="/content/flash" no-search>
         <settings-subpage page-title="$i18n{siteSettingsFlash}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting category="{{ContentSettingsTypes.PLUGINS}}"
               toggle-off-label="$i18n{siteSettingsFlashBlock}"
               toggle-on-label="$i18n{siteSettingsFlashAllow}"
@@ -392,8 +374,6 @@
       </template>
       <template is="dom-if" route-path="/content/popups" no-search>
         <settings-subpage page-title="$i18n{siteSettingsCategoryPopups}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting category="{{ContentSettingsTypes.POPUPS}}"
               toggle-off-label="$i18n{siteSettingsBlockedRecommended}"
               toggle-on-label="$i18n{siteSettingsAllowed}">
@@ -405,8 +385,6 @@
       </template>
       <template is="dom-if" route-path="/content/unsandboxedPlugins" no-search>
         <settings-subpage page-title="$i18n{siteSettingsUnsandboxedPlugins}">
-          <button class="icon-help subpage-title-extra"
-              is="paper-icon-button-light" on-tap="onHelpTap_"></button>
           <category-default-setting
               toggle-off-label="$i18n{siteSettingsUnsandboxedPluginsBlock}"
               toggle-on-label=
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html
index 71ca0fb..76c37239 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.html
+++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -15,6 +15,10 @@
         margin-top: 64px;
       }
 
+      .showing-subpage ~ #overscroll {
+        display: none;
+      }
+
       #noSearchResults {
         align-items: center;
         display: flex;
diff --git a/chrome/browser/resources/settings/settings_page_css.html b/chrome/browser/resources/settings/settings_page_css.html
index 07b269d..6aa289e 100644
--- a/chrome/browser/resources/settings/settings_page_css.html
+++ b/chrome/browser/resources/settings/settings_page_css.html
@@ -16,7 +16,7 @@
       }
 
       :host(.showing-subpage) {
-        /* Set the height to the container height so the subpage scrolls. */
+        /* The subpage container should extend to the bottom of the page. */
         height: 100%;
       }
 
diff --git a/chrome/browser/resources/settings/site_settings/add_site_dialog.js b/chrome/browser/resources/settings/site_settings/add_site_dialog.js
index 48fca0f..59d1ac63 100644
--- a/chrome/browser/resources/settings/site_settings/add_site_dialog.js
+++ b/chrome/browser/resources/settings/site_settings/add_site_dialog.js
@@ -86,9 +86,8 @@
   onSubmit_: function() {
     if (this.$.add.disabled)
       return;  // Can happen when Enter is pressed.
-    var pattern = this.addPatternWildcard(this.site_);
     this.browserProxy.setCategoryPermissionForOrigin(
-        pattern, pattern, this.category, this.contentSetting,
+        this.site_, this.site_, this.category, this.contentSetting,
         this.$.incognito.checked);
     this.$.dialog.close();
   },
diff --git a/chrome/browser/resources/settings/site_settings/cookie_info.js b/chrome/browser/resources/settings/site_settings/cookie_info.js
index d58eb6e..ba05b4a2 100644
--- a/chrome/browser/resources/settings/site_settings/cookie_info.js
+++ b/chrome/browser/resources/settings/site_settings/cookie_info.js
@@ -76,7 +76,7 @@
   var out = [];
   var fields = cookieInfo[data.type];
   for (var i = 0; i < fields.length; i++) {
-    var field = fields[0];
+    var field = fields[i];
     // Iterate through the keys found in |cookieInfo| for the given |type|
     // and see if those keys are present in the data. If so, display them
     // (in the order determined by |cookieInfo|).
diff --git a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
index d7ea49b..7196b784 100644
--- a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
+++ b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
@@ -22,7 +22,7 @@
 
     /**
      * The cookie entries for the given site.
-     * @type {!Array<!CookieDataItem>}
+     * @type {!Array<!CookieDetails>}
      * @private
      */
     entries_: Array,
@@ -83,14 +83,14 @@
   },
 
   /**
-   * @param {!CookieDataSummaryItem} cookies
+   * @param {!CookieList} cookies
    * @private
    */
   onCookiesLoaded_: function(cookies) {
     this.siteId_ = cookies.id;
     this.entries_ = cookies.children;
     // Set up flag for expanding cookie details.
-    this.entries_.map(function(e) { return e.expanded_ = false; });
+    this.entries_.forEach(function(e) { e.expanded_ = false; });
   },
 
   /**
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
index 737d0e4..9365965 100644
--- a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
+++ b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
@@ -61,25 +61,6 @@
   },
 
   /**
-   * Adds the wildcard prefix to a pattern string (if missing).
-   * @param {string} pattern The pattern to add the wildcard to.
-   * @return {string} The resulting pattern.
-   * @private
-   */
-  addPatternWildcard: function(pattern) {
-    if (pattern.indexOf('[*.]') > -1)
-      return pattern;
-    if (pattern.startsWith('http://'))
-      return pattern.replace('http://', 'http://[*.]');
-    else if (pattern.startsWith('https://'))
-      return pattern.replace('https://', 'https://[*.]');
-    else if (pattern.startsWith('chrome-extension://'))
-      return pattern;  // No need for a wildcard for this.
-    else
-      return '[*.]' + pattern;
-  },
-
-  /**
    * Removes the wildcard prefix from a pattern string.
    * @param {string} pattern The pattern to remove the wildcard from.
    * @return {string} The resulting pattern.
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
index 05035f40..65125779 100644
--- a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
+++ b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
@@ -106,7 +106,7 @@
     /**
      * Gets the cookie details for a particular site.
      * @param {string} site The name of the site.
-     * @return {!Promise<!CookieDataSummaryItem>}
+     * @return {!Promise<!CookieList>}
      */
     getCookieDetails: function(site) {},
 
diff --git a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
index b31a327..7803717 100644
--- a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
+++ b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
@@ -2,7 +2,6 @@
 <html dir="$i18n{textdirection}" lang="$i18n{language}">
   <head>
     <meta charset="utf-8">
-    <link rel="import" href="chrome://resources/html/i18n_behavior.html">
     <link rel="import" href="chrome://resources/html/polymer.html">
     <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
     <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
@@ -28,6 +27,11 @@
       }
 
       .radio-button-title-container {
+        font-weight: 500;
+        line-height: 20px;
+      }
+
+      .radio-button-subtitle-container {
         line-height: 20px;
       }
 
@@ -64,16 +68,22 @@
         <paper-radio-group selected="createNewUser">
           <paper-radio-button id="createNewUserRadioButton"
               name="createNewUser">
-             <div class="radio-button-title-container"
-                  id="createNewUserRadioButtonTitle">
+            <div class="radio-button-title-container">
               $i18n{signinEmailConfirmationCreateProfileButtonTitle}
             </div>
+            <div class="radio-button-subtitle-container"
+                id="createNewUserRadioButtonSubtitle">
+              $i18n{signinEmailConfirmationCreateProfileButtonSubtitle}
+            </div>
           </paper-radio-button>
           <paper-radio-button id="startSyncRadioButton" name="startSync">
-             <div class="radio-button-title-container"
-                 id="startSyncRadioButtonTitle">
+            <div class="radio-button-title-container">
               $i18n{signinEmailConfirmationStartSyncButtonTitle}
             </div>
+            <div class="radio-button-subtitle-container"
+                id="startSyncRadioButtonSubtitle">
+              $i18n{signinEmailConfirmationStartSyncButtonSubtitle}
+            </div>
           </paper-radio-button>
         </paper-radio-group>
       </div>
diff --git a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.js b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.js
index f4f41643..84ecd498 100644
--- a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.js
+++ b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.js
@@ -11,10 +11,10 @@
     var newEmail = args.newEmail;
     $('dialogTitle').textContent = loadTimeData.getStringF(
         'signinEmailConfirmationTitle', lastEmail);
-    $('createNewUserRadioButtonTitle').innerHTML = I18nBehavior.i18n(
-        'signinEmailConfirmationCreateProfileButtonTitle', newEmail);
-    $('startSyncRadioButtonTitle').innerHTML = I18nBehavior.i18n(
-        'signinEmailConfirmationStartSyncButtonTitle', newEmail);
+    $('createNewUserRadioButtonSubtitle').textContent = loadTimeData.getStringF(
+        'signinEmailConfirmationCreateProfileButtonSubtitle', newEmail);
+    $('startSyncRadioButtonSubtitle').textContent = loadTimeData.getStringF(
+        'signinEmailConfirmationStartSyncButtonSubtitle', newEmail);
 
     document.addEventListener('keydown', onKeyDown);
     $('confirmButton').addEventListener('click', onConfirm);
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chrome/browser/resources/vr_shell/vr_shell_ui.js
index aa23dec..4a52454 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.js
@@ -56,7 +56,7 @@
       ui.updateElement(this.elementId, update);
       if (enabled) {
         api.setContentCssSize(
-          this.CSS_WIDTH_PIXELS, this.CSS_HEIGHT_PIXELS, this.DPR);
+            this.CSS_WIDTH_PIXELS, this.CSS_HEIGHT_PIXELS, this.DPR);
       } else {
         // TODO(mthiesse): Restore the webVR resolution (which matches native
         // display resolution).
@@ -519,41 +519,47 @@
 
   class Background {
     constructor() {
-      /** @const */ var GRADIENT_LIGHER_GRAY =
-          {r: 0.57, g: 0.57, b: 0.57, a: 1.0};
-      /** @const */ var GRADIENT_DARKER_GRAY =
-          {r: 0.48, g: 0.48, b: 0.48, a: 1.0};
-      /** @const */ var SCENE_GROUND_SIZE = 25.0;
-      /** @const */ var SCENE_HEIGHT = 4.0;
-      /** @const */ var GRIDLINE_COUNT = 10;
+      /** @const */ this.SCENE_GROUND_SIZE = 25.0;
+      /** @const */ this.SCENE_HEIGHT = 4.0;
+      /** @const */ this.GRIDLINE_COUNT = 10;
+      /** @const */ this.HORIZON_COLOR = {r: 0.57, g: 0.57, b: 0.57, a: 1.0};
+      /** @const */ this.CENTER_COLOR = {r: 0.48, g: 0.48, b: 0.48, a: 1.0};
+      /** @const */ this.FULLSCREEN_BACKGROUND_COLOR =
+          {r: 0.1, g: 0.1, b: 0.1, a: 1.0};
 
       // Make ground plane.
       let groundPlane = new api.UiElementUpdate();
       groundPlane.setVisible(true);
-      groundPlane.setSize(SCENE_GROUND_SIZE, SCENE_GROUND_SIZE);
+      groundPlane.setSize(this.SCENE_GROUND_SIZE, this.SCENE_GROUND_SIZE);
       groundPlane.setFill(
-          new api.OpaqueGradient(GRADIENT_LIGHER_GRAY, GRADIENT_DARKER_GRAY));
-      groundPlane.setTranslation(0, -SCENE_HEIGHT / 2, 0);
+          new api.OpaqueGradient(this.HORIZON_COLOR, this.CENTER_COLOR));
+      groundPlane.setTranslation(0, -this.SCENE_HEIGHT / 2, 0);
       groundPlane.setRotation(1.0, 0.0, 0.0, -Math.PI / 2);
       this.groundPlaneId = ui.addElement(groundPlane);
 
       // Make ceiling plane.
       let ceilingPlane = new api.UiElementUpdate();
       ceilingPlane.setVisible(true);
-      ceilingPlane.setSize(SCENE_GROUND_SIZE, SCENE_GROUND_SIZE);
+      ceilingPlane.setSize(this.SCENE_GROUND_SIZE, this.SCENE_GROUND_SIZE);
       ceilingPlane.setFill(
-          new api.OpaqueGradient(GRADIENT_LIGHER_GRAY, GRADIENT_DARKER_GRAY));
-      ceilingPlane.setTranslation(0, SCENE_HEIGHT / 2, 0);
+          new api.OpaqueGradient(this.HORIZON_COLOR, this.CENTER_COLOR));
+      ceilingPlane.setTranslation(0, this.SCENE_HEIGHT / 2, 0);
       ceilingPlane.setRotation(1.0, 0.0, 0.0, Math.PI / 2);
       this.ceilingPlaneId = ui.addElement(ceilingPlane);
 
       // Ground grid.
       let groundGrid = new api.UiElementUpdate();
       groundGrid.setVisible(true);
-      groundGrid.setSize(SCENE_GROUND_SIZE, SCENE_GROUND_SIZE);
+      groundGrid.setSize(this.SCENE_GROUND_SIZE, this.SCENE_GROUND_SIZE);
+      let transparentHorizonColor = {
+        r: this.HORIZON_COLOR.r,
+        g: this.HORIZON_COLOR.g,
+        b: this.HORIZON_COLOR.b,
+        a: 0
+      };
       groundGrid.setFill(new api.GridGradient(
-          GRADIENT_LIGHER_GRAY, GRADIENT_LIGHER_GRAY, GRIDLINE_COUNT));
-      groundGrid.setTranslation(0, -SCENE_HEIGHT / 2 + 0.01, 0);
+          transparentHorizonColor, this.HORIZON_COLOR, this.GRIDLINE_COUNT));
+      groundGrid.setTranslation(0, -this.SCENE_HEIGHT / 2 + 0.01, 0);
       groundGrid.setRotation(1.0, 0.0, 0.0, -Math.PI / 2);
       this.groundGridId = ui.addElement(groundGrid);
     }
@@ -569,6 +575,23 @@
       groundGridUpdate.setVisible(enabled);
       ui.updateElement(this.groundGridId, groundGridUpdate);
     }
+
+    setFullscreen(fullscreen) {
+      let groundPlaneUpdate = new api.UiElementUpdate();
+      groundPlaneUpdate.setVisible(!fullscreen);
+      ui.updateElement(this.groundPlaneId, groundPlaneUpdate);
+      let ceilingPlaneUpdate = new api.UiElementUpdate();
+      ceilingPlaneUpdate.setVisible(!fullscreen);
+      ui.updateElement(this.ceilingPlaneId, ceilingPlaneUpdate);
+
+      // Set darker background color for fullscreen since the user might
+      // potentially watch a video.
+      if (fullscreen) {
+        ui.setBackgroundColor(this.FULLSCREEN_BACKGROUND_COLOR);
+      } else {
+        ui.setBackgroundColor(this.HORIZON_COLOR);
+      }
+    }
   };
 
   class Omnibox {
@@ -694,9 +717,9 @@
           URL_INDICATOR_VISIBILITY_TIMEOUT_MS);
       this.secureOriginWarnings.setEnabled(
           mode == api.Mode.WEB_VR && !menuMode);
+      this.background.setFullscreen(this.fullscreen);
 
       this.reloadUiButton.setEnabled(mode == api.Mode.STANDARD);
-      this.background.setEnabled(mode == api.Mode.STANDARD && !menuMode);
 
       api.setUiCssSize(
           uiRootElement.clientWidth, uiRootElement.clientHeight, UI_DPR);
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
index 02051f15f..db4c757 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
@@ -14,7 +14,8 @@
   'UPDATE_ELEMENT': 1,
   'REMOVE_ELEMENT': 2,
   'ADD_ANIMATION': 3,
-  'REMOVE_ANIMATION': 4
+  'REMOVE_ANIMATION': 4,
+  'UPDATE_BACKGROUND': 5
 };
 
 /**
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js b/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
index 214f66d..d1651a5 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
@@ -129,6 +129,11 @@
     delete this.animations[id];
   }
 
+  setBackgroundColor(color) {
+    this.commands.push(
+        {'type': api.Command.UPDATE_BACKGROUND, 'data': {'color': color}});
+  }
+
   /**
    * Purge all elements in the scene.
    */
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
index 3e3832b..26ddbbe 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
@@ -6,12 +6,16 @@
 
 #include <utility>
 
+#include "base/callback.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.h"
 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
+#include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_id.h"
 #include "extensions/common/extension_set.h"
@@ -42,10 +46,14 @@
 SettingsResetPromptModel::SettingsResetPromptModel(
     Profile* profile,
     std::unique_ptr<SettingsResetPromptConfig> prompt_config,
-    std::unique_ptr<ResettableSettingsSnapshot> settings_snapshot)
+    std::unique_ptr<ResettableSettingsSnapshot> settings_snapshot,
+    std::unique_ptr<BrandcodedDefaultSettings> default_settings,
+    std::unique_ptr<ProfileResetter> profile_resetter)
     : profile_(profile),
       prompt_config_(std::move(prompt_config)),
       settings_snapshot_(std::move(settings_snapshot)),
+      default_settings_(std::move(default_settings)),
+      profile_resetter_(std::move(profile_resetter)),
       settings_types_initialized_(0),
       homepage_reset_domain_id_(-1),
       homepage_reset_state_(NO_RESET_REQUIRED_DUE_TO_DOMAIN_NOT_MATCHED),
@@ -55,6 +63,8 @@
   DCHECK(profile_);
   DCHECK(prompt_config_);
   DCHECK(settings_snapshot_);
+  DCHECK(default_settings_);
+  DCHECK(profile_resetter_);
 
   InitHomepageData();
   InitDefaultSearchData();
@@ -69,12 +79,42 @@
 
 SettingsResetPromptModel::~SettingsResetPromptModel() {}
 
-bool SettingsResetPromptModel::ShouldPromptForReset() {
+bool SettingsResetPromptModel::ShouldPromptForReset() const {
   return homepage_reset_state() == RESET_REQUIRED ||
          default_search_reset_state() == RESET_REQUIRED ||
          startup_urls_reset_state() == RESET_REQUIRED;
 }
 
+void SettingsResetPromptModel::PerformReset(
+    const base::Closure& done_callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  // |default_settings_| is set in the constructor and will be passed on to
+  // |profile_resetter_| who will take over ownership. This method should never
+  // be called more than once during the lifetime of this object.
+  DCHECK(default_settings_);
+
+  // Disable all extensions that override settings that need to be reset.
+  ExtensionService* extension_service =
+      extensions::ExtensionSystem::Get(profile_)->extension_service();
+  DCHECK(extension_service);
+  for (const auto& item : extensions_to_disable()) {
+    const extensions::ExtensionId& extension_id = item.first;
+    extension_service->DisableExtension(
+        extension_id, extensions::Extension::DISABLE_USER_ACTION);
+  }
+
+  // Disable all the settings that need to be reset.
+  ProfileResetter::ResettableFlags reset_flags = 0;
+  if (homepage_reset_state() == RESET_REQUIRED)
+    reset_flags |= ProfileResetter::HOMEPAGE;
+  if (default_search_reset_state() == RESET_REQUIRED)
+    reset_flags |= ProfileResetter::DEFAULT_SEARCH_ENGINE;
+  if (startup_urls_reset_state() == RESET_REQUIRED)
+    reset_flags |= ProfileResetter::STARTUP_PAGES;
+  profile_resetter_->Reset(reset_flags, std::move(default_settings_),
+                           done_callback);
+}
+
 std::string SettingsResetPromptModel::homepage() const {
   return settings_snapshot_->homepage();
 }
@@ -178,7 +218,6 @@
 // that default values can be restored. This function should be called after
 // other Init*() functions.
 void SettingsResetPromptModel::InitExtensionData() {
-  DCHECK(settings_snapshot_);
   DCHECK_EQ(settings_types_initialized_, SETTINGS_TYPE_ALL);
 
   // |enabled_extensions()| is a container of [id, name] pairs.
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h
index abbdd27c..6eb4bfbc8 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h
@@ -13,12 +13,15 @@
 #include <unordered_set>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "chrome/browser/safe_browsing/settings_reset_prompt/extension_info.h"
 #include "extensions/common/extension_id.h"
 #include "url/gurl.h"
 
+class BrandcodedDefaultSettings;
 class Profile;
+class ProfileResetter;
 class ResettableSettingsSnapshot;
 
 namespace safe_browsing {
@@ -40,11 +43,20 @@
   SettingsResetPromptModel(
       Profile* profile,
       std::unique_ptr<SettingsResetPromptConfig> prompt_config,
-      std::unique_ptr<ResettableSettingsSnapshot> settings_snapshot);
+      std::unique_ptr<ResettableSettingsSnapshot> settings_snapshot,
+      std::unique_ptr<BrandcodedDefaultSettings> default_settings,
+      std::unique_ptr<ProfileResetter> profile_resetter);
   ~SettingsResetPromptModel();
 
   // Returns true if reset is enabled for any settings type.
-  bool ShouldPromptForReset();
+  bool ShouldPromptForReset() const;
+  // Resets the settings whose reset states are set to |RESET_REQUIRED| as
+  // returned by the methods below. Should be called only on the UI
+  // thread. |done_callback| will called from the UI thread when the reset
+  // operation has been completed.
+  //
+  // NOTE: Can only be called once during the lifetime of this object.
+  void PerformReset(const base::Closure& done_callback);
 
   std::string homepage() const;
   ResetState homepage_reset_state() const;
@@ -73,6 +85,10 @@
   Profile* const profile_;
   std::unique_ptr<SettingsResetPromptConfig> prompt_config_;
   std::unique_ptr<ResettableSettingsSnapshot> settings_snapshot_;
+  // |default_settings_| should only be accessed on the UI thread after
+  // construction.
+  std::unique_ptr<BrandcodedDefaultSettings> default_settings_;
+  std::unique_ptr<ProfileResetter> profile_resetter_;
 
   // Bits to keep track of which settings types have been initialized.
   uint32_t settings_types_initialized_;
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest.cc
index 92ba01a..32dd115 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest.cc
@@ -9,11 +9,14 @@
 #include <unordered_set>
 #include <utility>
 
+#include "base/callback.h"
 #include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_dir.h"
 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
 #include "chrome/browser/profiles/profile.h"
@@ -39,6 +42,7 @@
 using testing::Combine;
 using testing::ElementsAre;
 using testing::IsEmpty;
+using testing::NiceMock;
 using testing::Pair;
 using testing::UnorderedElementsAre;
 
@@ -108,6 +112,9 @@
     "}";
 
 class SettingsResetPromptModelBrowserTest : public ExtensionBrowserTest {
+ public:
+  virtual void OnResetDone() { ++reset_callbacks_; }
+
  protected:
   using ModelPointer = std::unique_ptr<SettingsResetPromptModel>;
 
@@ -197,16 +204,26 @@
   // Returns a model with a mock config that will return negative IDs for every
   // URL.
   ModelPointer CreateModel() {
-    return CreateModelForTesting(profile(), std::unordered_set<std::string>());
+    return CreateModelForTesting(profile(), std::unordered_set<std::string>(),
+                                 nullptr);
   }
 
   // Returns a model with a mock config that will return positive IDs for each
   // URL in |reset_urls|.
   ModelPointer CreateModel(std::unordered_set<std::string> reset_urls) {
-    return CreateModelForTesting(profile(), reset_urls);
+    return CreateModelForTesting(profile(), reset_urls, nullptr);
+  }
+
+  // Returns a model with a mock config that will return positive IDs for each
+  // URL in |reset_urls|.
+  ModelPointer CreateModel(std::unordered_set<std::string> reset_urls,
+                           std::unique_ptr<ProfileResetter> profile_resetter) {
+    return CreateModelForTesting(profile(), reset_urls,
+                                 std::move(profile_resetter));
   }
 
   SessionStartupPref startup_pref_;
+  int reset_callbacks_ = 0;
 };
 
 IN_PROC_BROWSER_TEST_F(SettingsResetPromptModelBrowserTest,
@@ -504,6 +521,72 @@
 // Some tests should run only on platforms where settings override for
 // extensions is available. See comment at the top for more details.
 #if defined(OS_WIN) || defined(OS_MACOSX)
+IN_PROC_BROWSER_TEST_F(SettingsResetPromptModelBrowserTest, PerformReset) {
+  // Load an extension that does not override settings and three extensions that
+  // each override one of homepage, default search and startup URLs.
+  const Extension* safe_extension = nullptr;
+  LoadManifest(kManifestNoOverride, &safe_extension);
+  const Extension* homepage_extension = nullptr;
+  LoadHomepageExtension(kHomepage1, &homepage_extension);
+  const Extension* startup_url_extension = nullptr;
+  LoadStartupUrlExtension(kStartupUrl1, &startup_url_extension);
+  const Extension* default_search_extension = nullptr;
+  LoadSearchExtension(kSearchUrl1, &default_search_extension);
+
+  // Let all overridden URLs require reset.
+  ProfileResetter::ResettableFlags expected_reset_flags =
+      ProfileResetter::HOMEPAGE | ProfileResetter::DEFAULT_SEARCH_ENGINE |
+      ProfileResetter::STARTUP_PAGES;
+  auto mock_resetter =
+      base::MakeUnique<NiceMock<MockProfileResetter>>(profile());
+  EXPECT_CALL(*mock_resetter.get(), MockReset(expected_reset_flags, _, _))
+      .Times(1);
+  ModelPointer model = CreateModel({kHomepage1, kStartupUrl1, kSearchUrl1},
+                                   std::move(mock_resetter));
+
+  EXPECT_TRUE(model->ShouldPromptForReset());
+  EXPECT_THAT(model->extensions_to_disable(),
+              UnorderedElementsAre(Pair(homepage_extension->id(), _),
+                                   Pair(startup_url_extension->id(), _),
+                                   Pair(default_search_extension->id(), _)));
+  EXPECT_EQ(model->homepage_reset_state(),
+            SettingsResetPromptModel::RESET_REQUIRED);
+  EXPECT_EQ(model->default_search_reset_state(),
+            SettingsResetPromptModel::RESET_REQUIRED);
+  EXPECT_EQ(model->startup_urls_reset_state(),
+            SettingsResetPromptModel::RESET_REQUIRED);
+
+  // The |PerformReset()| function uses |ExtensionService| directly to disable
+  // extensions so that we can expect the extensions to be disabled after the
+  // reset even though we are mocking the |ProfileResetter|.
+  model->PerformReset(
+      base::Bind(&SettingsResetPromptModelBrowserTest::OnResetDone,
+                 base::Unretained(this)));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(reset_callbacks_, 1);
+
+  // After the reset, should no longer need any resets and all
+  // settings-overriding extensions should be disabled.
+  ModelPointer model2 = CreateModel({kHomepage1, kStartupUrl1, kSearchUrl1});
+
+  EXPECT_FALSE(model2->ShouldPromptForReset());
+  EXPECT_EQ(
+      model2->homepage_reset_state(),
+      SettingsResetPromptModel::NO_RESET_REQUIRED_DUE_TO_DOMAIN_NOT_MATCHED);
+  EXPECT_EQ(
+      model2->default_search_reset_state(),
+      SettingsResetPromptModel::NO_RESET_REQUIRED_DUE_TO_DOMAIN_NOT_MATCHED);
+  EXPECT_EQ(
+      model2->startup_urls_reset_state(),
+      SettingsResetPromptModel::NO_RESET_REQUIRED_DUE_TO_DOMAIN_NOT_MATCHED);
+  EXPECT_FALSE(
+      extension_service()->IsExtensionEnabled(homepage_extension->id()));
+  EXPECT_FALSE(
+      extension_service()->IsExtensionEnabled(default_search_extension->id()));
+  EXPECT_FALSE(
+      extension_service()->IsExtensionEnabled(startup_url_extension->id()));
+}
+
 const char kManifestToOverrideAll[] =
     "{"
     "  'name': 'Override All Extension',"
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc
index b880638..40bd0d80 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_unittest.cc
@@ -9,7 +9,7 @@
 #include <unordered_set>
 #include <utility>
 
-#include "base/callback_forward.h"
+#include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -86,6 +86,9 @@
 
 class SettingsResetPromptModelTest
     : public extensions::ExtensionServiceTestBase {
+ public:
+  virtual void OnResetDone() { ++reset_callbacks_; }
+
  protected:
   using ModelPointer = std::unique_ptr<SettingsResetPromptModel>;
 
@@ -156,19 +159,29 @@
   }
 
   // Returns a model with a mock config that will return negative IDs for every
-  // URL. positive IDs for each URL in |reset_urls_|.
+  // URL.
   ModelPointer CreateModel() {
-    return CreateModelForTesting(profile(), std::unordered_set<std::string>());
+    return CreateModelForTesting(profile(), std::unordered_set<std::string>(),
+                                 nullptr);
   }
 
   // Returns a model with a mock config that will return positive IDs for each
   // URL in |reset_urls|.
   ModelPointer CreateModel(std::unordered_set<std::string> reset_urls) {
-    return CreateModelForTesting(profile(), reset_urls);
+    return CreateModelForTesting(profile(), reset_urls, nullptr);
+  }
+
+  // Returns a model with a mock config that will return positive IDs for each
+  // URL in |reset_urls|.
+  ModelPointer CreateModel(std::unordered_set<std::string> reset_urls,
+                           std::unique_ptr<ProfileResetter> profile_resetter) {
+    return CreateModelForTesting(profile(), reset_urls,
+                                 std::move(profile_resetter));
   }
 
   PrefService* prefs_;
   SessionStartupPref startup_pref_;
+  int reset_callbacks_ = 0;
 };
 
 class ResetStatesTest
@@ -364,6 +377,33 @@
   EXPECT_EQ(model->ShouldPromptForReset(), should_prompt_);
 }
 
+TEST_P(ResetStatesTest, PerformReset) {
+  ProfileResetter::ResettableFlags expected_reset_flags = 0U;
+  std::unordered_set<std::string> reset_urls;
+  if (homepage_reset_enabled_) {
+    reset_urls.insert(kHomepage);
+    expected_reset_flags |= ProfileResetter::HOMEPAGE;
+  }
+  if (default_search_reset_enabled_) {
+    reset_urls.insert(kDefaultSearch);
+    expected_reset_flags |= ProfileResetter::DEFAULT_SEARCH_ENGINE;
+  }
+  if (startup_urls_reset_enabled_) {
+    reset_urls.insert(kStartupUrl1);
+    expected_reset_flags |= ProfileResetter::STARTUP_PAGES;
+  }
+
+  auto profile_resetter =
+      base::MakeUnique<NiceMock<MockProfileResetter>>(profile());
+  EXPECT_CALL(*profile_resetter, MockReset(expected_reset_flags, _, _))
+      .Times(1);
+
+  ModelPointer model = CreateModel(reset_urls, std::move(profile_resetter));
+  model->PerformReset(base::Bind(&SettingsResetPromptModelTest::OnResetDone,
+                                 base::Unretained(this)));
+  EXPECT_EQ(reset_callbacks_, 1);
+}
+
 INSTANTIATE_TEST_CASE_P(SettingsResetPromptModel,
                         ResetStatesTest,
                         Combine(Bool(), Bool(), Bool()));
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.cc
index 56695f0..5fcdf787 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/profile_resetter/resettable_settings_snapshot.h"
 #include "chrome/browser/profiles/profile.h"
@@ -24,9 +25,23 @@
 
 MockSettingsResetPromptConfig::~MockSettingsResetPromptConfig() {}
 
+MockProfileResetter::MockProfileResetter(Profile* profile)
+    : ProfileResetter(profile) {}
+
+MockProfileResetter::~MockProfileResetter() {}
+
+void MockProfileResetter::Reset(
+    ProfileResetter::ResettableFlags resettable_flags,
+    std::unique_ptr<BrandcodedDefaultSettings> master_settings,
+    const base::Closure& callback) {
+  MockReset(resettable_flags, master_settings.get(), callback);
+  callback.Run();
+}
+
 std::unique_ptr<SettingsResetPromptModel> CreateModelForTesting(
     Profile* profile,
-    const std::unordered_set<std::string>& reset_urls) {
+    const std::unordered_set<std::string>& reset_urls,
+    std::unique_ptr<ProfileResetter> profile_resetter) {
   auto config = base::MakeUnique<NiceMock<MockSettingsResetPromptConfig>>();
 
   int id = 1;
@@ -38,7 +53,11 @@
 
   return base::MakeUnique<SettingsResetPromptModel>(
       profile, std::move(config),
-      base::MakeUnique<ResettableSettingsSnapshot>(profile));
+      base::MakeUnique<ResettableSettingsSnapshot>(profile),
+      base::MakeUnique<BrandcodedDefaultSettings>(),
+      profile_resetter
+          ? std::move(profile_resetter)
+          : base::MakeUnique<NiceMock<MockProfileResetter>>(profile));
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.h b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.h
index 7b21010..acfe4e0 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.h
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_test_utils.h
@@ -9,11 +9,14 @@
 #include <string>
 #include <unordered_set>
 
+#include "base/callback_forward.h"
+#include "chrome/browser/profile_resetter/profile_resetter.h"
 #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
+class BrandcodedDefaultSettings;
 class Profile;
 
 namespace safe_browsing {
@@ -28,12 +31,34 @@
   MOCK_CONST_METHOD1(UrlToResetDomainId, int(const GURL& URL));
 };
 
-// Returns a |SettingsResetPromptModel| with a mock |SettingsResetPromptConfig|
-// that will return positive reset domain IDs for each URL in |reset_urls| and
-// negative IDs otherwise.
+class MockProfileResetter : public ProfileResetter {
+ public:
+  explicit MockProfileResetter(Profile* profile);
+  ~MockProfileResetter() override;
+
+  // Calls |MockReset()| defined below. Set any expectations on |MockReset|.
+  // After the call to |MockReset()|, will call |callback.Run()| to simulate the
+  // real |ProfileResetter|'s behaviour.
+  void Reset(ProfileResetter::ResettableFlags resettable_flags,
+             std::unique_ptr<BrandcodedDefaultSettings> master_settings,
+             const base::Closure& callback) override;
+
+  MOCK_METHOD3(MockReset,
+               void(ProfileResetter::ResettableFlags resettable_flags,
+                    BrandcodedDefaultSettings* master_settings,
+                    const base::Closure& callback));
+  MOCK_CONST_METHOD0(IsActive, bool());
+};
+
+// Returns a |SettingsResetPromptModel| with mock objects passed to the model's
+// constructor as follows:
+// - A |NiceMock<MockSettingsResetPromptConfig>| that will return positive
+// domain IDs for each URL in |reset_urls| and negative IDs otherwise.
+// - A |NiceMock<MockProfileResetter>| if |profile_resetter| is nullptr.
 std::unique_ptr<SettingsResetPromptModel> CreateModelForTesting(
     Profile* profile,
-    const std::unordered_set<std::string>& reset_urls);
+    const std::unordered_set<std::string>& reset_urls,
+    std::unique_ptr<ProfileResetter> profile_resetter);
 
 }  // namespace safe_browsing
 
diff --git a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
index 4ff9a95..39f0dcd 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
@@ -63,6 +63,18 @@
 const base::FilePath::CharType kDocRoot[] =
     FILE_PATH_LITERAL("chrome/test/data");
 
+// Inject a script into the page. Used by tests that check for visible
+// password fields to wait for notifications about these
+// fields. Notifications about visible password fields are queued at the
+// end of the event loop, so waiting for a dummy script to run ensures
+// that these notifcations have been sent.
+void InjectScript(content::WebContents* contents) {
+  bool js_result = false;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      contents, "window.domAutomationController.send(true);", &js_result));
+  EXPECT_TRUE(js_result);
+}
+
 // A WebContentsObserver useful for testing the DidChangeVisibleSecurityState()
 // method: it keeps track of the latest security style and explanation that was
 // fired.
@@ -331,6 +343,51 @@
         security_state::switches::kMarkHttpWithPasswordsOrCcWithChip);
   }
 
+  // Navigates to an empty page and runs |javascript| to create a URL with with
+  // a scheme of |scheme|. If |expect_warning| is true, expects a password
+  // warning.
+  void TestPasswordFieldOnBlobOrFilesystemURL(const std::string& scheme,
+                                              const std::string& javascript,
+                                              bool expect_warning) {
+    content::WebContents* contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+    ASSERT_TRUE(contents);
+
+    SecurityStateTabHelper* helper =
+        SecurityStateTabHelper::FromWebContents(contents);
+    ASSERT_TRUE(helper);
+
+    ui_test_utils::NavigateToURL(
+        browser(),
+        GetURLWithNonLocalHostname(embedded_test_server(), "/empty.html"));
+
+    // Create a URL and navigate to it.
+    std::string blob_or_filesystem_url;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+        contents, javascript, &blob_or_filesystem_url));
+    EXPECT_TRUE(GURL(blob_or_filesystem_url).SchemeIs(scheme));
+
+    ui_test_utils::NavigateToURL(browser(), GURL(blob_or_filesystem_url));
+    InjectScript(contents);
+    security_state::SecurityInfo security_info;
+    helper->GetSecurityInfo(&security_info);
+
+    content::NavigationEntry* entry =
+        contents->GetController().GetVisibleEntry();
+    ASSERT_TRUE(entry);
+
+    if (expect_warning) {
+      EXPECT_EQ(security_state::HTTP_SHOW_WARNING,
+                security_info.security_level);
+      EXPECT_TRUE(entry->GetSSL().content_status &
+                  content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
+    } else {
+      EXPECT_EQ(security_state::NONE, security_info.security_level);
+      EXPECT_FALSE(entry->GetSSL().content_status &
+                   content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
+    }
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(SecurityStateTabHelperTestWithPasswordCcSwitch);
 };
@@ -938,18 +995,6 @@
       browser()->tab_strip_model()->GetActiveWebContents());
 }
 
-// Inject a script into the page. Used by tests that check for visible
-// password fields to wait for notifications about these
-// fields. Notifications about visible password fields are queued at the
-// end of the event loop, so waiting for a dummy script to run ensures
-// that these notifcations have been sent.
-void InjectScript(content::WebContents* contents) {
-  bool js_result = false;
-  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
-      contents, "window.domAutomationController.send(true);", &js_result));
-  EXPECT_TRUE(js_result);
-}
-
 // Tests that when a visible password field is detected on an HTTP page
 // load, and when the command-line flag is set, the security level is
 // downgraded to HTTP_SHOW_WARNING.
@@ -977,6 +1022,76 @@
               content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP);
 }
 
+// Tests that when a visible password field is detected on a blob URL, and when
+// the command-line flag is set, the security level is downgraded to
+// HTTP_SHOW_WARNING.
+IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch,
+                       PasswordSecurityLevelDowngradedOnBlobUrl) {
+  TestPasswordFieldOnBlobOrFilesystemURL(
+      "blob",
+      "var blob = new Blob(['<html><form><input type=password></form></html>'],"
+      "                    {type: 'text/html'});"
+      "window.domAutomationController.send(URL.createObjectURL(blob));",
+      true /* expect_warning */);
+}
+
+// Tests that when no password field is detected on a blob URL, and when the
+// command-line flag is set the security level is not downgraded to
+// HTTP_SHOW_WARNING.
+IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch,
+                       DefaultSecurityLevelOnBlobUrl) {
+  TestPasswordFieldOnBlobOrFilesystemURL(
+      "blob",
+      "var blob = new Blob(['<html>no password or credit card field</html>'],"
+      "                    {type: 'text/html'});"
+      "window.domAutomationController.send(URL.createObjectURL(blob));",
+      false /* expect_warning */);
+}
+
+// Same as PasswordSecurityLevelDowngradedOnBlobUrl, but instead of a blob URL,
+// this creates a filesystem URL.
+IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch,
+                       PasswordSecurityLevelDowngradedOnFilesystemUrl) {
+  TestPasswordFieldOnBlobOrFilesystemURL(
+      "filesystem",
+      "window.webkitRequestFileSystem(window.TEMPORARY, 4096, function(fs) {"
+      "  fs.root.getFile('test.html', {create: true}, function(fileEntry) {"
+      "    fileEntry.createWriter(function(writer) {"
+      "      writer.onwriteend = function(e) {"
+      "        window.domAutomationController.send(fileEntry.toURL());"
+      "      };"
+      "      var blob ="
+      "          new Blob(['<html><form><input type=password></form></html>'],"
+      "                   {type: 'text/html'});"
+      "      writer.write(blob);"
+      "    });"
+      "  });"
+      "});",
+      true /* expect_warning */);
+}
+
+// Same as DefaultSecurityLevelOnBlobUrl, but instead of a blob URL,
+// this creates a filesystem URL.
+IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch,
+                       DefaultSecurityLevelOnFilesystemUrl) {
+  TestPasswordFieldOnBlobOrFilesystemURL(
+      "filesystem",
+      "window.webkitRequestFileSystem(window.TEMPORARY, 4096, function(fs) {"
+      "  fs.root.getFile('test.html', {create: true}, function(fileEntry) {"
+      "    fileEntry.createWriter(function(writer) {"
+      "      writer.onwriteend = function(e) {"
+      "        window.domAutomationController.send(fileEntry.toURL());"
+      "      };"
+      "      var blob ="
+      "          new Blob(['<html>no password or credit card field</html>'],"
+      "                   {type: 'text/html'});"
+      "      writer.write(blob);"
+      "    });"
+      "  });"
+      "});",
+      false /* expect_warning */);
+}
+
 // Tests that when an invisible password field is present on an HTTP page
 // load, and when the command-line flag is set, the security level is
 // *not* downgraded to HTTP_SHOW_WARNING.
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
index 693ab281..7f334565 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
 #include "chrome/browser/subresource_filter/test_ruleset_publisher.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -39,6 +40,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -200,8 +202,10 @@
 
 class SubresourceFilterBrowserTestImpl : public InProcessBrowserTest {
  public:
-  explicit SubresourceFilterBrowserTestImpl(bool measure_performance)
-      : measure_performance_(measure_performance) {}
+  explicit SubresourceFilterBrowserTestImpl(bool measure_performance,
+                                            bool whitelist_site_on_reload)
+      : measure_performance_(measure_performance),
+        whitelist_site_on_reload_(whitelist_site_on_reload) {}
 
   ~SubresourceFilterBrowserTestImpl() override {}
 
@@ -234,7 +238,8 @@
     scoped_feature_toggle_.reset(new ScopedSubresourceFilterFeatureToggle(
         base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationLevelEnabled,
         kActivationScopeActivationList, kActivationListPhishingInterstitial,
-        measure_performance_ ? "1" : "0"));
+        measure_performance_ ? "1" : "0", "" /* suppress_notifications */,
+        whitelist_site_on_reload_ ? "true" : "false"));
 
     base::FilePath test_data_dir;
     PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
@@ -331,7 +336,8 @@
 
   std::unique_ptr<ScopedSubresourceFilterFeatureToggle> scoped_feature_toggle_;
   TestRulesetPublisher test_ruleset_publisher_;
-  bool measure_performance_;
+  const bool measure_performance_;
+  const bool whitelist_site_on_reload_;
   TestRulesetCreator ruleset_creator_;
 
   DISALLOW_COPY_AND_ASSIGN(SubresourceFilterBrowserTestImpl);
@@ -339,7 +345,8 @@
 
 class SubresourceFilterBrowserTest : public SubresourceFilterBrowserTestImpl {
  public:
-  SubresourceFilterBrowserTest() : SubresourceFilterBrowserTestImpl(false) {}
+  SubresourceFilterBrowserTest()
+      : SubresourceFilterBrowserTestImpl(false, false) {}
 };
 
 // TODO(pkalinnikov): It should be possible to have only one fixture, i.e.,
@@ -351,7 +358,14 @@
     : public SubresourceFilterBrowserTestImpl {
  public:
   SubresourceFilterWithPerformanceMeasurementBrowserTest()
-      : SubresourceFilterBrowserTestImpl(true) {}
+      : SubresourceFilterBrowserTestImpl(true, false) {}
+};
+
+class SubresourceFilterWhitelistSiteOnReloadBrowserTest
+    : public SubresourceFilterBrowserTestImpl {
+ public:
+  SubresourceFilterWhitelistSiteOnReloadBrowserTest()
+      : SubresourceFilterBrowserTestImpl(false, true) {}
 };
 
 // Tests -----------------------------------------------------------------------
@@ -726,4 +740,76 @@
       static_cast<base::Histogram::Sample>(ActivationLevel::DISABLED), 6);
 }
 
+IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest,
+                       ActivationEnabledOnReloadByDefault) {
+  GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
+  ConfigureAsPhishingURL(url);
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
+  ui_test_utils::NavigateToURL(browser(), url);
+  EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+
+  content::TestNavigationObserver observer(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      content::MessageLoopRunner::QuitMode::DEFERRED);
+  chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
+  observer.Wait();
+  EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+}
+
+IN_PROC_BROWSER_TEST_F(SubresourceFilterWhitelistSiteOnReloadBrowserTest,
+                       ActivationDisabledOnReload) {
+  GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
+  ConfigureAsPhishingURL(url);
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
+  ui_test_utils::NavigateToURL(browser(), url);
+  EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+
+  content::TestNavigationObserver observer(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      content::MessageLoopRunner::QuitMode::DEFERRED);
+  chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
+  observer.Wait();
+  EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+}
+
+IN_PROC_BROWSER_TEST_F(SubresourceFilterWhitelistSiteOnReloadBrowserTest,
+                       ActivationDisabledOnReloadFromScript) {
+  GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
+  ConfigureAsPhishingURL(url);
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
+  ui_test_utils::NavigateToURL(browser(), url);
+  EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+
+  content::TestNavigationObserver observer(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      content::MessageLoopRunner::QuitMode::DEFERRED);
+  ASSERT_TRUE(content::ExecuteScript(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "location.reload();"));
+  observer.Wait();
+  EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+}
+
+IN_PROC_BROWSER_TEST_F(SubresourceFilterWhitelistSiteOnReloadBrowserTest,
+                       ActivationDisabledOnNavigationToSameURL) {
+  GURL url(GetTestUrl("subresource_filter/frame_with_included_script.html"));
+  ConfigureAsPhishingURL(url);
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
+  ui_test_utils::NavigateToURL(browser(), url);
+  EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+
+  content::TestNavigationObserver observer(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      content::MessageLoopRunner::QuitMode::DEFERRED);
+  std::string nav_frame_script = "location.href = '" + url.spec() + "';";
+  ASSERT_TRUE(content::ExecuteScript(
+      browser()->tab_strip_model()->GetActiveWebContents(), nav_frame_script));
+  observer.Wait();
+  EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+}
+
 }  // namespace subresource_filter
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 09c30ee..ea1c1724 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -104,6 +104,9 @@
 #endif
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/printing/printer_pref_manager.h"
+#include "chrome/browser/chromeos/printing/printer_pref_manager_factory.h"
+#include "chrome/browser/chromeos/printing/printers_sync_bridge.h"
 #include "chrome/browser/ui/app_list/arc/arc_package_sync_data_type_controller.h"
 #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h"
 #include "components/sync_wifi/wifi_credential_syncable_service.h"
@@ -448,6 +451,12 @@
       return autofill::AutocompleteSyncBridge::FromWebDataService(
                  web_data_service_.get())
           ->AsWeakPtr();
+#if defined(OS_CHROMEOS)
+    case syncer::PRINTERS:
+      return chromeos::PrinterPrefManagerFactory::GetForBrowserContext(profile_)
+          ->GetSyncBridge()
+          ->AsWeakPtr();
+#endif
     default:
       NOTREACHED();
       return base::WeakPtr<syncer::ModelTypeSyncBridge>();
@@ -626,6 +635,7 @@
             syncer::WIFI_CREDENTIALS, error_callback, this, syncer::GROUP_UI,
             BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)));
   }
+
   // TODO(lgcheng): Add switch for this.
   sync_service->RegisterDataTypeController(
       base::MakeUnique<ArcPackageSyncDataTypeController>(
diff --git a/chrome/browser/sync/profile_sync_service_factory_unittest.cc b/chrome/browser/sync/profile_sync_service_factory_unittest.cc
index b831543..e326da8 100644
--- a/chrome/browser/sync/profile_sync_service_factory_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_factory_unittest.cc
@@ -42,9 +42,6 @@
 #if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_CHROMEOS)
     datatypes.push_back(syncer::DICTIONARY);
 #endif
-#if defined(OS_CHROMEOS)
-    datatypes.push_back(syncer::ARC_PACKAGE);
-#endif
     datatypes.push_back(syncer::EXTENSIONS);
     datatypes.push_back(syncer::EXTENSION_SETTINGS);
     datatypes.push_back(syncer::SEARCH_ENGINES);
@@ -53,6 +50,11 @@
     datatypes.push_back(syncer::SUPERVISED_USER_SHARED_SETTINGS);
 #endif  // !OS_ANDROID
 
+#if defined(OS_CHROMEOS)
+    datatypes.push_back(syncer::ARC_PACKAGE);
+    datatypes.push_back(syncer::PRINTERS);
+#endif  // OS_CHROMEOS
+
     // Common types.
     datatypes.push_back(syncer::AUTOFILL);
     datatypes.push_back(syncer::AUTOFILL_PROFILE);
diff --git a/chrome/browser/sync/test/integration/printers_helper.cc b/chrome/browser/sync/test/integration/printers_helper.cc
new file mode 100644
index 0000000..2c0e3cc9
--- /dev/null
+++ b/chrome/browser/sync/test/integration/printers_helper.cc
@@ -0,0 +1,161 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/test/integration/printers_helper.h"
+
+#include <algorithm>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/printing/printer_pref_manager.h"
+#include "chrome/browser/chromeos/printing/printer_pref_manager_factory.h"
+#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
+#include "chrome/browser/sync/test/integration/sync_test.h"
+
+using sync_datatype_helper::test;
+
+namespace printers_helper {
+
+namespace {
+
+using PrinterList = std::vector<std::unique_ptr<chromeos::Printer>>;
+
+// Returns true if Printer#id, Printer#description, and Printer#uri all match.
+bool PrintersAreMostlyEqual(const chromeos::Printer& left,
+                            const chromeos::Printer& right) {
+  return left.id() == right.id() && left.description() == right.description() &&
+         left.uri() == right.uri();
+}
+
+// Returns true if both lists have the same elements irrespective of order.
+bool ListsContainTheSamePrinters(const PrinterList& list_a,
+                                 const PrinterList& list_b) {
+  std::unordered_multimap<std::string, const chromeos::Printer*> map_b;
+  for (const auto& b : list_b) {
+    map_b.insert({b->id(), b.get()});
+  }
+
+  for (const auto& a : list_a) {
+    auto range = map_b.equal_range(a->id());
+
+    auto it = std::find_if(
+        range.first, range.second,
+        [&a](const std::pair<std::string, const chromeos::Printer*>& entry)
+            -> bool { return PrintersAreMostlyEqual(*a, *(entry.second)); });
+
+    if (it == range.second) {
+      // Element in a does not match an element in b. Lists do not contain the
+      // same elements.
+      return false;
+    }
+
+    map_b.erase(it);
+  }
+
+  return map_b.empty();
+}
+
+std::string PrinterId(int index) {
+  return base::StringPrintf("printer%d", index);
+}
+
+}  // namespace
+
+void AddPrinter(chromeos::PrinterPrefManager* manager,
+                const chromeos::Printer& printer) {
+  manager->RegisterPrinter(base::MakeUnique<chromeos::Printer>(printer));
+}
+
+void RemovePrinter(chromeos::PrinterPrefManager* manager, int index) {
+  chromeos::Printer testPrinter(CreateTestPrinter(index));
+  manager->RemovePrinter(testPrinter.id());
+}
+
+bool EditPrinterDescription(chromeos::PrinterPrefManager* manager,
+                            int index,
+                            const std::string& description) {
+  PrinterList printers = manager->GetPrinters();
+  std::string printer_id = PrinterId(index);
+  auto found = std::find_if(
+      printers.begin(), printers.end(),
+      [&printer_id](const std::unique_ptr<chromeos::Printer>& printer) -> bool {
+        return printer->id() == printer_id;
+      });
+
+  if (found == printers.end())
+    return false;
+
+  (*found)->set_description(description);
+  manager->RegisterPrinter(std::move(*found));
+
+  return true;
+}
+
+chromeos::Printer CreateTestPrinter(int index) {
+  chromeos::Printer printer(PrinterId(index));
+  printer.set_description("Description");
+  printer.set_uri(base::StringPrintf("ipp://192.168.1.%d", index));
+
+  return printer;
+}
+
+chromeos::PrinterPrefManager* GetVerifierPrinterStore() {
+  chromeos::PrinterPrefManager* manager =
+      chromeos::PrinterPrefManagerFactory::GetForBrowserContext(
+          sync_datatype_helper::test()->verifier());
+  // Must wait for ModelTypeStore initialization.
+  base::RunLoop().RunUntilIdle();
+
+  return manager;
+}
+
+chromeos::PrinterPrefManager* GetPrinterStore(int index) {
+  chromeos::PrinterPrefManager* manager =
+      chromeos::PrinterPrefManagerFactory::GetForBrowserContext(
+          sync_datatype_helper::test()->GetProfile(index));
+  // Must wait for ModelTypeStore initialization.
+  base::RunLoop().RunUntilIdle();
+
+  return manager;
+}
+
+int GetVerifierPrinterCount() {
+  return GetVerifierPrinterStore()->GetPrinters().size();
+}
+
+int GetPrinterCount(int index) {
+  return GetPrinterStore(index)->GetPrinters().size();
+}
+
+bool AllProfilesContainSamePrinters() {
+  auto reference_printers = GetPrinterStore(0)->GetPrinters();
+  for (int i = 1; i < test()->num_clients(); ++i) {
+    auto printers = GetPrinterStore(i)->GetPrinters();
+    if (!ListsContainTheSamePrinters(reference_printers, printers)) {
+      VLOG(1) << "Printers in client [" << i << "] don't match client 0";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool ProfileContainsSamePrintersAsVerifier(int index) {
+  return ListsContainTheSamePrinters(GetVerifierPrinterStore()->GetPrinters(),
+                                     GetPrinterStore(index)->GetPrinters());
+}
+
+PrintersMatchChecker::PrintersMatchChecker()
+    : AwaitMatchStatusChangeChecker(
+          base::Bind(&printers_helper::AllProfilesContainSamePrinters),
+          "All printers match") {}
+
+PrintersMatchChecker::~PrintersMatchChecker() {}
+
+}  // namespace printers_helper
diff --git a/chrome/browser/sync/test/integration/printers_helper.h b/chrome/browser/sync/test/integration/printers_helper.h
new file mode 100644
index 0000000..3a676dc
--- /dev/null
+++ b/chrome/browser/sync/test/integration/printers_helper.h
@@ -0,0 +1,75 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_PRINTERS_HELPER_H_
+#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_PRINTERS_HELPER_H_
+
+#include <memory>
+#include <string>
+
+#include "chrome/browser/chromeos/printing/printer_pref_manager.h"
+#include "chrome/browser/sync/test/integration/await_match_status_change_checker.h"
+#include "chromeos/printing/printer_configuration.h"
+
+namespace printers_helper {
+
+void SetUp();
+
+void SetupClients();
+
+// Create a test printer.
+chromeos::Printer CreateTestPrinter(int index);
+
+// Add printer to the supplied store.
+void AddPrinter(chromeos::PrinterPrefManager* manager,
+                const chromeos::Printer& printer);
+
+// Remove printer |index| from the |manager|.
+void RemovePrinter(chromeos::PrinterPrefManager* manager, int index);
+
+// Change the description of the printer at |index| with |description|.  Returns
+// false if the printer is not tracked by the manager.
+bool EditPrinterDescription(chromeos::PrinterPrefManager* manager,
+                            int index,
+                            const std::string& description);
+
+// Returns the verifier store.
+chromeos::PrinterPrefManager* GetVerifierPrinterStore();
+
+// Returns printer store at |index|.
+chromeos::PrinterPrefManager* GetPrinterStore(int index);
+
+// Returns the number of printers in the verifier store.
+int GetVerifierPrinterCount();
+
+// Returns the number of printers in printer store |index|.
+int GetPrinterCount(int index);
+
+// Returns true if all profiles contain the same printers as profile 0.
+bool AllProfilesContainSamePrinters();
+
+// Returns true if the verifier store and printer store |index| contain the same
+// data.
+bool ProfileContainsSamePrintersAsVerifier(int index);
+
+// A waiter that can block until we can satisfy
+// AllProfilesContainSamePrinters().
+// Example:
+//     // Make changes that you expect to sync.
+//
+//     ASSERT_TRUE(PrintersMatchChecker().Wait());
+//
+//     // Sync is complete, verify the chagnes.
+class PrintersMatchChecker : public AwaitMatchStatusChangeChecker {
+ public:
+  PrintersMatchChecker();
+  ~PrintersMatchChecker() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PrintersMatchChecker);
+};
+
+}  // namespace printers_helper
+
+#endif  // CHROME_BROWSER_SYNC_TEST_INTEGRATION_PRINTERS_HELPER_H_
diff --git a/chrome/browser/sync/test/integration/single_client_printers_sync_test.cc b/chrome/browser/sync/test/integration/single_client_printers_sync_test.cc
new file mode 100644
index 0000000..4b41c7e
--- /dev/null
+++ b/chrome/browser/sync/test/integration/single_client_printers_sync_test.cc
@@ -0,0 +1,89 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+#include "base/macros.h"
+#include "chrome/browser/sync/test/integration/printers_helper.h"
+#include "chrome/browser/sync/test/integration/sync_test.h"
+#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
+#include "chromeos/printing/printer_configuration.h"
+
+using printers_helper::AddPrinter;
+using printers_helper::CreateTestPrinter;
+using printers_helper::EditPrinterDescription;
+using printers_helper::GetVerifierPrinterCount;
+using printers_helper::GetVerifierPrinterStore;
+using printers_helper::GetPrinterCount;
+using printers_helper::GetPrinterStore;
+using printers_helper::ProfileContainsSamePrintersAsVerifier;
+using printers_helper::RemovePrinter;
+
+class SingleClientPrintersSyncTest : public SyncTest {
+ public:
+  SingleClientPrintersSyncTest() : SyncTest(SINGLE_CLIENT) {}
+  ~SingleClientPrintersSyncTest() override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SingleClientPrintersSyncTest);
+};
+
+// Verify that printers aren't added with a sync call.
+IN_PROC_BROWSER_TEST_F(SingleClientPrintersSyncTest, NoPrinters) {
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+  ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
+  EXPECT_TRUE(ProfileContainsSamePrintersAsVerifier(0));
+}
+
+// Verify syncing doesn't randomly remove a printer.
+IN_PROC_BROWSER_TEST_F(SingleClientPrintersSyncTest, SingleNewPrinter) {
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+  ASSERT_EQ(0, GetVerifierPrinterCount());
+
+  AddPrinter(GetPrinterStore(0), printers_helper::CreateTestPrinter(0));
+  AddPrinter(GetVerifierPrinterStore(), printers_helper::CreateTestPrinter(0));
+  ASSERT_EQ(1, GetPrinterCount(0));
+  ASSERT_EQ(1, GetVerifierPrinterCount());
+
+  ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
+  EXPECT_EQ(1, GetVerifierPrinterCount());
+  EXPECT_TRUE(ProfileContainsSamePrintersAsVerifier(0));
+}
+
+// Verify editing a printer doesn't add it.
+IN_PROC_BROWSER_TEST_F(SingleClientPrintersSyncTest, EditPrinter) {
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+  AddPrinter(GetPrinterStore(0), printers_helper::CreateTestPrinter(0));
+  AddPrinter(GetVerifierPrinterStore(), printers_helper::CreateTestPrinter(0));
+
+  ASSERT_TRUE(
+      EditPrinterDescription(GetPrinterStore(0), 0, "Updated description"));
+
+  EXPECT_EQ(1, GetPrinterCount(0));
+  EXPECT_EQ(1, GetVerifierPrinterCount());
+  EXPECT_FALSE(ProfileContainsSamePrintersAsVerifier(0));
+}
+
+// Verify that removing a printer works.
+IN_PROC_BROWSER_TEST_F(SingleClientPrintersSyncTest, RemovePrinter) {
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+  AddPrinter(GetPrinterStore(0), printers_helper::CreateTestPrinter(0));
+  EXPECT_EQ(1, GetPrinterCount(0));
+
+  RemovePrinter(GetPrinterStore(0), 0);
+  EXPECT_EQ(0, GetPrinterCount(0));
+}
+
+// Verify that merging data added before sync works.
+IN_PROC_BROWSER_TEST_F(SingleClientPrintersSyncTest, AddBeforeSetup) {
+  ASSERT_TRUE(SetupClients());
+
+  AddPrinter(GetPrinterStore(0), printers_helper::CreateTestPrinter(0));
+  EXPECT_EQ(1, GetPrinterCount(0));
+
+  EXPECT_TRUE(SetupSync()) << "SetupSync() failed.";
+}
diff --git a/chrome/browser/sync/test/integration/two_client_printers_sync_test.cc b/chrome/browser/sync/test/integration/two_client_printers_sync_test.cc
new file mode 100644
index 0000000..9633883
--- /dev/null
+++ b/chrome/browser/sync/test/integration/two_client_printers_sync_test.cc
@@ -0,0 +1,150 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdio.h>
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "chrome/browser/sync/test/integration/printers_helper.h"
+#include "chrome/browser/sync/test/integration/sync_test.h"
+
+namespace {
+
+using printers_helper::AddPrinter;
+using printers_helper::AllProfilesContainSamePrinters;
+using printers_helper::EditPrinterDescription;
+using printers_helper::CreateTestPrinter;
+using printers_helper::GetPrinterCount;
+using printers_helper::GetPrinterStore;
+using printers_helper::PrintersMatchChecker;
+using printers_helper::RemovePrinter;
+
+class TwoClientPrintersSyncTest : public SyncTest {
+ public:
+  TwoClientPrintersSyncTest() : SyncTest(TWO_CLIENT) {}
+  ~TwoClientPrintersSyncTest() override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TwoClientPrintersSyncTest);
+};
+
+IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest, NoPrinters) {
+  ASSERT_TRUE(SetupSync());
+
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest, OnePrinter) {
+  ASSERT_TRUE(SetupSync());
+
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(2));
+
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest, SimultaneousAdd) {
+  ASSERT_TRUE(SetupSync());
+
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(1));
+  AddPrinter(GetPrinterStore(1), CreateTestPrinter(2));
+
+  // Each store is guaranteed to have 1 printer because the tests run on the UI
+  // thread.  ApplySyncChanges happens after we wait on the checker.
+  ASSERT_EQ(1, GetPrinterCount(0));
+  ASSERT_EQ(1, GetPrinterCount(1));
+
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+  EXPECT_EQ(2, GetPrinterCount(0));
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest, RemovePrinter) {
+  ASSERT_TRUE(SetupSync());
+
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(1));
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(2));
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(3));
+
+  // Verify the profiles have the same printers
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+  EXPECT_EQ(3, GetPrinterCount(0));
+
+  // Remove printer 2 from store 1
+  RemovePrinter(GetPrinterStore(1), 2);
+
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+  EXPECT_EQ(2, GetPrinterCount(0));
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest, RemoveAndEditPrinters) {
+  const std::string updated_description = "Testing changes";
+
+  ASSERT_TRUE(SetupSync());
+
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(1));
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(2));
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(3));
+
+  // Verify the profiles have the same printers
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+  EXPECT_EQ(3, GetPrinterCount(0));
+
+  // Edit printer 1 from store 0
+  ASSERT_TRUE(
+      EditPrinterDescription(GetPrinterStore(0), 1, updated_description));
+
+  // Remove printer 2 from store 1
+  RemovePrinter(GetPrinterStore(1), 2);
+
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+  EXPECT_EQ(2, GetPrinterCount(0));
+  EXPECT_EQ(updated_description,
+            GetPrinterStore(1)->GetPrinters()[0]->description());
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest, ConflictResolution) {
+  ASSERT_TRUE(SetupSync());
+
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(0));
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(2));
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(3));
+
+  // Store 0 and 1 have 3 printers now.
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+
+  std::string overwritten_message = "I should not show up";
+  ASSERT_TRUE(
+      EditPrinterDescription(GetPrinterStore(1), 0, overwritten_message));
+
+  // Wait for a non-zero period (200ms).
+  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
+
+  std::string valid_message = "YAY!  More recent changes win!";
+  ASSERT_TRUE(EditPrinterDescription(GetPrinterStore(0), 0, valid_message));
+
+  // Conflict resolution shoud run here.
+  ASSERT_TRUE(PrintersMatchChecker().Wait());
+  // The more recent update should win.
+  EXPECT_EQ(valid_message, GetPrinterStore(1)->GetPrinters()[0]->description());
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest, SimpleMerge) {
+  ASSERT_TRUE(SetupClients());
+  base::RunLoop().RunUntilIdle();
+
+  // Store 0 has the even printers
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(0));
+  AddPrinter(GetPrinterStore(0), CreateTestPrinter(2));
+
+  // Store 1 has the odd printers
+  AddPrinter(GetPrinterStore(1), CreateTestPrinter(1));
+  AddPrinter(GetPrinterStore(1), CreateTestPrinter(3));
+
+  ASSERT_TRUE(SetupSync());
+
+  // Stores should contain the same values now.
+  EXPECT_EQ(4, GetPrinterCount(0));
+  EXPECT_TRUE(AllProfilesContainSamePrinters());
+}
+
+}  // namespace
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h
index 3e328d7..c75ee950c9 100644
--- a/chrome/browser/themes/theme_properties.h
+++ b/chrome/browser/themes/theme_properties.h
@@ -80,6 +80,9 @@
   enum NotOverwritableByUserThemeProperty {
     COLOR_CONTROL_BACKGROUND = 1000,
 
+    // The color of the border drawn around the location bar.
+    COLOR_LOCATION_BAR_BORDER,
+
     // The color of the line separating the bottom of the toolbar from the
     // contents.
     COLOR_TOOLBAR_BOTTOM_SEPARATOR,
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 8c8103e..77549f41 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -438,6 +438,8 @@
       return SkColorSetA(
           GetColor(ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON, incognito),
           0x33);
+    case ThemeProperties::COLOR_LOCATION_BAR_BORDER:
+      return SkColorSetA(SK_ColorBLACK, 0x4D);
     case ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR:
     case ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR_INACTIVE: {
       const SkColor tab_color =
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a682bc1..ea1dad3a 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1284,6 +1284,8 @@
   }
   if (use_ash) {
     sources += [
+      "ash/app_launcher_id.cc",
+      "ash/app_launcher_id.h",
       "ash/app_list/app_list_controller_ash.cc",
       "ash/app_list/app_list_controller_ash.h",
       "ash/app_list/app_list_presenter_delegate_mus.cc",
diff --git a/chrome/browser/ui/apps/PRESUBMIT.py b/chrome/browser/ui/apps/PRESUBMIT.py
deleted file mode 100644
index 627f282..0000000
--- a/chrome/browser/ui/apps/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2014 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.
-
-"""Presubmit script for extensions and apps.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/chrome/browser/ui/ash/PRESUBMIT.py b/chrome/browser/ui/ash/PRESUBMIT.py
deleted file mode 100644
index f39f299b..0000000
--- a/chrome/browser/ui/ash/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for ash.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/chrome/browser/ui/ash/app_launcher_id.cc b/chrome/browser/ui/ash/app_launcher_id.cc
new file mode 100644
index 0000000..fa42b1f
--- /dev/null
+++ b/chrome/browser/ui/ash/app_launcher_id.cc
@@ -0,0 +1,27 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/app_launcher_id.h"
+
+#include "base/logging.h"
+
+namespace ash {
+namespace launcher {
+
+AppLauncherId::AppLauncherId(const std::string& app_id,
+                             const std::string& launch_id)
+    : app_id_(app_id), launch_id_(launch_id) {
+  DCHECK(!app_id.empty());
+}
+
+AppLauncherId::AppLauncherId(const std::string& app_id) : app_id_(app_id) {
+  DCHECK(!app_id.empty());
+}
+
+AppLauncherId::AppLauncherId() {}
+
+AppLauncherId::~AppLauncherId() {}
+
+}  // namespace launcher
+}  // namespace ash
diff --git a/chrome/browser/ui/ash/app_launcher_id.h b/chrome/browser/ui/ash/app_launcher_id.h
new file mode 100644
index 0000000..dcdcc6f
--- /dev/null
+++ b/chrome/browser/ui/ash/app_launcher_id.h
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ASH_APP_LAUNCHER_ID_H_
+#define CHROME_BROWSER_UI_ASH_APP_LAUNCHER_ID_H_
+
+#include <string>
+
+namespace ash {
+namespace launcher {
+
+// A unique chrome launcher id used to identify a shelf item. This class is a
+// wrapper for the chrome launcher identifier. |app_launcher_id_| includes the
+// |app_id| and the |launch_id|. The |app_id| is the application id associated
+// with a set of windows. The |launch_id| is an id that can be passed to an app
+// when launched in order to support multiple shelf items per app. This id is
+// used together with the |app_id| to uniquely identify each shelf item that
+// has the same |app_id|. The |app_id| must not be empty.
+class AppLauncherId {
+ public:
+  AppLauncherId(const std::string& app_id, const std::string& launch_id);
+  // Creates an AppLauncherId with an empty |launch_id|.
+  explicit AppLauncherId(const std::string& app_id);
+  // Empty constructor for pre-allocating.
+  AppLauncherId();
+  ~AppLauncherId();
+
+  AppLauncherId(const AppLauncherId& app_launcher_id) = default;
+  AppLauncherId(AppLauncherId&& app_launcher_id) = default;
+  AppLauncherId& operator=(const AppLauncherId& other) = default;
+
+  const std::string& app_id() const { return app_id_; }
+  const std::string& launch_id() const { return launch_id_; }
+
+ private:
+  // The application id associated with a set of windows.
+  std::string app_id_;
+  // An id that can be passed to an app when launched in order to support
+  // multiple shelf items per app.
+  std::string launch_id_;
+};
+
+}  // namespace launcher
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_UI_ASH_APP_LAUNCHER_ID_H_
diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
index de13c3b8..e9b7012 100644
--- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
@@ -127,9 +127,8 @@
     AppListSource source,
     int event_flags) {
   ChromeLauncherController::instance()->LaunchApp(
-      extension->id(),
-      AppListSourceToLaunchSource(source),
-      event_flags);
+      ash::launcher::AppLauncherId(extension->id()),
+      AppListSourceToLaunchSource(source), event_flags);
   DismissView();
 }
 
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.cc b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
index 18433a4..324d92a 100644
--- a/chrome/browser/ui/ash/chrome_launcher_prefs.cc
+++ b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+#include "chrome/browser/ui/ash/app_launcher_id.h"
 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
@@ -35,6 +36,13 @@
 
 namespace {
 
+std::unique_ptr<base::DictionaryValue> CreateAppDict(
+    const std::string& app_id) {
+  auto app_value = base::MakeUnique<base::DictionaryValue>();
+  app_value->SetString(kPinnedAppsPrefAppIDPath, app_id);
+  return app_value;
+}
+
 // App ID of default pinned apps.
 const char* kDefaultPinnedApps[] = {
     extension_misc::kGmailAppId, extension_misc::kGoogleDocAppId,
@@ -43,7 +51,7 @@
 base::ListValue* CreateDefaultPinnedAppsList() {
   std::unique_ptr<base::ListValue> apps(new base::ListValue);
   for (size_t i = 0; i < arraysize(kDefaultPinnedApps); ++i)
-    apps->Append(CreateAppDict(AppLauncherId(kDefaultPinnedApps[i])));
+    apps->Append(CreateAppDict(kDefaultPinnedApps[i]));
 
   return apps.release();
 }
@@ -218,12 +226,19 @@
     pref_service->SetString(local_path, pref_service->GetString(synced_path));
 }
 
-struct PinInfo {
-  PinInfo(const AppLauncherId& app_launcher_id,
-          const syncer::StringOrdinal& item_ordinal)
-      : app_launcher_id(app_launcher_id), item_ordinal(item_ordinal) {}
+std::vector<AppLauncherId> AppIdsToAppLauncherIds(
+    const std::vector<std::string> app_ids) {
+  std::vector<AppLauncherId> app_launcher_ids(app_ids.size(), AppLauncherId());
+  for (size_t i = 0; i < app_ids.size(); ++i)
+    app_launcher_ids[i] = AppLauncherId(app_ids[i]);
+  return app_launcher_ids;
+}
 
-  AppLauncherId app_launcher_id;
+struct PinInfo {
+  PinInfo(const std::string& app_id, const syncer::StringOrdinal& item_ordinal)
+      : app_id(app_id), item_ordinal(item_ordinal) {}
+
+  std::string app_id;
   syncer::StringOrdinal item_ordinal;
 };
 
@@ -237,26 +252,25 @@
 // to check if app exists in the list.
 class AppTracker {
  public:
-  bool HasApp(const AppLauncherId& app_launcher_id) const {
-    return app_set_.find(app_launcher_id) != app_set_.end();
+  bool HasApp(const std::string& app_id) const {
+    return app_set_.find(app_id) != app_set_.end();
   }
 
-  void AddApp(const AppLauncherId& app_launcher_id) {
-    if (HasApp(app_launcher_id))
+  void AddApp(const std::string& app_id) {
+    if (HasApp(app_id))
       return;
-    app_list_.push_back(app_launcher_id);
-    app_set_.insert(app_launcher_id);
+    app_list_.push_back(app_id);
+    app_set_.insert(app_id);
   }
 
-  void MaybeAddApp(const AppLauncherId& app_launcher_id,
+  void MaybeAddApp(const std::string& app_id,
                    const LauncherControllerHelper* helper,
                    bool check_for_valid_app) {
-    DCHECK_NE(kPinnedAppsPlaceholder, app_launcher_id.ToString());
-    if (check_for_valid_app &&
-        !helper->IsValidIDForCurrentUser(app_launcher_id.ToString())) {
+    DCHECK_NE(kPinnedAppsPlaceholder, app_id);
+    if (check_for_valid_app && !helper->IsValidIDForCurrentUser(app_id)) {
       return;
     }
-    AddApp(app_launcher_id);
+    AddApp(app_id);
   }
 
   void MaybeAddAppFromPref(const base::DictionaryValue* app_pref,
@@ -278,14 +292,14 @@
       return;
     }
 
-    MaybeAddApp(AppLauncherId(app_id), helper, check_for_valid_app);
+    MaybeAddApp(app_id, helper, check_for_valid_app);
   }
 
-  const std::vector<AppLauncherId>& app_list() const { return app_list_; }
+  const std::vector<std::string>& app_list() const { return app_list_; }
 
  private:
-  std::vector<AppLauncherId> app_list_;
-  std::set<AppLauncherId> app_set_;
+  std::vector<std::string> app_list_;
+  std::set<std::string> app_set_;
 };
 
 }  // namespace
@@ -301,28 +315,6 @@
 const char kShelfAlignmentLeft[] = "Left";
 const char kShelfAlignmentRight[] = "Right";
 
-AppLauncherId::AppLauncherId(const std::string& app_id,
-                             const std::string& launch_id)
-    : app_id_(app_id), launch_id_(launch_id) {
-  DCHECK(!app_id.empty());
-}
-
-AppLauncherId::AppLauncherId(const std::string& app_id) : app_id_(app_id) {
-  DCHECK(!app_id.empty());
-}
-
-AppLauncherId::AppLauncherId() {}
-
-AppLauncherId::~AppLauncherId() {}
-
-std::string AppLauncherId::ToString() const {
-  return app_id_ + launch_id_;
-}
-
-bool AppLauncherId::operator<(const AppLauncherId& other) const {
-  return ToString() < other.ToString();
-}
-
 void RegisterChromeLauncherUserPrefs(
     user_prefs::PrefRegistrySyncable* registry) {
   // TODO: If we want to support multiple profiles this will likely need to be
@@ -349,13 +341,6 @@
   registry->RegisterBooleanPref(prefs::kShowLogoutButtonInTray, false);
 }
 
-std::unique_ptr<base::DictionaryValue> CreateAppDict(
-    const AppLauncherId& app_launcher_id) {
-  auto app_value = base::MakeUnique<base::DictionaryValue>();
-  app_value->SetString(kPinnedAppsPrefAppIDPath, app_launcher_id.ToString());
-  return app_value;
-}
-
 ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs,
                                                    int64_t display_id) {
   DCHECK_NE(display_id, display::kInvalidDisplayId);
@@ -450,16 +435,15 @@
       for (const auto& activity : activities) {
         const std::string arc_app_id =
             ArcAppListPrefs::GetAppId(arc_package, activity);
-        apps->MaybeAddApp(AppLauncherId(arc_app_id), helper,
-                          check_for_valid_app);
+        apps->MaybeAddApp(arc_app_id, helper, check_for_valid_app);
       }
     } else {
-      apps->MaybeAddApp(AppLauncherId(app_id), helper, check_for_valid_app);
+      apps->MaybeAddApp(app_id, helper, check_for_valid_app);
     }
   }
 }
 
-std::vector<AppLauncherId> GetPinnedAppsFromPrefsLegacy(
+std::vector<std::string> GetPinnedAppsFromPrefsLegacy(
     const PrefService* prefs,
     const LauncherControllerHelper* helper,
     bool check_for_valid_app) {
@@ -477,7 +461,7 @@
 
   // Check if Chrome is in either of the the preferences lists.
   std::unique_ptr<base::Value> chrome_app(
-      CreateAppDict(AppLauncherId(extension_misc::kChromeAppId)));
+      CreateAppDict(extension_misc::kChromeAppId));
 
   AppTracker apps;
   GetAppsPinnedByPolicy(prefs, helper, check_for_valid_app, &apps);
@@ -487,7 +471,7 @@
     // We need to position the chrome icon relative to its place in the pinned
     // preference list - even if an item of that list isn't shown yet.
     if (i == chrome_icon_index)
-      apps.AddApp(AppLauncherId(extension_misc::kChromeAppId));
+      apps.AddApp(extension_misc::kChromeAppId);
     const base::DictionaryValue* app_pref = nullptr;
     if (!pinned_apps->GetDictionary(i, &app_pref)) {
       LOG(ERROR) << "There is no dictionary for app entry.";
@@ -497,7 +481,7 @@
   }
 
   // If not added yet, the chrome item will be the last item in the list.
-  apps.AddApp(AppLauncherId(extension_misc::kChromeAppId));
+  apps.AddApp(extension_misc::kChromeAppId);
   return apps.app_list();
 }
 
@@ -576,26 +560,26 @@
                             : syncer::StringOrdinal::CreateInitialOrdinal();
 }
 
-std::vector<AppLauncherId> ImportLegacyPinnedApps(
+std::vector<std::string> ImportLegacyPinnedApps(
     const PrefService* prefs,
     LauncherControllerHelper* helper) {
-  std::vector<AppLauncherId> legacy_pins_all =
+  const std::vector<std::string> legacy_pins_all =
       GetPinnedAppsFromPrefsLegacy(prefs, helper, false);
   DCHECK(!legacy_pins_all.empty());
 
   app_list::AppListSyncableService* app_service =
       app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile());
 
-  std::vector<AppLauncherId> legacy_pins_valid;
+  std::vector<std::string> legacy_pins_valid;
   syncer::StringOrdinal last_position =
       syncer::StringOrdinal::CreateInitialOrdinal();
   // Convert to sync item record.
-  for (const auto& app_launcher_id : legacy_pins_all) {
-    DCHECK_NE(kPinnedAppsPlaceholder, app_launcher_id.ToString());
-    app_service->SetPinPosition(app_launcher_id.ToString(), last_position);
+  for (const auto& app_id : legacy_pins_all) {
+    DCHECK_NE(kPinnedAppsPlaceholder, app_id);
+    app_service->SetPinPosition(app_id, last_position);
     last_position = last_position.CreateAfter();
-    if (helper->IsValidIDForCurrentUser(app_launcher_id.ToString()))
-      legacy_pins_valid.push_back(app_launcher_id);
+    if (helper->IsValidIDForCurrentUser(app_id))
+      legacy_pins_valid.push_back(app_id);
   }
 
   // Now process default apps.
@@ -640,8 +624,8 @@
       continue;
     }
 
-    pin_infos.push_back(PinInfo(AppLauncherId(sync_peer.first),
-                                sync_peer.second->item_pin_ordinal));
+    pin_infos.push_back(
+        PinInfo(sync_peer.first, sync_peer.second->item_pin_ordinal));
   }
 
   if (first_run) {
@@ -649,11 +633,12 @@
     sync_preferences::PrefServiceSyncable* const pref_service_syncable =
         PrefServiceSyncableFromProfile(helper->profile());
     if (!pref_service_syncable->IsSyncing())
-      return GetPinnedAppsFromPrefsLegacy(prefs, helper, true);
+      return AppIdsToAppLauncherIds(
+          GetPinnedAppsFromPrefsLegacy(prefs, helper, true));
 
     // We need to import legacy pins model and convert it to sync based
     // model.
-    return ImportLegacyPinnedApps(prefs, helper);
+    return AppIdsToAppLauncherIds(ImportLegacyPinnedApps(prefs, helper));
   }
 
   // Sort pins according their ordinals.
@@ -664,30 +649,27 @@
 
   // Pinned by policy apps appear first, if they were not shown before.
   syncer::StringOrdinal front_position = GetFirstPinPosition(helper->profile());
-  std::vector<AppLauncherId>::const_reverse_iterator it;
+  std::vector<std::string>::const_reverse_iterator it;
   for (it = policy_apps.app_list().rbegin();
        it != policy_apps.app_list().rend(); ++it) {
-    const std::string& app_launcher_id_str = (*it).ToString();
-    if (app_launcher_id_str == kPinnedAppsPlaceholder)
+    const std::string& app_id = *it;
+    if (app_id == kPinnedAppsPlaceholder)
       continue;
 
     // Check if we already processed current app.
-    if (app_service->GetPinPosition(app_launcher_id_str).IsValid())
+    if (app_service->GetPinPosition(app_id).IsValid())
       continue;
 
     // Now move it to the front.
-    pin_infos.insert(pin_infos.begin(),
-                     PinInfo(AppLauncherId((*it).app_id(), (*it).launch_id()),
-                             front_position));
-    app_service->SetPinPosition(app_launcher_id_str, front_position);
+    pin_infos.insert(pin_infos.begin(), PinInfo(*it, front_position));
+    app_service->SetPinPosition(app_id, front_position);
     front_position = front_position.CreateBefore();
   }
 
   // Now insert Chrome browser app if needed.
   if (!app_service->GetPinPosition(extension_misc::kChromeAppId).IsValid()) {
-    pin_infos.insert(
-        pin_infos.begin(),
-        PinInfo(AppLauncherId(extension_misc::kChromeAppId), front_position));
+    pin_infos.insert(pin_infos.begin(),
+                     PinInfo(extension_misc::kChromeAppId, front_position));
     app_service->SetPinPosition(extension_misc::kChromeAppId, front_position);
   }
 
@@ -696,27 +678,35 @@
       const syncer::StringOrdinal arc_host_position =
           GetLastPinPosition(helper->profile());
       pin_infos.insert(pin_infos.begin(),
-                       PinInfo(AppLauncherId(ArcSupportHost::kHostAppId),
-                               arc_host_position));
+                       PinInfo(ArcSupportHost::kHostAppId, arc_host_position));
       app_service->SetPinPosition(ArcSupportHost::kHostAppId,
                                   arc_host_position);
     }
   }
 
   // Convert to AppLauncherId array.
-  std::vector<AppLauncherId> pins(pin_infos.size(), AppLauncherId());
+  std::vector<std::string> pins(pin_infos.size());
   for (size_t i = 0; i < pin_infos.size(); ++i)
-    pins[i] = pin_infos[i].app_launcher_id;
+    pins[i] = pin_infos[i].app_id;
 
-  return pins;
+  return AppIdsToAppLauncherIds(pins);
 }
 
 void RemovePinPosition(Profile* profile, const AppLauncherId& app_launcher_id) {
   DCHECK(profile);
+
+  const std::string& app_id = app_launcher_id.app_id();
+  if (!app_launcher_id.launch_id().empty()) {
+    VLOG(2) << "Syncing remove pin for '" << app_id
+            << "' with non-empty launch id '" << app_launcher_id.launch_id()
+            << "' is not supported.";
+    return;
+  }
+  DCHECK(!app_id.empty());
+
   app_list::AppListSyncableService* app_service =
       app_list::AppListSyncableServiceFactory::GetForProfile(profile);
-  app_service->SetPinPosition(app_launcher_id.ToString(),
-                              syncer::StringOrdinal());
+  app_service->SetPinPosition(app_id, syncer::StringOrdinal());
 }
 
 void SetPinPosition(Profile* profile,
@@ -724,10 +714,19 @@
                     const AppLauncherId& app_launcher_id_before,
                     const std::vector<AppLauncherId>& app_launcher_ids_after) {
   DCHECK(profile);
-  const std::string app_launcher_id_str = app_launcher_id.ToString();
-  const std::string app_launcher_id_before_str =
-      app_launcher_id_before.ToString();
-  DCHECK_NE(app_launcher_id_str, app_launcher_id_before_str);
+
+  const std::string& app_id = app_launcher_id.app_id();
+  if (!app_launcher_id.launch_id().empty()) {
+    VLOG(2) << "Syncing set pin for '" << app_id
+            << "' with non-empty launch id '" << app_launcher_id.launch_id()
+            << "' is not supported.";
+    return;
+  }
+
+  const std::string& app_id_before = app_launcher_id_before.app_id();
+
+  DCHECK(!app_id.empty());
+  DCHECK_NE(app_id, app_id_before);
 
   app_list::AppListSyncableService* app_service =
       app_list::AppListSyncableServiceFactory::GetForProfile(profile);
@@ -736,21 +735,17 @@
     return;
 
   syncer::StringOrdinal position_before =
-      app_launcher_id_before_str.empty()
-          ? syncer::StringOrdinal()
-          : app_service->GetPinPosition(app_launcher_id_before_str);
+      app_id_before.empty() ? syncer::StringOrdinal()
+                            : app_service->GetPinPosition(app_id_before);
   syncer::StringOrdinal position_after;
   for (const auto& app_launcher_id_after : app_launcher_ids_after) {
-    const std::string app_launcher_id_after_str =
-        app_launcher_id_after.ToString();
-    DCHECK_NE(app_launcher_id_after_str, app_launcher_id_str);
-    DCHECK_NE(app_launcher_id_after_str, app_launcher_id_before_str);
-    syncer::StringOrdinal position =
-        app_service->GetPinPosition(app_launcher_id_after_str);
+    const std::string& app_id_after = app_launcher_id_after.app_id();
+    DCHECK_NE(app_id_after, app_id);
+    DCHECK_NE(app_id_after, app_id_before);
+    syncer::StringOrdinal position = app_service->GetPinPosition(app_id_after);
     DCHECK(position.IsValid());
     if (!position.IsValid()) {
-      LOG(ERROR) << "Sync pin position was not found for "
-                 << app_launcher_id_after_str;
+      LOG(ERROR) << "Sync pin position was not found for " << app_id_after;
       continue;
     }
     if (!position_before.IsValid() || !position.Equals(position_before)) {
@@ -768,7 +763,7 @@
     pin_position = position_after.CreateBefore();
   else
     pin_position = syncer::StringOrdinal::CreateInitialOrdinal();
-  app_service->SetPinPosition(app_launcher_id_str, pin_position);
+  app_service->SetPinPosition(app_id, pin_position);
 }
 
 }  // namespace launcher
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.h b/chrome/browser/ui/ash/chrome_launcher_prefs.h
index 1ec582a..f54481c 100644
--- a/chrome/browser/ui/ash/chrome_launcher_prefs.h
+++ b/chrome/browser/ui/ash/chrome_launcher_prefs.h
@@ -17,10 +17,6 @@
 class PrefService;
 class Profile;
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace sync_preferences {
 class PrefServiceSyncable;
 }
@@ -32,6 +28,8 @@
 namespace ash {
 namespace launcher {
 
+class AppLauncherId;
+
 // Path within the dictionary entries in the prefs::kPinnedLauncherApps list
 // specifying the extension ID of the app to be pinned by that entry.
 extern const char kPinnedAppsPrefAppIDPath[];
@@ -51,46 +49,9 @@
 extern const char kShelfAlignmentLeft[];
 extern const char kShelfAlignmentRight[];
 
-// A unique chrome launcher id used to identify a shelf item. This class is a
-// wrapper for the chrome launcher identifier. |app_launcher_id_| includes the
-// |app_id| and the |launch_id|. The |app_id| is the application id associated
-// with a set of windows. The |launch_id| is an id that can be passed to an app
-// when launched in order to support multiple shelf items per app. This id is
-// used together with the |app_id| to uniquely identify each shelf item that
-// has the same |app_id|. The |app_id| must not be empty.
-class AppLauncherId {
- public:
-  AppLauncherId(const std::string& app_id, const std::string& launch_id);
-  // Creates an AppLauncherId with an empty |launch_id|.
-  explicit AppLauncherId(const std::string& app_id);
-  // Empty constructor for pre-allocating.
-  AppLauncherId();
-  ~AppLauncherId();
-
-  AppLauncherId(const AppLauncherId& app_launcher_id) = default;
-  AppLauncherId(AppLauncherId&& app_launcher_id) = default;
-  AppLauncherId& operator=(const AppLauncherId& other) = default;
-
-  std::string ToString() const;
-  const std::string& app_id() const { return app_id_; }
-  const std::string& launch_id() const { return launch_id_; }
-
-  bool operator<(const AppLauncherId& other) const;
-
- private:
-  // The application id associated with a set of windows.
-  std::string app_id_;
-  // An id that can be passed to an app when launched in order to support
-  // multiple shelf items per app.
-  std::string launch_id_;
-};
-
 void RegisterChromeLauncherUserPrefs(
     user_prefs::PrefRegistrySyncable* registry);
 
-std::unique_ptr<base::DictionaryValue> CreateAppDict(
-    const AppLauncherId& app_launcher_id);
-
 // Get or set the shelf auto hide behavior preference for a particular display.
 ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs,
                                                    int64_t display_id);
@@ -109,13 +70,15 @@
     const PrefService* prefs,
     LauncherControllerHelper* helper);
 
-// Removes information about pin position from sync model for the app.
+// Removes information about pin position from sync model for the app. Note,
+// |app_launcher_id| with non-empty launch_id is not supported.
 void RemovePinPosition(Profile* profile, const AppLauncherId& app_launcher_id);
 
 // Updates information about pin position in sync model for the app
 // |app_launcher_id|. |app_launcher_id_before| optionally specifies an app that
 // exists right before the target app. |app_launcher_ids_after| optionally
 // specifies sorted by position apps that exist right after the target app.
+// Note, |app_launcher_id| with non-empty launch_id is not supported.
 void SetPinPosition(Profile* profile,
                     const AppLauncherId& app_launcher_id,
                     const AppLauncherId& app_launcher_id_before,
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
index b42c02a..872431e8 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
@@ -92,33 +92,25 @@
   }
 }
 
-AppShortcutLauncherItemController::~AppShortcutLauncherItemController() {
-}
-
-void AppShortcutLauncherItemController::Launch(ash::LaunchSource source,
-                                               int event_flags) {
-  // Launching an app replaces shortcut item controller to app controller. As
-  // result app_id_, launch_id_ are deleted during this call. Use local copies
-  // to prevent crash condition.
-  launcher_controller()->LaunchAppWithLaunchId(
-      std::string(app_id()), std::string(launch_id()), source, event_flags);
-}
+AppShortcutLauncherItemController::~AppShortcutLauncherItemController() {}
 
 ash::ShelfItemDelegate::PerformedAction
 AppShortcutLauncherItemController::Activate(ash::LaunchSource source) {
   content::WebContents* content = GetLRUApplication();
   if (!content) {
-    if (IsV2App()) {
-      // Ideally we come here only once. After that ShellLauncherItemController
-      // will take over when the shell window gets opened. However there are
-      // apps which take a lot of time for pre-processing (like the files app)
-      // before they open a window. Since there is currently no other way to
-      // detect if an app was started we suppress any further clicks within a
-      // special time out.
-      if (!AllowNextLaunchAttempt())
-        return kNoAction;
-    }
-    Launch(source, ui::EF_NONE);
+    // Ideally we come here only once. After that ShellLauncherItemController
+    // will take over when the shell window gets opened. However there are apps
+    // which take a lot of time for pre-processing (like the files app) before
+    // they open a window. Since there is currently no other way to detect if an
+    // app was started we suppress any further clicks within a special time out.
+    if (IsV2App() && !AllowNextLaunchAttempt())
+      return kNoAction;
+
+    // Launching some items replaces this item controller instance, which
+    // destroys the app and launch id strings; making copies avoid crashes.
+    launcher_controller()->LaunchApp(
+        ash::launcher::AppLauncherId(app_id(), launch_id()), source,
+        ui::EF_NONE);
     return kNewWindowCreated;
   }
   return ActivateContent(content);
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
index 801c28c..a5c5a55 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
@@ -41,7 +41,6 @@
   std::vector<content::WebContents*> GetRunningApplications();
 
   // LauncherItemController overrides:
-  void Launch(ash::LaunchSource source, int event_flags) override;
   ash::ShelfItemDelegate::PerformedAction Activate(
       ash::LaunchSource source) override;
   ash::ShelfItemDelegate::PerformedAction ItemSelected(
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
index a5444c49..6670fe4 100644
--- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
@@ -69,11 +69,6 @@
     last_active_window_ = app_window;
 }
 
-void AppWindowLauncherItemController::Launch(ash::LaunchSource source,
-                                             int event_flags) {
-  launcher_controller()->LaunchApp(app_id(), source, ui::EF_NONE);
-}
-
 ash::ShelfItemDelegate::PerformedAction
 AppWindowLauncherItemController::Activate(ash::LaunchSource source) {
   DCHECK(!windows_.empty());
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
index 5650cbc8..d6827ab 100644
--- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
@@ -43,7 +43,6 @@
   ui::BaseWindow* GetAppWindow(aura::Window* window);
 
   // LauncherItemController overrides:
-  void Launch(ash::LaunchSource source, int event_flags) override;
   ash::ShelfItemDelegate::PerformedAction Activate(
       ash::LaunchSource source) override;
   AppWindowLauncherItemController* AsAppWindowLauncherItemController() override;
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
index f16a57b..dbeb0452 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
@@ -18,7 +18,7 @@
     ChromeLauncherController* controller,
     int event_flags,
     const base::WeakPtr<ArcAppDeferredLauncherController>& host)
-    : LauncherItemController(arc_app_id, "", controller),
+    : LauncherItemController(arc_app_id, std::string(), controller),
       event_flags_(event_flags),
       host_(host),
       start_time_(base::Time::Now()) {}
@@ -47,9 +47,6 @@
     host_->Close(app_id());
 }
 
-void ArcAppDeferredLauncherItemController::Launch(ash::LaunchSource source,
-                                                  int event_flags) {}
-
 ash::ShelfItemDelegate::PerformedAction
 ArcAppDeferredLauncherItemController::Activate(ash::LaunchSource source) {
   return ash::ShelfItemDelegate::kNoAction;
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
index fce450e..7da11ea 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
@@ -39,7 +39,6 @@
   void Close() override;
 
   // LauncherItemController overrides:
-  void Launch(ash::LaunchSource source, int event_flags) override;
   ash::ShelfItemDelegate::PerformedAction Activate(
       ash::LaunchSource source) override;
 
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
index 12da626..df3fc2d2 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
@@ -19,7 +19,7 @@
 ArcAppWindowLauncherItemController::ArcAppWindowLauncherItemController(
     const std::string& arc_app_id,
     ChromeLauncherController* controller)
-    : AppWindowLauncherItemController(arc_app_id, "", controller) {}
+    : AppWindowLauncherItemController(arc_app_id, std::string(), controller) {}
 
 ArcAppWindowLauncherItemController::~ArcAppWindowLauncherItemController() {}
 
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index da46397..0a838d62 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -64,13 +64,12 @@
     ChromeLauncherController* launcher_controller,
     ash::ShelfModel* shelf_model)
     : LauncherItemController(extension_misc::kChromeAppId,
-                             "",
+                             std::string(),
                              launcher_controller),
       shelf_model_(shelf_model) {}
 
 BrowserShortcutLauncherItemController::
-    ~BrowserShortcutLauncherItemController() {
-}
+    ~BrowserShortcutLauncherItemController() {}
 
 void BrowserShortcutLauncherItemController::UpdateBrowserItemState() {
   // Determine the new browser's active state and change if necessary.
@@ -129,10 +128,6 @@
           launcher_controller()->GetShelfIDForWebContents(web_contents));
 }
 
-void BrowserShortcutLauncherItemController::Launch(ash::LaunchSource source,
-                                                   int event_flags) {
-}
-
 ash::ShelfItemDelegate::PerformedAction
 BrowserShortcutLauncherItemController::Activate(ash::LaunchSource source) {
   Browser* last_browser =
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
index d9e00eb..e84a40d 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -43,7 +43,6 @@
   bool IsListOfActiveBrowserEmpty();
 
   // LauncherItemController overrides:
-  void Launch(ash::LaunchSource source, int event_flags) override;
   ShelfItemDelegate::PerformedAction Activate(
       ash::LaunchSource source) override;
   ash::ShelfItemDelegate::PerformedAction ItemSelected(
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index 5159b6df..2558c41 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -36,19 +36,10 @@
   OnInit();
 }
 
-void ChromeLauncherController::LaunchApp(const std::string& app_id,
+void ChromeLauncherController::LaunchApp(ash::launcher::AppLauncherId id,
                                          ash::LaunchSource source,
                                          int event_flags) {
-  launcher_controller_helper_->LaunchApp(app_id, source, event_flags);
-}
-
-void ChromeLauncherController::LaunchAppWithLaunchId(
-    const std::string& app_id,
-    const std::string& launch_id,
-    ash::LaunchSource source,
-    int event_flags) {
-  launcher_controller_helper_->LaunchAppWithLaunchId(app_id, launch_id, source,
-                                                     event_flags);
+  launcher_controller_helper_->LaunchApp(id, source, event_flags);
 }
 
 ChromeLauncherController::ChromeLauncherController() : observer_binding_(this) {
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
index b40a511..5aa42d4 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/app_icon_loader.h"
 #include "chrome/browser/ui/app_icon_loader_delegate.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
+#include "chrome/browser/ui/ash/app_launcher_id.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_types.h"
 #include "chrome/browser/ui/ash/launcher/settings_window_observer.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
@@ -134,19 +135,12 @@
   // Returns true if the specified item is for a platform app.
   virtual bool IsPlatformApp(ash::ShelfID id) = 0;
 
-  // Opens a new instance of the application identified by |app_id|.
+  // Opens a new instance of the application identified by the AppLauncherId.
   // Used by the app-list, and by pinned-app shelf items.
-  void LaunchApp(const std::string& app_id,
+  void LaunchApp(ash::launcher::AppLauncherId id,
                  ash::LaunchSource source,
                  int event_flags);
 
-  // As above but includes |launch_id|, an id that can be passed to an app when
-  // launched in order to support multiple shelf items per app.
-  void LaunchAppWithLaunchId(const std::string& app_id,
-                             const std::string& launch_id,
-                             ash::LaunchSource source,
-                             int event_flags);
-
   // If |app_id| is running, reactivates the app's most recently active window,
   // otherwise launches and activates the app.
   // Used by the app-list, and by pinned-app shelf items.
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
index 6d6f16d..c6f5978 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ui/ash/app_launcher_id.h"
 #include "chrome/browser/ui/ash/app_sync_ui_state.h"
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 #include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h"
@@ -414,7 +415,12 @@
   LauncherItemController* controller = GetLauncherItemController(id);
   if (!controller)
     return;  // In case invoked from menu and item closed while menu up.
-  controller->Launch(ash::LAUNCH_FROM_UNKNOWN, event_flags);
+
+  // Launching some items replaces the associated item controller instance,
+  // which destroys the app and launch id strings; making copies avoid crashes.
+  LaunchApp(ash::launcher::AppLauncherId(controller->app_id(),
+                                         controller->launch_id()),
+            ash::LAUNCH_FROM_UNKNOWN, event_flags);
 }
 
 void ChromeLauncherControllerImpl::Close(ash::ShelfID id) {
@@ -454,11 +460,11 @@
   // Create a temporary application launcher item and use it to see if there are
   // running instances.
   std::unique_ptr<AppShortcutLauncherItemController> app_controller(
-      AppShortcutLauncherItemController::Create(app_id, "", this));
+      AppShortcutLauncherItemController::Create(app_id, std::string(), this));
   if (!app_controller->GetRunningApplications().empty())
     app_controller->Activate(source);
   else
-    LaunchApp(app_id, source, event_flags);
+    LaunchApp(ash::launcher::AppLauncherId(app_id), source, event_flags);
 }
 
 void ChromeLauncherControllerImpl::SetLauncherItemImage(
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
index 42a4047d..f4af721d 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
+#include "chrome/browser/ui/ash/app_launcher_id.h"
 #include "chrome/browser/ui/ash/app_list/test/app_list_service_ash_test_api.h"
 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h"
@@ -925,9 +926,9 @@
   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB,
                          WindowOpenDisposition::NEW_BACKGROUND_TAB);
   EXPECT_EQ(++tab_count, tab_strip->count());
-  controller_->LaunchApp(last_loaded_extension_id(),
-                                               ash::LAUNCH_FROM_UNKNOWN,
-                                               0);
+  controller_->LaunchApp(
+      ash::launcher::AppLauncherId(last_loaded_extension_id()),
+      ash::LAUNCH_FROM_UNKNOWN, 0);
 }
 
 // Confirm that clicking a icon for an app running in one of 2 maxmized windows
@@ -977,12 +978,11 @@
 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchApp) {
   TabStripModel* tab_strip = browser()->tab_strip_model();
   int tab_count = tab_strip->count();
-  const Extension* extension =
-      LoadExtension(test_data_dir_.AppendASCII("app1"));
-
-  controller_->LaunchApp(extension->id(), ash::LAUNCH_FROM_UNKNOWN, 0);
+  ash::launcher::AppLauncherId id(
+      LoadExtension(test_data_dir_.AppendASCII("app1"))->id());
+  controller_->LaunchApp(id, ash::LAUNCH_FROM_UNKNOWN, 0);
   EXPECT_EQ(++tab_count, tab_strip->count());
-  controller_->LaunchApp(extension->id(), ash::LAUNCH_FROM_UNKNOWN, 0);
+  controller_->LaunchApp(id, ash::LAUNCH_FROM_UNKNOWN, 0);
   EXPECT_EQ(++tab_count, tab_strip->count());
 }
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
index ef0f41a..7421631b 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
@@ -54,6 +54,7 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/arc/arc_default_app_list.h"
 #include "chrome/browser/ui/apps/chrome_app_delegate.h"
+#include "chrome/browser/ui/ash/app_launcher_id.h"
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
 #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h"
 #include "chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_controller.h"
@@ -260,7 +261,6 @@
   ~TestV2AppLauncherItemController() override {}
 
   // Override for LauncherItemController:
-  void Launch(ash::LaunchSource source, int event_flags) override {}
   ash::ShelfItemDelegate::PerformedAction Activate(
       ash::LaunchSource source) override {
     return kExistingWindowActivated;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc
index e51e737c3..d5948dd 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc
@@ -8,6 +8,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/ash/app_launcher_id.h"
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h"
 #include "extensions/grit/extensions_browser_resources.h"
@@ -34,7 +35,8 @@
  private:
   // ash::mojom::ShelfItemDelegate:
   void LaunchItem() override {
-    controller_->LaunchApp(app_id_, ash::LAUNCH_FROM_UNKNOWN, ui::EF_NONE);
+    controller_->LaunchApp(ash::launcher::AppLauncherId(app_id_),
+                           ash::LAUNCH_FROM_UNKNOWN, ui::EF_NONE);
   }
   void ExecuteCommand(uint32_t command_id, int32_t event_flags) override {
     NOTIMPLEMENTED();
@@ -279,7 +281,7 @@
 
   for (const auto& app_launcher_id : pinned_apps) {
     const std::string app_id = app_launcher_id.app_id();
-    if (app_launcher_id.ToString() == ash::launcher::kPinnedAppsPlaceholder)
+    if (app_launcher_id.app_id() == ash::launcher::kPinnedAppsPlaceholder)
       continue;
 
     ash::mojom::ShelfItemPtr item(ash::mojom::ShelfItem::New());
diff --git a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
index 28a0ee2..4d0cf7d 100644
--- a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
@@ -169,17 +169,10 @@
   return true;
 }
 
-void LauncherControllerHelper::LaunchApp(const std::string& app_id,
+void LauncherControllerHelper::LaunchApp(ash::launcher::AppLauncherId id,
                                          ash::LaunchSource source,
                                          int event_flags) {
-  LaunchAppWithLaunchId(app_id, "", source, event_flags);
-}
-
-void LauncherControllerHelper::LaunchAppWithLaunchId(
-    const std::string& app_id,
-    const std::string& launch_id,
-    ash::LaunchSource source,
-    int event_flags) {
+  const std::string& app_id = id.app_id();
   const ArcAppListPrefs* arc_prefs = GetArcAppListPrefs();
   if (arc_prefs && arc_prefs->IsRegistered(app_id)) {
     arc::LaunchApp(profile_, app_id, event_flags);
@@ -215,7 +208,7 @@
     params.override_url = net::AppendQueryParameter(
         extension_url, extension_urls::kWebstoreSourceField, source_value);
   }
-  params.launch_id = launch_id;
+  params.launch_id = id.launch_id();
 
   OpenApplication(params);
 }
@@ -225,8 +218,9 @@
 }
 
 void LauncherControllerHelper::ExtensionEnableFlowFinished() {
-  LaunchApp(extension_enable_flow_->extension_id(), ash::LAUNCH_FROM_UNKNOWN,
-            ui::EF_NONE);
+  LaunchApp(
+      ash::launcher::AppLauncherId(extension_enable_flow_->extension_id()),
+      ash::LAUNCH_FROM_UNKNOWN, ui::EF_NONE);
   extension_enable_flow_.reset();
 }
 
diff --git a/chrome/browser/ui/ash/launcher/launcher_controller_helper.h b/chrome/browser/ui/ash/launcher/launcher_controller_helper.h
index 97045db..33e64ab 100644
--- a/chrome/browser/ui/ash/launcher/launcher_controller_helper.h
+++ b/chrome/browser/ui/ash/launcher/launcher_controller_helper.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/ui/ash/app_launcher_id.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_types.h"
 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
 
@@ -41,15 +42,10 @@
   // Note that already running applications are ignored by the restore process.
   virtual bool IsValidIDForCurrentUser(const std::string& id) const;
 
-  void LaunchApp(const std::string& app_id,
+  void LaunchApp(ash::launcher::AppLauncherId id,
                  ash::LaunchSource source,
                  int event_flags);
 
-  void LaunchAppWithLaunchId(const std::string& app_id,
-                             const std::string& launch_id,
-                             ash::LaunchSource source,
-                             int event_flags);
-
   virtual ArcAppListPrefs* GetArcAppListPrefs() const;
 
   Profile* profile() { return profile_; }
diff --git a/chrome/browser/ui/ash/launcher/launcher_item_controller.h b/chrome/browser/ui/ash/launcher/launcher_item_controller.h
index 3661e81c..4378732 100644
--- a/chrome/browser/ui/ash/launcher/launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/launcher_item_controller.h
@@ -19,6 +19,8 @@
 
 // LauncherItemController is used by ChromeLauncherController to track one
 // or more windows associated with a shelf item.
+// TODO (khmel): Consider using ash::launcher::AppLauncherId instead of pair
+// |app_id| and |launch_id|.
 class LauncherItemController : public ash::ShelfItemDelegate {
  public:
   LauncherItemController(const std::string& app_id,
@@ -47,9 +49,6 @@
     image_set_by_controller_ = image_set_by_controller;
   }
 
-  // Launches a new instance of the app associated with this item.
-  virtual void Launch(ash::LaunchSource source, int event_flags) = 0;
-
   // Shows and activates the most-recently-active window associated with the
   // item, or launches the item if it is not currently open.
   // Returns the action performed by activating the item.
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm
index 6cf0a8d..fb43143 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor_unittest.mm
@@ -19,6 +19,7 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/ocmock_extensions.h"
+#import "ui/base/cocoa/touch_bar_forward_declarations.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
 
 using ::testing::Return;
@@ -195,6 +196,14 @@
   [editor_ display];
 }
 
+// Tests that the Touch Bar is nothing.
+TEST_F(AutocompleteTextFieldEditorTest, TouchBarTest) {
+  if ([field_ respondsToSelector:@selector(touchBar)]) {
+    NSTouchBar* touch_bar = [field_ performSelector:@selector(touchBar)];
+    EXPECT_FALSE(touch_bar);
+  }
+}
+
 // Test that -paste: is correctly delegated to the observer.
 TEST_F(AutocompleteTextFieldEditorObserverTest, Paste) {
   EXPECT_CALL(field_observer_, OnPaste());
diff --git a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
index 3cca551..91487c1 100644
--- a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
@@ -39,6 +39,22 @@
 // Maximum height of the credential list. The unit is one row height.
 constexpr CGFloat kMaxHeightAccounts = 3.5;
 
+}  // namespace
+
+// An image view that consumes the mouse click.
+@interface InfoImageView : NSImageView
+@end
+
+@implementation InfoImageView
+- (void)mouseDown:(NSEvent*)theEvent {
+  if (theEvent.type != NSLeftMouseDown) {
+    [super mouseDown:theEvent];
+  }
+}
+@end
+
+namespace {
+
 NSImageView* IconForPSL(const NSRect& parentRect, const std::string& tooltip) {
   NSImage* image = gfx::NSImageFromImageSkia(gfx::CreateVectorIcon(
       gfx::VectorIconId::INFO_OUTLINE, gfx::kChromeIconGrey));
@@ -48,7 +64,7 @@
       NSMinY(parentRect) + (NSHeight(parentRect) - kInfoIconSize) / 2,
       kInfoIconSize, kInfoIconSize);
   base::scoped_nsobject<NSImageView> icon(
-      [[NSImageView alloc] initWithFrame:rect]);
+      [[InfoImageView alloc] initWithFrame:rect]);
   [icon setImage:image];
   [icon setToolTip:base::SysUTF8ToNSString(tooltip)];
   return icon.autorelease();
diff --git a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
index 3f34aeea..62b634fe 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
@@ -1594,13 +1594,10 @@
       showLock = item.signed_in &&
           profiles::IsLockAvailable(browser_->profile());
     } else {
-      NSButton* otherProfileView = [self createOtherProfileView:i];
-      if (!firstProfileView_) {
-        firstProfileView_ = otherProfileView;
-      }
-      [otherProfiles addObject:otherProfileView];
+      [otherProfiles addObject:[self createOtherProfileView:i]];
     }
   }
+  firstProfileView_ = [otherProfiles lastObject];
   if (!currentProfileView)  // Guest windows don't have an active profile.
     currentProfileView = [self createGuestProfileView];
 
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index 116c0211..ac56c5b 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -1127,6 +1127,10 @@
     }
     isLastTabPinned = isPinned;
 
+    // Flip if in RTL mode.
+    tabFrame.origin.x =
+        FlipXInView(tabStripView_, tabFrame.size.width, tabFrame.origin.x);
+
     if (laidOutNonPinnedTabs > numberOfNonPinnedTabs) {
       // There is not enough space to fit this tab.
       tabFrame.size.width = 0;
@@ -1145,9 +1149,6 @@
       }
     }
 
-    tabFrame.origin.x =
-        FlipXInView(tabStripView_, tabFrame.size.width, tabFrame.origin.x);
-
     // Check the frame by identifier to avoid redundant calls to animator.
     id frameTarget = visible && animate ? [[tab view] animator] : [tab view];
     NSValue* identifier = [NSValue valueWithPointer:[tab view]];
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc
index e651d3f..8112502a 100644
--- a/chrome/browser/ui/libgtkui/gtk_ui.cc
+++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -364,25 +364,6 @@
   return GetDpi() / kDefaultDPI;
 }
 
-// Returns the font size for the *raw* device scale factor in points.
-// The |ui_device_scale_factor| is used to cancel the scale to be applied by UI
-// and to compensate the scale when the device_scale_factor is floored.
-double GetFontSizePixelsInPoint(float ui_device_scale_factor) {
-  // There are 72 points in an inch.
-  double point = GetDpi() / 72.0;
-
-  // Take device_scale_factor into account — if Chrome already scales the
-  // entire UI up by 2x, we should not also scale up.
-  point /= ui_device_scale_factor;
-
-  // Allow the scale lower than 1.0 only for fonts. Don't always use
-  // the raw value however, because the 1.0~1.3 is rounded to 1.0.
-  float raw_scale = GetRawDeviceScaleFactor();
-  if (raw_scale < 1.0f)
-    return point * raw_scale / ui_device_scale_factor;
-  return point;
-}
-
 views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() {
   std::unique_ptr<base::Environment> env(base::Environment::Create());
   switch (base::nix::GetDesktopEnvironment(env.get())) {
@@ -841,6 +822,10 @@
   colors_[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT] =
       color_utils::BlendTowardOppositeLuma(toolbar_text_color, 50);
 
+  // Color drawn around the location bar.
+  colors_[ThemeProperties::COLOR_LOCATION_BAR_BORDER] =
+      GetBorderColor("GtkToolbar#toolbar GtkEntry#entry");
+
   inactive_selection_bg_color_ =
       GetBgColor("GtkEntry#entry:backdrop #selection:selected");
   inactive_selection_fg_color_ =
@@ -990,8 +975,8 @@
     // Round the value when converting to pixels to match GTK's logic.
     const double size_points = pango_font_description_get_size(desc) /
                                static_cast<double>(PANGO_SCALE);
-    default_font_size_pixels_ = static_cast<int>(
-        GetFontSizePixelsInPoint(GetDeviceScaleFactor()) * size_points);
+    default_font_size_pixels_ =
+        static_cast<int>(kDefaultDPI / 72.0 * size_points + 0.5);
     query.point_size = static_cast<int>(size_points);
   }
 
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc
index 72267d28..8c3e178 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -91,6 +91,7 @@
   prefs::kWebKitMinimumFontSize,
   prefs::kWebKitMinimumLogicalFontSize,
   prefs::kWebKitPluginsEnabled,
+  prefs::kWebKitEncryptedMediaEnabled,
   prefs::kWebkitTabsToLinks,
   prefs::kWebKitTextAreasAreResizable,
   prefs::kWebKitWebSecurityEnabled,
@@ -522,6 +523,8 @@
                                 pref_defaults.loads_images_automatically);
   registry->RegisterBooleanPref(prefs::kWebKitPluginsEnabled,
                                 pref_defaults.plugins_enabled);
+  registry->RegisterBooleanPref(prefs::kWebKitEncryptedMediaEnabled,
+                                pref_defaults.encrypted_media_enabled);
   registry->RegisterBooleanPref(prefs::kWebKitDomPasteEnabled,
                                 pref_defaults.dom_paste_enabled);
   registry->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable,
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc
index f3b2e23..e5e2ac7 100644
--- a/chrome/browser/ui/search/search_ipc_router.cc
+++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -204,8 +204,7 @@
   delegate_->FocusOmnibox(state);
 }
 
-void SearchIPCRouter::SearchBoxDeleteMostVisitedItem(int page_seq_no,
-                                                     const GURL& url) {
+void SearchIPCRouter::DeleteMostVisitedItem(int page_seq_no, const GURL& url) {
   if (!IsRenderedInInstantProcess(web_contents()))
     return;
   if (page_seq_no != commit_counter_)
@@ -218,8 +217,8 @@
   delegate_->OnDeleteMostVisitedItem(url);
 }
 
-void SearchIPCRouter::SearchBoxUndoMostVisitedDeletion(int page_seq_no,
-                                                       const GURL& url) {
+void SearchIPCRouter::UndoMostVisitedDeletion(int page_seq_no,
+                                              const GURL& url) {
   if (!IsRenderedInInstantProcess(web_contents()))
     return;
   if (page_seq_no != commit_counter_)
@@ -232,7 +231,7 @@
   delegate_->OnUndoMostVisitedDeletion(url);
 }
 
-void SearchIPCRouter::SearchBoxUndoAllMostVisitedDeletions(int page_seq_no) {
+void SearchIPCRouter::UndoAllMostVisitedDeletions(int page_seq_no) {
   if (!IsRenderedInInstantProcess(web_contents()))
     return;
   if (page_seq_no != commit_counter_)
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h
index 43398249..dd66614 100644
--- a/chrome/browser/ui/search/search_ipc_router.h
+++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -175,11 +175,9 @@
   void InstantSupportDetermined(int page_seq_no,
                                 bool supports_instant) override;
   void FocusOmnibox(int page_id, OmniboxFocusState state) override;
-  void SearchBoxDeleteMostVisitedItem(int page_seq_no,
-                                      const GURL& url) override;
-  void SearchBoxUndoMostVisitedDeletion(int page_seq_no,
-                                        const GURL& url) override;
-  void SearchBoxUndoAllMostVisitedDeletions(int page_seq_no) override;
+  void DeleteMostVisitedItem(int page_seq_no, const GURL& url) override;
+  void UndoMostVisitedDeletion(int page_seq_no, const GURL& url) override;
+  void UndoAllMostVisitedDeletions(int page_seq_no) override;
   void LogEvent(int page_seq_no,
                 NTPLoggingEventType event,
                 base::TimeDelta time) override;
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc
index bb7db73..cc5e03b 100644
--- a/chrome/browser/ui/search/search_ipc_router_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -369,8 +369,8 @@
   EXPECT_CALL(*policy, ShouldProcessDeleteMostVisitedItem()).Times(1)
       .WillOnce(testing::Return(true));
 
-  GetSearchIPCRouter().SearchBoxDeleteMostVisitedItem(GetSearchIPCRouterSeqNo(),
-                                                      item_url);
+  GetSearchIPCRouter().DeleteMostVisitedItem(GetSearchIPCRouterSeqNo(),
+                                             item_url);
 }
 
 TEST_F(SearchIPCRouterTest, IgnoreDeleteMostVisitedItemMsg) {
@@ -382,8 +382,8 @@
   EXPECT_CALL(*policy, ShouldProcessDeleteMostVisitedItem()).Times(1)
       .WillOnce(testing::Return(false));
 
-  GetSearchIPCRouter().SearchBoxDeleteMostVisitedItem(GetSearchIPCRouterSeqNo(),
-                                                      item_url);
+  GetSearchIPCRouter().DeleteMostVisitedItem(GetSearchIPCRouterSeqNo(),
+                                             item_url);
 }
 
 TEST_F(SearchIPCRouterTest, ProcessUndoMostVisitedDeletionMsg) {
@@ -395,8 +395,8 @@
   EXPECT_CALL(*policy, ShouldProcessUndoMostVisitedDeletion()).Times(1)
       .WillOnce(testing::Return(true));
 
-  GetSearchIPCRouter().SearchBoxUndoMostVisitedDeletion(
-      GetSearchIPCRouterSeqNo(), item_url);
+  GetSearchIPCRouter().UndoMostVisitedDeletion(GetSearchIPCRouterSeqNo(),
+                                               item_url);
 }
 
 TEST_F(SearchIPCRouterTest, IgnoreUndoMostVisitedDeletionMsg) {
@@ -408,8 +408,8 @@
   EXPECT_CALL(*policy, ShouldProcessUndoMostVisitedDeletion()).Times(1)
       .WillOnce(testing::Return(false));
 
-  GetSearchIPCRouter().SearchBoxUndoMostVisitedDeletion(
-      GetSearchIPCRouterSeqNo(), item_url);
+  GetSearchIPCRouter().UndoMostVisitedDeletion(GetSearchIPCRouterSeqNo(),
+                                               item_url);
 }
 
 TEST_F(SearchIPCRouterTest, ProcessUndoAllMostVisitedDeletionsMsg) {
@@ -420,8 +420,7 @@
   EXPECT_CALL(*policy, ShouldProcessUndoAllMostVisitedDeletions()).Times(1)
       .WillOnce(testing::Return(true));
 
-  GetSearchIPCRouter().SearchBoxUndoAllMostVisitedDeletions(
-      GetSearchIPCRouterSeqNo());
+  GetSearchIPCRouter().UndoAllMostVisitedDeletions(GetSearchIPCRouterSeqNo());
 }
 
 TEST_F(SearchIPCRouterTest, IgnoreUndoAllMostVisitedDeletionsMsg) {
@@ -432,8 +431,7 @@
   EXPECT_CALL(*policy, ShouldProcessUndoAllMostVisitedDeletions()).Times(1)
       .WillOnce(testing::Return(false));
 
-  GetSearchIPCRouter().SearchBoxUndoAllMostVisitedDeletions(
-      GetSearchIPCRouterSeqNo());
+  GetSearchIPCRouter().UndoAllMostVisitedDeletions(GetSearchIPCRouterSeqNo());
 }
 
 TEST_F(SearchIPCRouterTest, IgnoreMessageIfThePageIsNotActive) {
@@ -451,15 +449,15 @@
 
   EXPECT_CALL(*mock_delegate(), OnDeleteMostVisitedItem(item_url)).Times(0);
   EXPECT_CALL(*policy, ShouldProcessDeleteMostVisitedItem()).Times(0);
-  GetSearchIPCRouter().SearchBoxDeleteMostVisitedItem(page_seq_no, item_url);
+  GetSearchIPCRouter().DeleteMostVisitedItem(page_seq_no, item_url);
 
   EXPECT_CALL(*mock_delegate(), OnUndoMostVisitedDeletion(item_url)).Times(0);
   EXPECT_CALL(*policy, ShouldProcessUndoMostVisitedDeletion()).Times(0);
-  GetSearchIPCRouter().SearchBoxUndoMostVisitedDeletion(page_seq_no, item_url);
+  GetSearchIPCRouter().UndoMostVisitedDeletion(page_seq_no, item_url);
 
   EXPECT_CALL(*mock_delegate(), OnUndoAllMostVisitedDeletions()).Times(0);
   EXPECT_CALL(*policy, ShouldProcessUndoAllMostVisitedDeletions()).Times(0);
-  GetSearchIPCRouter().SearchBoxUndoAllMostVisitedDeletions(page_seq_no);
+  GetSearchIPCRouter().UndoAllMostVisitedDeletions(page_seq_no);
 
   EXPECT_CALL(*mock_delegate(), FocusOmnibox(OMNIBOX_FOCUS_VISIBLE)).Times(0);
   EXPECT_CALL(*policy, ShouldProcessFocusOmnibox(is_active_tab)).Times(0);
diff --git a/chrome/browser/ui/views/ash/PRESUBMIT.py b/chrome/browser/ui/views/ash/PRESUBMIT.py
deleted file mode 100644
index f39f299b..0000000
--- a/chrome/browser/ui/views/ash/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for ash.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index c3d7f7ce..a9692e2 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -644,10 +644,12 @@
   FillClientEdgeRects(x, y, w, height, true, toolbar_color, canvas);
 
   // For popup windows, draw location bar sides.
+  SkColor location_bar_border_color =
+      browser_view()->toolbar()->location_bar()->GetOpaqueBorderColor(
+          incognito);
   if (!tabstrip_visible && IsToolbarVisible()) {
     FillClientEdgeRects(x, y, w, toolbar_bounds.height(), false,
-                        LocationBarView::GetOpaqueBorderColor(incognito),
-                        canvas);
+                        location_bar_border_color, canvas);
   }
 }
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 17dfec3..a37de8a5 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/translate/chrome_translate_client.h"
 #include "chrome/browser/translate/translate_service.h"
 #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h"
@@ -102,13 +103,6 @@
 using content::WebContents;
 using views::View;
 
-namespace {
-
-// The border color, drawn on top of the toolbar.
-const SkColor kBorderColor = SkColorSetA(SK_ColorBLACK, 0x4D);
-
-}  // namespace
-
 
 // LocationBarView -----------------------------------------------------------
 
@@ -159,13 +153,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // LocationBarView, public:
 
-// static
-SkColor LocationBarView::GetOpaqueBorderColor(bool incognito) {
-  return color_utils::GetResultingPaintColor(
-      kBorderColor, ThemeProperties::GetDefaultColor(
-                        ThemeProperties::COLOR_TOOLBAR, incognito));
-}
-
 void LocationBarView::Init() {
   // We need to be in a Widget, otherwise GetNativeTheme() may change and we're
   // not prepared for that.
@@ -304,6 +291,12 @@
   return gfx::kPlaceholderColor;
 }
 
+SkColor LocationBarView::GetOpaqueBorderColor(bool incognito) {
+  return color_utils::GetResultingPaintColor(
+      GetBorderColor(), ThemeProperties::GetDefaultColor(
+                            ThemeProperties::COLOR_TOOLBAR, incognito));
+}
+
 SkColor LocationBarView::GetSecureTextColor(
     security_state::SecurityLevel security_level) const {
   if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT) {
@@ -614,7 +607,7 @@
     // This border color will be blended on top of the toolbar (which may use an
     // image in the case of themes).
     set_background(
-        new BackgroundWith1PxBorder(GetColor(BACKGROUND), kBorderColor));
+        new BackgroundWith1PxBorder(GetColor(BACKGROUND), GetBorderColor()));
   }
   SchedulePaint();
 }
@@ -669,6 +662,11 @@
                          : 0;
 }
 
+SkColor LocationBarView::GetBorderColor() {
+  return GetThemeProvider()->GetColor(
+      ThemeProperties::COLOR_LOCATION_BAR_BORDER);
+}
+
 int LocationBarView::GetHorizontalEdgeThickness() const {
   return is_popup_mode_
              ? 0
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index b8aae51..54f184de 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -126,10 +126,6 @@
 
   ~LocationBarView() override;
 
-  // Returns the location bar border color blended with the toolbar color.
-  // It's guaranteed to be opaque.
-  static SkColor GetOpaqueBorderColor(bool incognito);
-
   // Initializes the LocationBarView.
   void Init();
 
@@ -141,6 +137,10 @@
   // system theme.
   SkColor GetColor(ColorKind kind) const;
 
+  // Returns the location bar border color blended with the toolbar color.
+  // It's guaranteed to be opaque.
+  SkColor GetOpaqueBorderColor(bool incognito);
+
   // Returns the color to be used for security text in the context of
   // |security_level|.
   SkColor GetSecureTextColor(
@@ -255,6 +255,9 @@
   // |view| should add to the trailing width after the omnibox.
   int IncrementalMinimumWidth(views::View* view) const;
 
+  // The border color, drawn on top of the toolbar.
+  SkColor GetBorderColor();
+
   // Returns the thickness of any visible edge, in pixels.
   int GetHorizontalEdgeThickness() const;
   int GetVerticalEdgeThickness() const;
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.cc b/chrome/browser/ui/views/passwords/credentials_item_view.cc
index e6cf904..29fadaf 100644
--- a/chrome/browser/ui/views/passwords/credentials_item_view.cc
+++ b/chrome/browser/ui/views/passwords/credentials_item_view.cc
@@ -59,6 +59,14 @@
   ImageView::OnPaint(canvas);
 }
 
+// An ImageView that consumes the mouse events.
+class InfoImageView : public views::ImageView {
+ public:
+  // View:
+  bool OnMousePressed(const ui::MouseEvent& event) override { return true; }
+  bool OnMouseDragged(const ui::MouseEvent& event) override { return true; }
+};
+
 }  // namespace
 
 CredentialsItemView::CredentialsItemView(
@@ -110,7 +118,7 @@
   }
 
   if (form_->is_public_suffix_match) {
-    info_icon_ = new views::ImageView;
+    info_icon_ = new InfoImageView;
     info_icon_->SetImage(gfx::CreateVectorIcon(gfx::VectorIconId::INFO_OUTLINE,
                                                kInfoIconSize,
                                                gfx::kChromeIconGrey));
diff --git a/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc b/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
index 83ab217c..03741eb 100644
--- a/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
+++ b/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
@@ -8,18 +8,57 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/table_model.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/controls/table/table_view.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/layout_constants.h"
 #include "ui/views/window/dialog_client_view.h"
+#include "url/gurl.h"
 
 namespace {
 
 int kDialogWidth = 500;
 int kDialogHeight = 400;
 
-}  // namespace
+}
+
+// Supplies data to the table view.
+class TargetPickerTableModel : public ui::TableModel {
+ public:
+  explicit TargetPickerTableModel(
+      const std::vector<std::pair<base::string16, GURL>>* targets);
+
+ private:
+  // ui::TableModel overrides:
+  int RowCount() override;
+  base::string16 GetText(int row, int column_id) override;
+  void SetObserver(ui::TableModelObserver* observer) override;
+
+  // Owned by WebShareTargetPickerView.
+  const std::vector<std::pair<base::string16, GURL>>* targets_;
+
+  DISALLOW_COPY_AND_ASSIGN(TargetPickerTableModel);
+};
+
+TargetPickerTableModel::TargetPickerTableModel(
+    const std::vector<std::pair<base::string16, GURL>>* targets)
+    : targets_(targets) {}
+
+int TargetPickerTableModel::RowCount() {
+  return targets_->size();
+}
+
+base::string16 TargetPickerTableModel::GetText(int row, int /*column_id*/) {
+  // Show "title (origin)", to disambiguate titles that are the same, and as a
+  // security measure.
+  return (*targets_)[row].first +
+         base::UTF8ToUTF16(" (" + (*targets_)[row].second.GetOrigin().spec() +
+                           ")");
+}
+
+void TargetPickerTableModel::SetObserver(ui::TableModelObserver* observer) {}
 
 namespace chrome {
 
@@ -37,7 +76,9 @@
 WebShareTargetPickerView::WebShareTargetPickerView(
     const std::vector<std::pair<base::string16, GURL>>& targets,
     const base::Callback<void(base::Optional<std::string>)>& close_callback)
-    : targets_(targets), close_callback_(close_callback) {
+    : targets_(targets),
+      table_model_(base::MakeUnique<TargetPickerTableModel>(&targets_)),
+      close_callback_(close_callback) {
   views::BoxLayout* layout = new views::BoxLayout(
       views::BoxLayout::kVertical, views::kPanelHorizMargin,
       views::kPanelVertMargin, views::kRelatedControlVerticalSpacing);
@@ -48,9 +89,10 @@
   AddChildView(overview_label);
 
   std::vector<ui::TableColumn> table_columns{ui::TableColumn()};
-  table_ = new views::TableView(this, table_columns, views::TEXT_ONLY, true);
+  table_ = new views::TableView(table_model_.get(), table_columns,
+                                views::TEXT_ONLY, true);
   // Select the first row.
-  if (RowCount() > 0)
+  if (targets_.size() > 0)
     table_->Select(0);
 
   table_->set_observer(this);
@@ -63,7 +105,12 @@
   layout->SetFlexForView(table_parent, 1);
 }
 
-WebShareTargetPickerView::~WebShareTargetPickerView() {}
+WebShareTargetPickerView::~WebShareTargetPickerView() {
+  // Clear the pointer from |table_| which currently points at |table_model_|.
+  // Otherwise, |table_model_| will be deleted before |table_|, and |table_|'s
+  // destructor will try to call a method on the model.
+  table_->SetModel(nullptr);
+}
 
 gfx::Size WebShareTargetPickerView::GetPreferredSize() const {
   return gfx::Size(kDialogWidth, kDialogHeight);
@@ -117,17 +164,3 @@
 void WebShareTargetPickerView::OnDoubleClick() {
   GetDialogClientView()->AcceptWindow();
 }
-
-int WebShareTargetPickerView::RowCount() {
-  return targets_.size();
-}
-
-base::string16 WebShareTargetPickerView::GetText(int row, int /*column_id*/) {
-  // Show "title (origin)", to disambiguate titles that are the same, and as a
-  // security measure.
-  return targets_[row].first +
-         base::UTF8ToUTF16(" (" + targets_[row].second.GetOrigin().spec() +
-                           ")");
-}
-
-void WebShareTargetPickerView::SetObserver(ui::TableModelObserver* observer) {}
diff --git a/chrome/browser/ui/views/webshare/webshare_target_picker_view.h b/chrome/browser/ui/views/webshare/webshare_target_picker_view.h
index b3898a7..18464cf3 100644
--- a/chrome/browser/ui/views/webshare/webshare_target_picker_view.h
+++ b/chrome/browser/ui/views/webshare/webshare_target_picker_view.h
@@ -11,13 +11,20 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/browser_dialogs.h"
-#include "ui/base/models/table_model.h"
 #include "ui/base/ui_base_types.h"
-#include "ui/views/controls/table/table_view.h"
 #include "ui/views/controls/table/table_view_observer.h"
 #include "ui/views/window/dialog_delegate.h"
 
 class GURL;
+class TargetPickerTableModel;
+
+namespace views {
+class TableView;
+}
+
+namespace {
+class WebShareTargetPickerViewTest;
+}
 
 // Dialog that presents the user with a list of share target apps. Allows the
 // user to pick one target to be opened and have data passed to it.
@@ -26,8 +33,7 @@
 // in-development feature (Web Share) behind a runtime flag. It should not be
 // used by any released code until going through UI review.
 class WebShareTargetPickerView : public views::DialogDelegateView,
-                                 public views::TableViewObserver,
-                                 public ui::TableModel {
+                                 public views::TableViewObserver {
  public:
   // |targets| is a list of app title and manifest URL pairs that will be shown
   // in a list. If the user picks a target, this calls |callback| with the
@@ -56,15 +62,14 @@
   void OnSelectionChanged() override;
   void OnDoubleClick() override;
 
-  // ui::TableModel overrides:
-  int RowCount() override;
-  base::string16 GetText(int row, int column_id) override;
-  void SetObserver(ui::TableModelObserver* observer) override;
-
  private:
-  views::TableView* table_;
+  // For access to |table_|.
+  friend class WebShareTargetPickerViewTest;
+
+  views::TableView* table_ = nullptr;
 
   const std::vector<std::pair<base::string16, GURL>> targets_;
+  std::unique_ptr<TargetPickerTableModel> table_model_;
 
   base::Callback<void(base::Optional<std::string>)> close_callback_;
 
diff --git a/chrome/browser/ui/views/webshare/webshare_target_picker_view_unittest.cc b/chrome/browser/ui/views/webshare/webshare_target_picker_view_unittest.cc
new file mode 100644
index 0000000..a8d04789
--- /dev/null
+++ b/chrome/browser/ui/views/webshare/webshare_target_picker_view_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/webshare/webshare_target_picker_view.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/chrome_constrained_window_views_client.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "components/constrained_window/constrained_window_views.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/table/table_view.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/window/dialog_client_view.h"
+#include "ui/views/window/dialog_delegate.h"
+#include "url/gurl.h"
+
+namespace {
+
+class WebShareTargetPickerViewTest : public views::ViewsTestBase {
+ public:
+  WebShareTargetPickerViewTest() {}
+
+  void SetUp() override {
+    ViewsTestBase::SetUp();
+
+    SetConstrainedWindowViewsClient(CreateChromeConstrainedWindowViewsClient());
+
+    // Create the parent widget.
+    views::Widget::InitParams params =
+        CreateParams(views::Widget::InitParams::TYPE_WINDOW);
+    params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+
+    parent_widget_.reset(new views::Widget());
+    parent_widget_->Init(params);
+    parent_widget_->Show();
+  }
+
+  void TearDown() override {
+    if (view_)
+      view_->GetWidget()->CloseNow();
+    parent_widget_->CloseNow();
+    quit_closure_ = base::Closure();
+    constrained_window::SetConstrainedWindowViewsClient(nullptr);
+
+    ViewsTestBase::TearDown();
+  }
+
+ protected:
+  // Creates the WebShareTargetPickerView (available as view()).
+  void CreateView(const std::vector<std::pair<base::string16, GURL>>& targets) {
+    view_ = new WebShareTargetPickerView(
+        targets, base::Bind(&WebShareTargetPickerViewTest::OnCallback,
+                            base::Unretained(this)));
+    constrained_window::CreateBrowserModalDialogViews(
+        view_, parent_widget_->GetNativeWindow())
+        ->Show();
+  }
+
+  // Sets the closure that will be called when the dialog is closed. This is
+  // used in tests to quit the RunLoop.
+  void SetQuitClosure(base::Closure&& quit_closure) {
+    quit_closure_ = std::move(quit_closure);
+  }
+
+  // The view under test.
+  WebShareTargetPickerView* view() { return view_; }
+  // The table inside the view (for inspection).
+  views::TableView* table() { return view_->table_; }
+
+  // The result that was returned to the dialog's callback.
+  const base::Optional<std::string>& result() { return result_; }
+
+ private:
+  void OnCallback(base::Optional<std::string> result) {
+    result_ = result;
+    if (quit_closure_)
+      quit_closure_.Run();
+  }
+
+  std::unique_ptr<views::Widget> parent_widget_;
+  WebShareTargetPickerView* view_ = nullptr;
+
+  base::Optional<std::string> result_;
+
+  base::Closure quit_closure_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebShareTargetPickerViewTest);
+};
+
+// Table with 0 targets. Choose to cancel.
+TEST_F(WebShareTargetPickerViewTest, EmptyListCancel) {
+  CreateView(std::vector<std::pair<base::string16, GURL>>());
+  EXPECT_EQ(0, table()->RowCount());
+  EXPECT_EQ(-1, table()->FirstSelectedRow());  // Nothing selected.
+  EXPECT_FALSE(view()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
+
+  base::RunLoop run_loop;
+  SetQuitClosure(run_loop.QuitClosure());
+
+  view()->Cancel();
+
+  run_loop.Run();
+
+  EXPECT_EQ(base::nullopt, result());
+}
+
+// Table with 2 targets. Choose second target and share.
+TEST_F(WebShareTargetPickerViewTest, ChooseItem) {
+  std::vector<std::pair<base::string16, GURL>> targets{
+      std::make_pair(base::ASCIIToUTF16("App One"),
+                     GURL("https://appone.com/path/bits")),
+      std::make_pair(base::ASCIIToUTF16("App Two"),
+                     GURL("https://apptwo.xyz"))};
+  CreateView(targets);
+  EXPECT_EQ(2, table()->RowCount());
+  EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
+            table()->model()->GetText(0, 0));
+  EXPECT_EQ(base::ASCIIToUTF16("App Two (https://apptwo.xyz/)"),
+            table()->model()->GetText(1, 0));
+  EXPECT_EQ(0, table()->FirstSelectedRow());
+  EXPECT_TRUE(view()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
+
+  // Deselect and ensure OK button is disabled.
+  table()->Select(-1);
+  EXPECT_FALSE(view()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
+
+  // Select the second app and ensure the OK button is enabled.
+  table()->Select(1);
+  EXPECT_TRUE(view()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
+
+  base::RunLoop run_loop;
+  SetQuitClosure(run_loop.QuitClosure());
+
+  view()->Accept();
+
+  run_loop.Run();
+
+  EXPECT_EQ(base::Optional<std::string>("https://apptwo.xyz/"), result());
+}
+
+// Table with 1 target. Select using double-click.
+TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) {
+  std::vector<std::pair<base::string16, GURL>> targets{std::make_pair(
+      base::ASCIIToUTF16("App One"), GURL("https://appone.com/path/bits"))};
+  CreateView(targets);
+  EXPECT_EQ(1, table()->RowCount());
+  EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
+            table()->model()->GetText(0, 0));
+  EXPECT_EQ(0, table()->FirstSelectedRow());
+  EXPECT_TRUE(view()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
+
+  base::RunLoop run_loop;
+  SetQuitClosure(run_loop.QuitClosure());
+
+  view()->OnDoubleClick();
+
+  run_loop.Run();
+
+  EXPECT_EQ(base::Optional<std::string>("https://appone.com/path/bits"),
+            result());
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
index 2409e16..acc63920 100644
--- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
+++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
@@ -109,6 +109,16 @@
 // bubble (e.g. +3). Use +1 to obtain a smaller font.
 constexpr int kSummaryFontSizeDelta = 1;
 
+// Adds a ColumnSet on |layout| with a single View column and padding columns
+// on either side of it with |margin| width.
+void AddColumnWithSideMargin(views::GridLayout* layout, int margin, int id) {
+  views::ColumnSet* column_set = layout->AddColumnSet(id);
+  column_set->AddPaddingColumn(0, margin);
+  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+                        views::GridLayout::USE_PREF, 0, 0);
+  column_set->AddPaddingColumn(0, margin);
+}
+
 }  // namespace
 
 // |PopupHeaderView| is the UI element (view) that represents the header of the
@@ -116,8 +126,9 @@
 // identity check and the name of the site's identity.
 class PopupHeaderView : public views::View {
  public:
-  explicit PopupHeaderView(views::ButtonListener* button_listener,
-                           views::StyledLabelListener* styled_label_listener);
+  PopupHeaderView(views::ButtonListener* button_listener,
+                  views::StyledLabelListener* styled_label_listener,
+                  int side_margin);
   ~PopupHeaderView() override;
 
   // Sets the security summary for the current page.
@@ -179,7 +190,8 @@
 
 PopupHeaderView::PopupHeaderView(
     views::ButtonListener* button_listener,
-    views::StyledLabelListener* styled_label_listener)
+    views::StyledLabelListener* styled_label_listener,
+    int side_margin)
     : styled_label_listener_(styled_label_listener),
       details_label_(nullptr),
       reset_decisions_label_container_(nullptr),
@@ -188,11 +200,7 @@
   SetLayoutManager(layout);
 
   const int label_column_status = 1;
-  views::ColumnSet* column_set_status =
-      layout->AddColumnSet(label_column_status);
-  column_set_status->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
-                               1, views::GridLayout::USE_PREF, 0, 0);
-
+  AddColumnWithSideMargin(layout, side_margin, label_column_status);
   layout->AddPaddingRow(0, kHeaderLabelSpacing);
 
   layout->StartRow(0, label_column_status);
@@ -402,8 +410,21 @@
   set_anchor_view_insets(gfx::Insets(
       GetLayoutConstant(LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET), 0));
 
+  // Capture the default bubble margin, and move it to the Layout classes. This
+  // is necessary so that the views::Separator can extend the full width of the
+  // bubble.
+  const int side_margin = margins().left();
+  DCHECK_EQ(margins().left(), margins().right());
+
+  // Also remove the top margin from the client area so there is less space
+  // below the dialog title.
+  set_margins(gfx::Insets(0, 0, margins().bottom(), 0));
+
   views::GridLayout* layout = new views::GridLayout(this);
   SetLayoutManager(layout);
+
+  // Use a single ColumnSet here. Otherwise the preferred width doesn't properly
+  // propagate up to the dialog width.
   const int content_column = 0;
   views::ColumnSet* column_set = layout->AddColumnSet(content_column);
   column_set->AddColumn(views::GridLayout::FILL,
@@ -413,7 +434,7 @@
                         0,
                         0);
 
-  header_ = new PopupHeaderView(this, this);
+  header_ = new PopupHeaderView(this, this, side_margin);
   layout->StartRow(1, content_column);
   layout->AddView(header_);
 
@@ -424,18 +445,14 @@
   layout->AddPaddingRow(1, kHeaderMarginBottom);
   layout->StartRow(1, content_column);
 
-  site_settings_view_ = CreateSiteSettingsView();
+  site_settings_view_ = CreateSiteSettingsView(side_margin);
   layout->AddView(site_settings_view_);
 
-  // Remove the top margin from the client area so there is less space below the
-  // dialog title.
-  set_margins(
-      gfx::Insets(0, margins().left(), margins().bottom(), margins().right()));
   if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) {
     // In non-material, titles are inset from the dialog margin. Ensure the
     // horizontal insets match.
-    set_title_margins(gfx::Insets(views::kPanelVertMargin, margins().left(), 0,
-                                  margins().right()));
+    set_title_margins(
+        gfx::Insets(views::kPanelVertMargin, side_margin, 0, side_margin));
   }
   views::BubbleDialogDelegateView::CreateBubble(this);
 
@@ -681,10 +698,10 @@
   SizeToContents();
 }
 
-views::View* WebsiteSettingsPopupView::CreateSiteSettingsView() {
+views::View* WebsiteSettingsPopupView::CreateSiteSettingsView(int side_margin) {
   views::View* site_settings_view = new views::View();
   views::BoxLayout* box_layout =
-      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
+      new views::BoxLayout(views::BoxLayout::kVertical, side_margin, 0, 0);
   site_settings_view->SetLayoutManager(box_layout);
   box_layout->set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.h b/chrome/browser/ui/views/website_settings/website_settings_popup_view.h
index 78f4c76..0a5e461 100644
--- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.h
+++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.h
@@ -135,7 +135,7 @@
 
   // Creates the contents of the |site_settings_view_|. The ownership of the
   // returned view is transferred to the caller.
-  views::View* CreateSiteSettingsView() WARN_UNUSED_RESULT;
+  views::View* CreateSiteSettingsView(int side_margin) WARN_UNUSED_RESULT;
 
   // Used to asynchronously handle clicks since these calls may cause the
   // destruction of the settings view and the base class window still needs to
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
index 7ddf1fd7..5d6e079 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -160,6 +160,7 @@
   // MD-OOBE
   builder->Add("oobeOKButtonText", IDS_OOBE_OK_BUTTON_TEXT);
   builder->Add("welcomeNextButtonText", IDS_OOBE_WELCOME_NEXT_BUTTON_TEXT);
+  builder->Add("languageButtonLabel", IDS_LANGUAGE_BUTTON_LABEL);
   builder->Add("languageSectionTitle", IDS_LANGUAGE_SECTION_TITLE);
   builder->Add("accessibilitySectionTitle", IDS_ACCESSIBILITY_SECTION_TITLE);
   builder->Add("accessibilitySectionHint", IDS_ACCESSIBILITY_SECTION_HINT);
@@ -168,7 +169,9 @@
   builder->Add("networkSectionHint", IDS_NETWORK_SECTION_HINT);
 
   builder->Add("languageDropdownTitle", IDS_LANGUAGE_DROPDOWN_TITLE);
+  builder->Add("languageDropdownLabel", IDS_LANGUAGE_DROPDOWN_LABEL);
   builder->Add("keyboardDropdownTitle", IDS_KEYBOARD_DROPDOWN_TITLE);
+  builder->Add("keyboardDropdownLabel", IDS_KEYBOARD_DROPDOWN_LABEL);
   builder->Add("proxySettingsMenuName", IDS_PROXY_SETTINGS_MENU_NAME);
   builder->Add("addWiFiNetworkMenuName", IDS_ADD_WI_FI_NETWORK_MENU_NAME);
   builder->Add("addMobileNetworkMenuName", IDS_ADD_MOBILE_NETWORK_MENU_NAME);
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
index c62cad7..4a0e5c2 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
@@ -56,13 +56,6 @@
   content::PresentationError expected_error_;
 };
 
-class MockRoutesUpdatedCallback {
- public:
-  MOCK_METHOD2(OnRoutesUpdated,
-               void(const std::vector<MediaRoute>& routes,
-                    const std::vector<MediaRoute::Id>& joinable_route_ids));
-};
-
 class MediaRouterUITest : public ChromeRenderViewHostTestHarness {
  public:
   MediaRouterUITest() {
@@ -341,7 +334,6 @@
   MediaSource media_source_1(MediaSourceForTab(tab_id));
   MediaSource media_source_2("mediaSource");
   MediaSource media_source_3(MediaSourceForDesktop());
-  MockRoutesUpdatedCallback mock_callback;
   std::unique_ptr<MediaRouterUI::UIMediaRoutesObserver> observer(
       new MediaRouterUI::UIMediaRoutesObserver(
           &mock_router_, MediaSource::Id(),
@@ -390,7 +382,6 @@
   MediaSource media_source_1("mediaSource1");
   MediaSource media_source_2("mediaSource2");
   MediaSource media_source_3(MediaSourceForDesktop());
-  MockRoutesUpdatedCallback mock_callback;
   std::unique_ptr<MediaRouterUI::UIMediaRoutesObserver> observer(
       new MediaRouterUI::UIMediaRoutesObserver(
           &mock_router_, MediaSource::Id(),
diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc
index e98857f9..5d59f51 100644
--- a/chrome/browser/ui/webui/options/content_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/content_settings_handler.cc
@@ -419,11 +419,13 @@
     {"notificationsAllow", IDS_NOTIFICATIONS_ALLOW_RADIO},
     {"notificationsAsk", IDS_NOTIFICATIONS_ASK_RADIO},
     {"notificationsBlock", IDS_NOTIFICATIONS_BLOCK_RADIO},
-#if defined(OS_CHROMEOS) || defined(OS_WIN)
     // Protected Content filter
     {"protectedContentTabLabel", IDS_PROTECTED_CONTENT_TAB_LABEL},
+    {"protectedContentEnableCheckbox", IDS_PROTECTED_CONTENT_ENABLE_CHECKBOX},
+#if defined(OS_CHROMEOS) || defined(OS_WIN)
     {"protectedContentInfo", IDS_PROTECTED_CONTENT_INFO},
-    {"protectedContentEnable", IDS_PROTECTED_CONTENT_ENABLE},
+    {"protectedContentEnableIdentifiersCheckbox",
+     IDS_PROTECTED_CONTENT_ENABLE_IDENTIFIERS_CHECKBOX},
     {"protectedContentHeader", IDS_PROTECTED_CONTENT_HEADER},
 #endif  // defined(OS_CHROMEOS) || defined(OS_WIN)
     // Microphone filter.
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 7ed472c6..5bae09d 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -27,7 +27,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -319,7 +319,6 @@
 void PrintToPdfCallback(const scoped_refptr<base::RefCountedBytes>& data,
                         const base::FilePath& path,
                         const base::Closure& pdf_file_saved_closure) {
-  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
   base::File file(path,
                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
   file.WriteAtCurrentPos(reinterpret_cast<const char*>(data->front()),
@@ -1405,9 +1404,9 @@
   // Handle the no prompting case. Like the dialog prompt, this function
   // returns and eventually FileSelected() gets called.
   if (!prompt_user) {
-    base::PostTaskAndReplyWithResult(
-        BrowserThread::GetBlockingPool(),
-        FROM_HERE,
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                       base::TaskPriority::BACKGROUND),
         base::Bind(&GetUniquePath,
                    download_prefs->SaveFilePath().Append(default_filename)),
         base::Bind(&PrintPreviewHandler::OnGotUniqueFileName,
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 80d456b..d429ad0 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -323,6 +323,9 @@
       {"bluetoothAccept", IDS_OPTIONS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY},
       {"bluetoothConnected", IDS_SETTINGS_BLUETOOTH_CONNECTED},
       {"bluetoothConnecting", IDS_SETTINGS_BLUETOOTH_CONNECTING},
+      {"bluetoothDeviceListPaired", IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_PAIRED},
+      {"bluetoothDeviceListUnpaired",
+       IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_UNPAIRED},
       {"bluetoothDisabled", IDS_SETTINGS_BLUETOOTH_DISABLED},
       {"bluetoothDisconnect", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT},
       {"bluetoothDismiss", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISMISS_ERROR},
@@ -330,17 +333,16 @@
       {"bluetoothExpandA11yLabel",
        IDS_SETTINGS_BLUETOOTH_EXPAND_ACCESSIBILITY_LABEL},
       {"bluetoothNoDevices", IDS_SETTINGS_BLUETOOTH_NO_DEVICES},
+      {"bluetoothNoDevicesFound", IDS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND},
       {"bluetoothNotConnected", IDS_SETTINGS_BLUETOOTH_NOT_CONNECTED},
       {"bluetoothOff", IDS_SETTINGS_BLUETOOTH_OFF},
       {"bluetoothOn", IDS_SETTINGS_BLUETOOTH_ON},
       {"bluetoothPageTitle", IDS_SETTINGS_BLUETOOTH},
       {"bluetoothPair", IDS_SETTINGS_BLUETOOTH_PAIR},
-      {"bluetoothPairDevice", IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE},
       {"bluetoothPairDevicePageTitle",
        IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE},
       {"bluetoothReject", IDS_OPTIONS_SETTINGS_BLUETOOTH_REJECT_PASSKEY},
       {"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE},
-      {"bluetoothScanning", IDS_SETTINGS_BLUETOOTH_SCANNING},
       // Device connecting and pairing.
       {"bluetoothStartConnecting", IDS_SETTINGS_BLUETOOTH_START_CONNECTING},
       {"bluetoothEnterKey", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_KEY},
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc
index 3a0954a..9c17f2e 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -37,6 +37,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/text/bytes_formatting.h"
 
+#if defined(OS_CHROMEOS)
+#include "components/user_manager/user_manager.h"
+#endif
+
 namespace settings {
 
 namespace {
@@ -374,8 +378,15 @@
   ContentSetting default_setting;
   CHECK(content_settings::ContentSettingFromString(setting, &default_setting));
 
+  Profile* profile = profile_;
+#if defined(OS_CHROMEOS)
+  // ChromeOS special case: in Guest mode, settings are opened in Incognito
+  // mode so we need the original profile to actually modify settings.
+  if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
+    profile = profile->GetOriginalProfile();
+#endif
   HostContentSettingsMap* map =
-      HostContentSettingsMapFactory::GetForProfile(profile_);
+      HostContentSettingsMapFactory::GetForProfile(profile);
   map->SetDefaultContentSetting(
       static_cast<ContentSettingsType>(static_cast<int>(
           site_settings::ContentSettingsTypeFromGroupName(content_type))),
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
index f03fa02c..070d4ca 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -18,6 +18,11 @@
 #include "extensions/common/extension_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/users/mock_user_manager.h"
+#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
+#endif
+
 namespace {
 
 const char kCallbackId[] = "test-callback-id";
@@ -30,7 +35,13 @@
 
 class SiteSettingsHandlerTest : public testing::Test {
  public:
-  SiteSettingsHandlerTest() : handler_(&profile_) {}
+  SiteSettingsHandlerTest() : handler_(&profile_) {
+#if defined(OS_CHROMEOS)
+    mock_user_manager_ = new chromeos::MockUserManager;
+    user_manager_enabler_.reset(
+        new chromeos::ScopedUserManagerEnabler(mock_user_manager_));
+#endif
+  }
 
   void SetUp() override {
     handler()->set_web_ui(web_ui());
@@ -212,6 +223,10 @@
   TestingProfile* incognito_profile_;
   content::TestWebUI web_ui_;
   SiteSettingsHandler handler_;
+#if defined(OS_CHROMEOS)
+  chromeos::MockUserManager* mock_user_manager_;  // Not owned.
+  std::unique_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
+#endif
 };
 
 TEST_F(SiteSettingsHandlerTest, GetAndSetDefault) {
diff --git a/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc b/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
index 62074313..57dc189 100644
--- a/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
+++ b/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
@@ -140,8 +140,13 @@
     std::vector<content::WebUIMessageHandler*>* handlers) const {}
 
 void SigninEmailConfirmationDialog::GetDialogSize(gfx::Size* size) const {
-  // Avoid setting a dialog size in here as this dialog auto-resizes (see
-  // method |SigninEmailConfirmationDialog::Show|.
+  DCHECK(size);
+
+  // Set the dialog width if it's not set, so that the dialog is center-aligned
+  // horizontally when it appears. Avoid setting a dialog height in here as
+  // this dialog auto-resizes.
+  if (size->IsEmpty())
+    size->set_width(kDialogWidth);
 }
 
 std::string SigninEmailConfirmationDialog::GetDialogArgs() const {
diff --git a/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc b/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc
index 127bb61..bbf4deee 100644
--- a/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/signin_email_confirmation_ui.cc
@@ -33,9 +33,15 @@
       "signinEmailConfirmationCreateProfileButtonTitle",
       IDS_SIGNIN_EMAIL_CONFIRMATION_CREATE_PROFILE_RADIO_BUTTON_TITLE);
   source->AddLocalizedString(
+      "signinEmailConfirmationCreateProfileButtonSubtitle",
+      IDS_SIGNIN_EMAIL_CONFIRMATION_CREATE_PROFILE_RADIO_BUTTON_SUBTITLE);
+  source->AddLocalizedString(
       "signinEmailConfirmationStartSyncButtonTitle",
       IDS_SIGNIN_EMAIL_CONFIRMATION_START_SYNC_RADIO_BUTTON_TITLE);
   source->AddLocalizedString(
+      "signinEmailConfirmationStartSyncButtonSubtitle",
+      IDS_SIGNIN_EMAIL_CONFIRMATION_START_SYNC_RADIO_BUTTON_SUBTITLE);
+  source->AddLocalizedString(
       "signinEmailConfirmationConfirmLabel",
       IDS_SIGNIN_EMAIL_CONFIRMATION_CONFIRM_BUTTON_LABEL);
   source->AddLocalizedString("signinEmailConfirmationCloseLabel",
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc
index 508093d..14b6f87 100644
--- a/chrome/browser/win/jumplist.cc
+++ b/chrome/browser/win/jumplist.cc
@@ -44,7 +44,10 @@
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/icon_util.h"
+#include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_family.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "url/gurl.h"
 
 using content::BrowserThread;
@@ -73,7 +76,7 @@
 }
 
 // Creates a temporary icon file to be shown in JumpList.
-bool CreateIconFile(const SkBitmap& bitmap,
+bool CreateIconFile(const gfx::ImageSkia& image_skia,
                     const base::FilePath& icon_dir,
                     base::FilePath* icon_path) {
   // Retrieve the path to a temporary file.
@@ -86,7 +89,16 @@
   // Create an icon file from the favicon attached to the given |page|, and
   // save it as the temporary file.
   gfx::ImageFamily image_family;
-  image_family.Add(gfx::Image::CreateFrom1xBitmap(bitmap));
+  if (!image_skia.isNull()) {
+    std::vector<float> supported_scales = image_skia.GetSupportedScales();
+    for (auto& scale : supported_scales) {
+      gfx::ImageSkiaRep image_skia_rep = image_skia.GetRepresentation(scale);
+      if (!image_skia_rep.is_null())
+        image_family.Add(
+            gfx::Image::CreateFrom1xBitmap(image_skia_rep.sk_bitmap()));
+    }
+  }
+
   if (!IconUtil::CreateIconFileFromImageFamily(image_family, path,
                                                IconUtil::NORMAL_WRITE))
     return false;
@@ -104,7 +116,7 @@
   for (ShellLinkItemList::const_iterator item = item_list.begin();
       item != item_list.end(); ++item) {
     base::FilePath icon_path;
-    if (CreateIconFile((*item)->icon_data(), icon_dir, &icon_path))
+    if (CreateIconFile((*item)->icon_image(), icon_dir, &icon_path))
       (*item)->set_icon(icon_path.value(), 0);
   }
 }
@@ -541,10 +553,12 @@
     base::AutoLock auto_lock(data->list_lock_);
     // Attach the received data to the ShellLinkItem object.
     // This data will be decoded by the RunUpdateOnFileThread method.
-    if (!image_result.image.IsEmpty()) {
-      if (!data->icon_urls_.empty() && data->icon_urls_.front().second.get())
-        data->icon_urls_.front().second->set_icon_data(
-            image_result.image.AsBitmap());
+    if (!image_result.image.IsEmpty() && !data->icon_urls_.empty() &&
+        data->icon_urls_.front().second.get()) {
+      gfx::ImageSkia image_skia = image_result.image.AsImageSkia();
+      image_skia.EnsureRepsForSupportedScales();
+      std::unique_ptr<gfx::ImageSkia> deep_copy(image_skia.DeepCopy());
+      data->icon_urls_.front().second->set_icon_image(*deep_copy);
     }
 
     if (!data->icon_urls_.empty())
diff --git a/chrome/browser/win/jumplist_updater.h b/chrome/browser/win/jumplist_updater.h
index 6d49f15..dd4f4f5fc 100644
--- a/chrome/browser/win/jumplist_updater.h
+++ b/chrome/browser/win/jumplist_updater.h
@@ -16,7 +16,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/win/scoped_comptr.h"
-#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/image/image_skia.h"
 
 // Represents a class used for creating an IShellLink object.
 // Even though an IShellLink also needs the absolute path to an application to
@@ -29,7 +29,7 @@
   const std::wstring& title() const { return title_; }
   const std::wstring& icon_path() const { return icon_path_; }
   int icon_index() const { return icon_index_; }
-  const SkBitmap& icon_data() const { return icon_data_; }
+  const gfx::ImageSkia& icon_image() const { return icon_image_; }
 
   std::wstring GetArguments() const;
   base::CommandLine* GetCommandLine();
@@ -43,8 +43,8 @@
     icon_index_ = index;
   }
 
-  void set_icon_data(const SkBitmap& data) {
-    icon_data_ = data;
+  void set_icon_image(const gfx::ImageSkia& image) {
+    icon_image_ = image;
   }
 
  private:
@@ -65,10 +65,10 @@
   // one icon, this value is 0.
   int icon_index_;
 
-  // Icon bitmap. Used by the browser JumpList.
+  // Icon image. Used by the browser JumpList.
   // Note that an icon path must be supplied to IShellLink, so users of this
   // class must save icon data to disk.
-  SkBitmap icon_data_;
+  gfx::ImageSkia icon_image_;
 
   DISALLOW_COPY_AND_ASSIGN(ShellLinkItem);
 };
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 4f6c71aa..05b08cd 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -105,6 +105,12 @@
     "HappinessTrackingSystem", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
+// Controls whether the "improved recovery component" is used. The improved
+// recovery component is a redesigned Chrome component intended to restore
+// a broken Chrome updater in more scenarios than before.
+const base::Feature kImprovedRecoveryComponent{
+    "ImprovedRecoveryComponent", base::FEATURE_DISABLED_BY_DEFAULT};
+
 #if defined(GOOGLE_CHROME_BUILD) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
 // Enables showing the "This computer will no longer receive Google Chrome
 // updates" infobar instead of the "will soon stop receiving" infobar on
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 1ece66e2..a4904df 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -68,6 +68,8 @@
 extern const base::Feature kHappinessTrackingSystem;
 #endif
 
+extern const base::Feature kImprovedRecoveryComponent;
+
 #if defined(GOOGLE_CHROME_BUILD) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
 extern const base::Feature kLinuxObsoleteSystemIsEndOfTheLine;
 #endif
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc
index b1589f16..4ce7af6 100644
--- a/chrome/common/crash_keys.cc
+++ b/chrome/common/crash_keys.cc
@@ -111,7 +111,7 @@
     { kChannel, kSmallSize },
     { kActiveURL, kLargeSize },
     { kNumVariations, kSmallSize },
-    { kVariations, kLargeSize },
+    { kVariations, kHugeSize },
     { kNumExtensionsCount, kSmallSize },
     { kShutdownType, kSmallSize },
     { kBrowserUnpinTrace, kMediumSize },
diff --git a/chrome/common/extensions/PRESUBMIT.py b/chrome/common/extensions/PRESUBMIT.py
index bcfba68..1b0d113 100644
--- a/chrome/common/extensions/PRESUBMIT.py
+++ b/chrome/common/extensions/PRESUBMIT.py
@@ -162,7 +162,6 @@
 
 def CheckChangeOnUpload(input_api, output_api):
   results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   results += _CheckChange(input_api, output_api)
   return results
 
diff --git a/chrome/common/instant.mojom b/chrome/common/instant.mojom
index 3935339e..a9f0fdd 100644
--- a/chrome/common/instant.mojom
+++ b/chrome/common/instant.mojom
@@ -25,15 +25,14 @@
   // Tells InstantExtended to set the omnibox focus state.
   FocusOmnibox(int32 page_seq_no, OmniboxFocusState state);
 
-  // TODO(treib): Remove the SearchBox prefix from these three methods.
   // Tells InstantExtended to delete a most visited item.
-  SearchBoxDeleteMostVisitedItem(int32 page_seq_no, url.mojom.Url url);
+  DeleteMostVisitedItem(int32 page_seq_no, url.mojom.Url url);
 
   // Tells InstantExtended to undo all most visited item deletions.
-  SearchBoxUndoAllMostVisitedDeletions(int32 page_seq_no);
+  UndoAllMostVisitedDeletions(int32 page_seq_no);
 
   // Tells InstantExtended to undo one most visited item deletion.
-  SearchBoxUndoMostVisitedDeletion(int32 page_seq_no, url.mojom.Url url);
+  UndoMostVisitedDeletion(int32 page_seq_no, url.mojom.Url url);
 
   // Logs events from InstantExtended New Tab Pages.
   LogEvent(int32 page_seq_no,
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 6d0a7b30..6377621e 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -371,6 +371,8 @@
 const char kWebKitLoadsImagesAutomatically[] =
     "webkit.webprefs.loads_images_automatically";
 const char kWebKitPluginsEnabled[] = "webkit.webprefs.plugins_enabled";
+const char kWebKitEncryptedMediaEnabled[] =
+    "webkit.webprefs.encrypted_media_enabled";
 
 // Boolean that is true when Data Saver is enabled.
 // TODO(bengr): Migrate the preference string to "data_saver.enabled"
@@ -1282,9 +1284,6 @@
 const char kPushMessagingAppIdentifierMap[] =
     "gcm.push_messaging_application_id_map";
 
-// Maps from origin to background budget information.
-const char kBackgroundBudgetMap[] = "push_messaging.background_budget_map";
-
 // A string like "com.chrome.macosx" that should be used as the GCM category
 // when an app_id is sent as a subtype instead of as a category.
 const char kGCMProductCategoryForSubtypes[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 96517ce..a8cc94e 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -149,6 +149,7 @@
 extern const char kWebKitJavascriptCanOpenWindowsAutomatically[];
 extern const char kWebKitLoadsImagesAutomatically[];
 extern const char kWebKitPluginsEnabled[];
+extern const char kWebKitEncryptedMediaEnabled[];
 extern const char kWebKitDomPasteEnabled[];
 extern const char kWebKitTextAreasAreResizable[];
 extern const char kWebkitTabsToLinks[];
@@ -437,7 +438,6 @@
 #endif
 
 extern const char kPushMessagingAppIdentifierMap[];
-extern const char kBackgroundBudgetMap[];
 
 extern const char kGCMProductCategoryForSubtypes[];
 
diff --git a/chrome/renderer/extensions/PRESUBMIT.py b/chrome/renderer/extensions/PRESUBMIT.py
deleted file mode 100644
index 627f282..0000000
--- a/chrome/renderer/extensions/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2014 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.
-
-"""Presubmit script for extensions and apps.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index 41a44b6..2b898d8 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -286,7 +286,7 @@
 
 void SearchBox::DeleteMostVisitedItem(
     InstantRestrictedID most_visited_item_id) {
-  instant_service_->SearchBoxDeleteMostVisitedItem(
+  instant_service_->DeleteMostVisitedItem(
       page_seq_no_, GetURLForMostVisitedItem(most_visited_item_id));
 }
 
@@ -330,12 +330,12 @@
 }
 
 void SearchBox::UndoAllMostVisitedDeletions() {
-  instant_service_->SearchBoxUndoAllMostVisitedDeletions(page_seq_no_);
+  instant_service_->UndoAllMostVisitedDeletions(page_seq_no_);
 }
 
 void SearchBox::UndoMostVisitedDeletion(
     InstantRestrictedID most_visited_item_id) {
-  instant_service_->SearchBoxUndoMostVisitedDeletion(
+  instant_service_->UndoMostVisitedDeletion(
       page_seq_no_, GetURLForMostVisitedItem(most_visited_item_id));
 }
 
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index 5781157..9525e5b 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -67,7 +67,7 @@
   // Sends HistorySyncCheck to the browser.
   void CheckIsUserSyncingHistory();
 
-  // Sends SearchBoxDeleteMostVisitedItem to the browser.
+  // Sends DeleteMostVisitedItem to the browser.
   void DeleteMostVisitedItem(InstantRestrictedID most_visited_item_id);
 
   // Generates the image URL of |type| for the most visited item specified in
@@ -121,10 +121,10 @@
   // Sends ChromeViewHostMsg_StopCapturingKeyStrokes to the browser.
   void StopCapturingKeyStrokes();
 
-  // Sends SearchBoxUndoAllMostVisitedDeletions to the browser.
+  // Sends UndoAllMostVisitedDeletions to the browser.
   void UndoAllMostVisitedDeletions();
 
-  // Sends SearchBoxUndoMostVisitedDeletion to the browser.
+  // Sends UndoMostVisitedDeletion to the browser.
   void UndoMostVisitedDeletion(InstantRestrictedID most_visited_item_id);
 
   bool is_focused() const { return is_focused_; }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6dd43504..26ba839 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -849,6 +849,8 @@
       "../browser/sync/test/integration/passwords_helper.h",
       "../browser/sync/test/integration/preferences_helper.cc",
       "../browser/sync/test/integration/preferences_helper.h",
+      "../browser/sync/test/integration/printers_helper.cc",
+      "../browser/sync/test/integration/printers_helper.h",
       "../browser/sync/test/integration/profile_sync_service_harness.cc",
       "../browser/sync/test/integration/profile_sync_service_harness.h",
       "../browser/sync/test/integration/quiesce_status_change_checker.cc",
@@ -925,6 +927,8 @@
     }
     if (!is_chromeos) {
       sources -= [
+        "../browser/sync/test/integration/printers_helper.cc",
+        "../browser/sync/test/integration/printers_helper.h",
         "../browser/sync/test/integration/sync_arc_package_helper.cc",
         "../browser/sync/test/integration/sync_arc_package_helper.h",
         "../browser/sync/test/integration/wifi_credentials_helper.cc",
@@ -2719,6 +2723,7 @@
       "../browser/sync/test/integration/single_client_password_manager_setting_migrator_service_sync_test.cc",
       "../browser/sync/test/integration/single_client_passwords_sync_test.cc",
       "../browser/sync/test/integration/single_client_preferences_sync_test.cc",
+      "../browser/sync/test/integration/single_client_printers_sync_test.cc",
       "../browser/sync/test/integration/single_client_search_engines_sync_test.cc",
       "../browser/sync/test/integration/single_client_sessions_sync_test.cc",
       "../browser/sync/test/integration/single_client_supervised_user_settings_sync_test.cc",
@@ -2740,6 +2745,7 @@
       "../browser/sync/test/integration/two_client_password_manager_setting_migrator_service_sync_test.cc",
       "../browser/sync/test/integration/two_client_passwords_sync_test.cc",
       "../browser/sync/test/integration/two_client_preferences_sync_test.cc",
+      "../browser/sync/test/integration/two_client_printers_sync_test.cc",
       "../browser/sync/test/integration/two_client_search_engines_sync_test.cc",
       "../browser/sync/test/integration/two_client_sessions_sync_test.cc",
       "../browser/sync/test/integration/two_client_themes_sync_test.cc",
@@ -2824,8 +2830,10 @@
     if (!is_chromeos) {
       sources -= [
         "../browser/sync/test/integration/single_client_arc_package_sync_test.cc",
+        "../browser/sync/test/integration/single_client_printers_sync_test.cc",
         "../browser/sync/test/integration/single_client_wifi_credentials_sync_test.cc",
         "../browser/sync/test/integration/two_client_arc_package_sync_test.cc",
+        "../browser/sync/test/integration/two_client_printers_sync_test.cc",
         "../browser/sync/test/integration/two_client_wifi_credentials_sync_test.cc",
       ]
     }
@@ -4847,6 +4855,7 @@
         "../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/webshare/webshare_target_picker_view_unittest.cc",
       ]
     }
     if (use_aura) {
diff --git a/chrome/test/data/extensions/api_test/native_bindings/background.html b/chrome/test/data/extensions/api_test/native_bindings/extension/background.html
similarity index 100%
rename from chrome/test/data/extensions/api_test/native_bindings/background.html
rename to chrome/test/data/extensions/api_test/native_bindings/extension/background.html
diff --git a/chrome/test/data/extensions/api_test/native_bindings/background.js b/chrome/test/data/extensions/api_test/native_bindings/extension/background.js
similarity index 98%
rename from chrome/test/data/extensions/api_test/native_bindings/background.js
rename to chrome/test/data/extensions/api_test/native_bindings/extension/background.js
index 58b4edb2..7300d5c 100644
--- a/chrome/test/data/extensions/api_test/native_bindings/background.js
+++ b/chrome/test/data/extensions/api_test/native_bindings/extension/background.js
@@ -78,7 +78,7 @@
       sendResponse('started');
     });
     var url = 'http://localhost:' + portNumber +
-              '/native_bindings/messaging_test.html';
+              '/native_bindings/extension/messaging_test.html';
     chrome.tabs.create({url: url}, function(tab) {
       chrome.test.assertNoLastError();
       chrome.test.assertTrue(!!tab);
diff --git a/chrome/test/data/extensions/api_test/native_bindings/content_script.js b/chrome/test/data/extensions/api_test/native_bindings/extension/content_script.js
similarity index 100%
rename from chrome/test/data/extensions/api_test/native_bindings/content_script.js
rename to chrome/test/data/extensions/api_test/native_bindings/extension/content_script.js
diff --git a/chrome/test/data/extensions/api_test/native_bindings/manifest.json b/chrome/test/data/extensions/api_test/native_bindings/extension/manifest.json
similarity index 100%
rename from chrome/test/data/extensions/api_test/native_bindings/manifest.json
rename to chrome/test/data/extensions/api_test/native_bindings/extension/manifest.json
diff --git a/chrome/test/data/extensions/api_test/native_bindings/messaging_test.html b/chrome/test/data/extensions/api_test/native_bindings/extension/messaging_test.html
similarity index 100%
rename from chrome/test/data/extensions/api_test/native_bindings/messaging_test.html
rename to chrome/test/data/extensions/api_test/native_bindings/extension/messaging_test.html
diff --git a/chrome/test/data/extensions/api_test/native_bindings/platform_app/main.html b/chrome/test/data/extensions/api_test/native_bindings/platform_app/main.html
new file mode 100644
index 0000000..23a65adc
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/native_bindings/platform_app/main.html
@@ -0,0 +1,10 @@
+<!--
+ * Copyright 2017 The Chromium Authors. All rights reserved.  Use of this
+ * source code is governed by a BSD-style license that can be found in the
+ * LICENSE file.
+-->
+<html>
+<body>
+<script src="main.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/api_test/native_bindings/platform_app/main.js b/chrome/test/data/extensions/api_test/native_bindings/platform_app/main.js
new file mode 100644
index 0000000..c0e57ab
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/native_bindings/platform_app/main.js
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.test.assertTrue(!!chrome.app, 'app');
+chrome.test.assertTrue(!!chrome.app.window, 'app.window');
+
+var currentWindow = chrome.app.window.current();
+// Current window is pretty funny and has a ton of custom JS bindings, also
+// utilizing an internal API (currentWindowInternal). Test a bunch of stuff.
+chrome.test.assertTrue(!!currentWindow, 'currentWindow');
+// An instance property.
+chrome.test.assertTrue(!!currentWindow.innerBounds, 'innerBounds');
+// A method from the internal API.
+chrome.test.assertTrue(!!currentWindow.drawAttention, 'drawAttention');
+// A method on the prototype.
+chrome.test.assertTrue(!!currentWindow.isFullscreen, 'isFullscreen');
+// A property on the prototype.
+chrome.test.assertTrue(!!currentWindow.contentWindow, 'contentWindow');
+
+chrome.test.succeed();
diff --git a/chrome/test/data/extensions/api_test/native_bindings/platform_app/manifest.json b/chrome/test/data/extensions/api_test/native_bindings/platform_app/manifest.json
new file mode 100644
index 0000000..3f5c332c
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/native_bindings/platform_app/manifest.json
@@ -0,0 +1,9 @@
+{
+  "name": "Platform App Test: minimal platform app",
+  "version": "1",
+  "app": {
+    "background": {
+      "scripts": ["test.js"]
+    }
+  }
+}
diff --git a/chrome/test/data/extensions/api_test/native_bindings/platform_app/test.js b/chrome/test/data/extensions/api_test/native_bindings/platform_app/test.js
new file mode 100644
index 0000000..40a8908
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/native_bindings/platform_app/test.js
@@ -0,0 +1,7 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.app.runtime.onLaunched.addListener(function() {
+  chrome.app.window.create('main.html', {}, function () {});
+});
diff --git a/chrome/test/data/local_ntp_browsertest.html b/chrome/test/data/local_ntp_browsertest.html
index 59d6865d..8d84e278 100644
--- a/chrome/test/data/local_ntp_browsertest.html
+++ b/chrome/test/data/local_ntp_browsertest.html
@@ -12,7 +12,15 @@
   <script src="local_ntp_browsertest.js"></script>
   <template id="local-ntp-body">
     <div id="ntp-contents">
+      <div id="logo" title="Google"></div>
+      <div id="fakebox">
+        <div id="fakebox-text"></div>
+        <input id="fakebox-input" autocomplete="off" tabIndex="-1" type="url"
+            aria-hidden="true">
+        <div id="cursor"></div>
+      </div>
       <div id="most-visited">
+        <!-- The container for the tiles. The MV iframe goes in here. -->
         <div id="mv-tiles"></div>
         <!-- Notification shown when a tile is blacklisted. -->
         <div id="mv-notice" class="mv-notice-hide">
diff --git a/chrome/test/data/local_ntp_browsertest.js b/chrome/test/data/local_ntp_browsertest.js
index 57f5b7ba..50028119 100644
--- a/chrome/test/data/local_ntp_browsertest.js
+++ b/chrome/test/data/local_ntp_browsertest.js
@@ -66,14 +66,24 @@
 
 
 /**
+ * Checks whether a given HTMLElement exists and is visible.
+ * @param {HTMLElement|undefined} elem An HTMLElement.
+ * @return {boolean} True if the element exists and is visible.
+ */
+function elementIsVisible(elem) {
+  return elem && elem.offsetWidth > 0 && elem.offsetHeight > 0;
+}
+
+
+/**
  * Tests that Google NTPs show a fakebox and logo.
  */
 function testShowsFakeboxAndLogoIfGoogle() {
   var localNTP = LocalNTP();
   configData.isGooglePage = true;
   localNTP.init();
-  assert($('fakebox'));
-  assert($('logo'));
+  assert(elementIsVisible($('fakebox')));
+  assert(elementIsVisible($('logo')));
 }
 
 
@@ -84,6 +94,6 @@
   var localNTP = LocalNTP();
   configData.isGooglePage = false;
   localNTP.init();
-  assert(!$('fakebox'));
-  assert(!$('logo'));
+  assert(!elementIsVisible($('fakebox')));
+  assert(!elementIsVisible($('logo')));
 }
diff --git a/chrome/test/data/webui/settings/bluetooth_page_tests.js b/chrome/test/data/webui/settings/bluetooth_page_tests.js
index 6e1ccfc..518c7669 100644
--- a/chrome/test/data/webui/settings/bluetooth_page_tests.js
+++ b/chrome/test/data/webui/settings/bluetooth_page_tests.js
@@ -23,16 +23,15 @@
       name: 'FakePairedDevice2',
       paired: true,
       connected: false,
-      connecting: true,
     },
     {
       address: '00:00:00:00:00:01',
-      name: 'FakeUnPairedDevice1',
+      name: 'FakeUnpairedDevice1',
       paired: false,
     },
     {
       address: '00:00:00:00:00:02',
-      name: 'FakeUnPairedDevice2',
+      name: 'FakeUnpairedDevice2',
       paired: false,
     },
   ];
@@ -65,6 +64,7 @@
     bluetoothPage = document.createElement('settings-bluetooth-page');
     assertTrue(!!bluetoothPage);
 
+    bluetoothApi_.setDevicesForTest([]);
     document.body.appendChild(bluetoothPage);
     Polymer.dom.flush();
   });
@@ -108,61 +108,77 @@
       assertFalse(bluetoothPage.bluetoothEnabled_);
     });
 
-    test('device list', function() {
-      var deviceList = subpage.$.container;
-      assertTrue(!!deviceList);
-      assertTrue(deviceList.hidden);
-      assertFalse(subpage.$.noDevices.hidden);
+    test('paired device list', function() {
+      var pairedContainer = subpage.$.pairedContainer;
+      assertTrue(!!pairedContainer);
+      assertTrue(pairedContainer.hidden);
+      assertFalse(subpage.$.noPairedDevices.hidden);
 
       bluetoothApi_.setDevicesForTest(fakeDevices_);
       Polymer.dom.flush();
       assertEquals(4, subpage.deviceList_.length);
-      assertTrue(subpage.$.noDevices.hidden);
+      assertEquals(2, subpage.pairedDeviceList_.length);
+      assertTrue(subpage.$.noPairedDevices.hidden);
 
-      var devicesIronList = subpage.$$('#container > iron-list');
-      assertTrue(!!devicesIronList);
-      devicesIronList.notifyResize();
+      var ironList = subpage.$.pairedDevices;
+      assertTrue(!!ironList);
+      ironList.notifyResize();
       Polymer.dom.flush();
-      var devices = deviceList.querySelectorAll('bluetooth-device-list-item');
+      var devices = ironList.querySelectorAll('bluetooth-device-list-item');
       assertEquals(2, devices.length);
       assertTrue(devices[0].device.connected);
       assertFalse(devices[1].device.connected);
-      assertTrue(devices[1].device.connecting);
     });
 
-    test('device dialog', function() {
-      // Tap the 'add device' button.
-      MockInteractions.tap(subpage.$.pairButton);
-      Polymer.dom.flush();
+    test('unpaired device list', function() {
+      var unpairedContainer = subpage.$.unpairedContainer;
+      assertTrue(!!unpairedContainer);
+      assertTrue(unpairedContainer.hidden);
+      assertFalse(subpage.$.noUnpairedDevices.hidden);
 
-      // Ensure the dialog appears.
+      bluetoothApi_.setDevicesForTest(fakeDevices_);
+      Polymer.dom.flush();
+      assertEquals(4, subpage.deviceList_.length);
+      assertEquals(2, subpage.unpairedDeviceList_.length);
+      assertTrue(subpage.$.noUnpairedDevices.hidden);
+
+      var ironList = subpage.$.unpairedDevices;
+      assertTrue(!!ironList);
+      ironList.notifyResize();
+      Polymer.dom.flush();
+      var devices = ironList.querySelectorAll('bluetooth-device-list-item');
+      assertEquals(2, devices.length);
+      assertFalse(devices[0].device.paired);
+      assertFalse(devices[1].device.paired);
+    });
+
+    test('pair device', function(done) {
+      bluetoothApi_.setDevicesForTest(fakeDevices_);
+      Polymer.dom.flush();
+      assertEquals(4, subpage.deviceList_.length);
+      assertEquals(2, subpage.pairedDeviceList_.length);
+      assertEquals(2, subpage.unpairedDeviceList_.length);
+
+      var address = subpage.unpairedDeviceList_[0].address;
+      bluetoothPrivateApi_.connect(address, function() {
+        Polymer.dom.flush();
+        assertEquals(3, subpage.pairedDeviceList_.length);
+        assertEquals(1, subpage.unpairedDeviceList_.length);
+        done();
+      });
+    });
+
+    test('pair dialog', function() {
+      bluetoothApi_.setDevicesForTest(fakeDevices_);
+      Polymer.dom.flush();
       var dialog = subpage.$.deviceDialog;
       assertTrue(!!dialog);
-      assertTrue(dialog.$.dialog.open);
-      assertEquals(dialog.deviceList.length, 4);
-
-      // Ensure the dialog has the expected devices.
-      var devicesIronList = dialog.$$('#dialogDeviceList iron-list');
-      assertTrue(!!devicesIronList);
-      devicesIronList.notifyResize();
-      Polymer.dom.flush();
-      var devices =
-          devicesIronList.querySelectorAll('bluetooth-device-list-item');
-      assertEquals(devices.length, 2);
-
-      // Select a device.
-      MockInteractions.tap(devices[0].$$('div'));
-      Polymer.dom.flush();
-      // Ensure the pairing dialog is shown.
-      assertTrue(!!dialog.$$('#pairing'));
-
-      // Ensure the device wass connected to.
-      expectEquals(1, bluetoothPrivateApi_.connectedDevices_.size);
-
-      // Close the dialog.
-      dialog.close();
-      Polymer.dom.flush();
       assertFalse(dialog.$.dialog.open);
+
+      // Simulate selecting an unpaired device; should show the pair dialog.
+      subpage.connectDevice_(subpage.unpairedDeviceList_[0]);
+      Polymer.dom.flush();
+      assertTrue(dialog.$.dialog.open);
     });
   });
 });
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index f2556bac..674ccbf 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -689,7 +689,8 @@
     'test_site_settings_prefs_browser_proxy.js',
     'zoom_levels_tests.js',
     'usb_devices_tests.js',
-    'protocol_handlers_tests.js'
+    'protocol_handlers_tests.js',
+    'site_data_details_subpage_tests.js',
   ]),
 };
 
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js
index c953240..4254c20 100644
--- a/chrome/test/data/webui/settings/device_page_tests.js
+++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -609,48 +609,6 @@
               .updatePowerStatusCalled_);
         });
 
-        test('battery status', function() {
-          var icon = powerRow.querySelector('iron-icon');
-          assertEquals('settings:battery-unknown', icon.icon);
-
-          // Start at 50%.
-          var batteryStatus = {
-            charging: false,
-            calculating: false,
-            percent: 50,
-            statusText: '5 hours left',
-          };
-          cr.webUIListenerCallback(
-              'battery-status-changed', Object.assign({}, batteryStatus));
-          setPowerSources([], '', false);
-          assertEquals(icon.icon, 'settings:battery-50');
-
-          // Update to charging.
-          var powerSource = {
-            id: '1',
-            type: settings.PowerDeviceType.DEDICATED_CHARGER,
-            description: 'AC adapter',
-          };
-          batteryStatus.charging = true;
-          batteryStatus.percent = 65;
-          cr.webUIListenerCallback(
-              'battery-status-changed', Object.assign({}, batteryStatus));
-          setPowerSources([powerSource], powerSource.id, false);
-          assertEquals(icon.icon, 'settings:battery-charging-60');
-
-          // Update with a low-power charger.
-          setPowerSources([powerSource], powerSource.id, true);
-          assertEquals(icon.icon, 'settings:battery-unreliable');
-
-          // Update with no charger and a critical battery level.
-          batteryStatus.charging = false;
-          batteryStatus.percent = 2;
-          cr.webUIListenerCallback(
-              'battery-status-changed', Object.assign({}, batteryStatus));
-          setPowerSources([], '', false);
-          assertEquals(icon.icon, 'settings:battery-alert');
-        });
-
         test('power sources', function() {
           var batteryStatus = {
             charging: false,
diff --git a/chrome/test/data/webui/settings/fake_bluetooth.js b/chrome/test/data/webui/settings/fake_bluetooth.js
index bda3e4d..8af4983c 100644
--- a/chrome/test/data/webui/settings/fake_bluetooth.js
+++ b/chrome/test/data/webui/settings/fake_bluetooth.js
@@ -25,17 +25,13 @@
 
   FakeBluetooth.prototype = {
     // Public testing methods.
-    /**
-     * @param {boolean} enabled
-     */
+    /** @param {boolean} enabled */
     setEnabled: function(enabled) {
       this.adapterState.powered = enabled;
       this.onAdapterStateChanged.callListeners(this.adapterState);
     },
 
-    /**
-     * @param {!Array<!chrome.bluetooth.Device>} devices
-     */
+    /** @param {!Array<!chrome.bluetooth.Device>} devices */
     setDevicesForTest: function(devices) {
       for (var d of this.devices)
         this.onDeviceRemoved.callListeners(d);
@@ -44,6 +40,30 @@
         this.onDeviceAdded.callListeners(d);
     },
 
+    /**
+     * @param {string}
+     * @return {!chrome.bluetooth.Device}
+     */
+    getDeviceForTest: function(address) {
+      return this.devices.find(function(d) {
+        return d.address == address;
+      });
+    },
+
+    /** @param {!chrome.bluetooth.Device} device */
+    updateDeviceForTest: function(device, opt_callback) {
+      var index = this.devices.findIndex(function(d) {
+        return d.address == device.address;
+      });
+      if (index == -1) {
+        this.devices.push(device);
+        this.onDeviceAdded.callListeners(device);
+        return;
+      }
+      this.devices[index] = device;
+      this.onDeviceChanged.callListeners(device);
+    },
+
     // Bluetooth overrides.
     /** @override */
     getAdapterState: function(callback) {
diff --git a/chrome/test/data/webui/settings/fake_bluetooth_private.js b/chrome/test/data/webui/settings/fake_bluetooth_private.js
index 7367da9..efbe7073 100644
--- a/chrome/test/data/webui/settings/fake_bluetooth_private.js
+++ b/chrome/test/data/webui/settings/fake_bluetooth_private.js
@@ -26,14 +26,14 @@
     setAdapterState: function(state, opt_callback) {
       this.bluetoothApi_.adapterState = state;
       if (opt_callback)
-        setTimeout(opt_callback);
+        opt_callback();
     },
 
     /** @override */
     setPairingResponse: function(options, opt_callback) {
       this.pairingResponses_[options.device.address] = options;
       if (opt_callback)
-        setTimeout(opt_callback);
+        opt_callback();
     },
 
     /** @override */
@@ -47,9 +47,13 @@
 
     /** @override */
     connect: function(address, opt_callback) {
-      this.connectedDevices_.add(address);
+      var device =
+          this.bluetoothApi_.getDeviceForTest(address) || {address: address};
+      device.paired = true;
+      device.connecting = true;
+      this.bluetoothApi_.updateDeviceForTest(device);
       if (opt_callback)
-        setTimeout(opt_callback);
+        opt_callback(chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS);
     },
 
     /** @override */
diff --git a/chrome/test/data/webui/settings/languages_page_browsertest.js b/chrome/test/data/webui/settings/languages_page_browsertest.js
index ed8935a..99efbc2 100644
--- a/chrome/test/data/webui/settings/languages_page_browsertest.js
+++ b/chrome/test/data/webui/settings/languages_page_browsertest.js
@@ -116,7 +116,7 @@
 
       setup(function(done) {
         var addLanguagesButton =
-            languagesCollapse.querySelector('.list-button:last-of-type');
+            languagesCollapse.querySelector('#addLanguages');
         MockInteractions.tap(addLanguagesButton);
 
         // The page stamps the dialog, registers listeners, and populates the
@@ -412,7 +412,7 @@
       if (cr.isChromeOS) {
         assertTrue(inputMethodSettingsExist);
         var manageInputMethodsButton =
-            inputMethodsCollapse.querySelector('.list-button:last-of-type');
+            inputMethodsCollapse.querySelector('#manageInputMethods');
         MockInteractions.tap(manageInputMethodsButton);
         assertTrue(!!languagesPage.$$('settings-manage-input-methods-page'));
       } else {
@@ -451,7 +451,7 @@
     });
 
     if (!cr.isMac) {
-      test('spellcheck edit dictionary page add word button', function() {
+      test('spellcheck edit dictionary page add word validation', function() {
         assertFalse(!!languagesPage.$$('settings-edit-dictionary-page'));
         var spellCheckCollapse = languagesPage.$.spellCheckCollapse;
         MockInteractions.tap(
diff --git a/chrome/test/data/webui/settings/site_data_details_subpage_tests.js b/chrome/test/data/webui/settings/site_data_details_subpage_tests.js
new file mode 100644
index 0000000..43b5051
--- /dev/null
+++ b/chrome/test/data/webui/settings/site_data_details_subpage_tests.js
@@ -0,0 +1,77 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Suite of tests for site-data-details-subpage. */
+suite('SiteDataDetailsSubpage', function() {
+  /** @type {?SiteDataDetailsSubpageElement} */
+  var page = null;
+
+  /** @type {TestSiteSettingsPrefsBrowserProxy} */
+  var browserProxy = null;
+  /** @type {!CookieDetails} */
+  var cookieDetails = {
+    accessibleToScript: "Yes",
+    content: "dummy_cookie_contents",
+    created: "Tuesday, February 7, 2017 at 11:28:45 AM",
+    domain: ".foo.com",
+    expires: "Wednesday, February 7, 2018 at 11:28:45 AM",
+    hasChildren: false,
+    id: "328",
+    idPath: "74,165,328",
+    name: "abcd",
+    path: "/",
+    sendfor: "Any kind of connection",
+    title: "abcd",
+    type: "cookie"
+  };
+
+  /** @type {!CookieList} */
+  var cookieList = {
+    id: 'fooId',
+    children: [cookieDetails],
+  };
+
+  var site = 'foo.com';
+
+  setup(function() {
+    browserProxy = new TestSiteSettingsPrefsBrowserProxy();
+    browserProxy.setCookieDetails(cookieList);
+    settings.SiteSettingsPrefsBrowserProxyImpl.instance_ = browserProxy;
+    PolymerTest.clearBody();
+    page = document.createElement('site-data-details-subpage');
+    settings.navigateTo(
+        settings.Route.SITE_SETTINGS_DATA_DETAILS,
+        new URLSearchParams('site=' + site));
+
+    document.body.appendChild(page);
+  });
+
+  teardown(function() {
+    settings.resetRouteForTesting();
+  });
+
+  test('DetailsShownForCookie', function() {
+    return browserProxy.whenCalled('getCookieDetails').then(
+        function(actualSite) {
+          assertEquals(site, actualSite);
+
+          Polymer.dom.flush();
+          var entries = page.root.querySelectorAll('.settings-box');
+          assertEquals(1, entries.length);
+
+          var listItems = page.root.querySelectorAll('.list-item');
+          // |cookieInfo| is a global var defined in
+          // site_settings/cookie_info.js, and specifies the fields that are
+          // shown for a cookie.
+          assertEquals(cookieInfo.cookie.length, listItems.length);
+
+          // Check that all the cookie information is presented in the DOM.
+          var cookieDetailValues = page.root.querySelectorAll('.secondary');
+          cookieDetailValues.forEach(function(div, i) {
+            var key = cookieInfo.cookie[i][0];
+            assertEquals(cookieDetails[key], div.textContent);
+          });
+        });
+  });
+});
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js
index 44162ea..b3017cb 100644
--- a/chrome/test/data/webui/settings/site_list_tests.js
+++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -347,6 +347,9 @@
 
       teardown(function() {
         closeActionMenu();
+        // The code being tested changes the Route. Reset so that state is not
+        // leaked across tests.
+        settings.resetRouteForTesting();
       });
 
       /**
diff --git a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
index 83f0280..b350452 100644
--- a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
+++ b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
@@ -48,6 +48,7 @@
   settings.TestBrowserProxy.call(this, [
     'fetchUsbDevices',
     'fetchZoomLevels',
+    'getCookieDetails',
     'getDefaultValueForContentType',
     'getExceptionList',
     'observeProtocolHandlers',
@@ -72,6 +73,9 @@
 
   /** @private {!Array<!ProtocolEntry>} */
   this.protocolHandlers_ = [];
+
+  /** @private {?CookieList} */
+  this.cookieDetails_ = null;
 };
 
 TestSiteSettingsPrefsBrowserProxy.prototype = {
@@ -126,6 +130,19 @@
   },
 
   /** @override */
+  getCookieDetails: function(site) {
+    this.methodCalled('getCookieDetails', site);
+    return Promise.resolve(this.cookieDetails_  || {id: '', children: []});
+  },
+
+  /**
+   * @param {!CookieList} cookieList
+   */
+  setCookieDetails: function(cookieList) {
+    this.cookieDetails_ = cookieList;
+  },
+
+  /** @override */
   getDefaultValueForContentType: function(contentType) {
     this.methodCalled('getDefaultValueForContentType', contentType);
 
diff --git a/chromecast/app/cast_test_launcher.cc b/chromecast/app/cast_test_launcher.cc
index 9a6a989..76e5dcb8 100644
--- a/chromecast/app/cast_test_launcher.cc
+++ b/chromecast/app/cast_test_launcher.cc
@@ -6,7 +6,6 @@
 #include "base/sys_info.h"
 #include "base/test/test_suite.h"
 #include "chromecast/app/cast_main_delegate.h"
-#include "chromecast/base/cast_paths.h"
 #include "content/public/test/test_launcher.h"
 #include "ipc/ipc_channel.h"
 #include "mojo/edk/embedder/embedder.h"
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 259ef3f..2d6be6d 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -55,6 +55,8 @@
     "metrics/cast_stability_metrics_provider.h",
     "pref_service_helper.cc",
     "pref_service_helper.h",
+    "renderer_prelauncher.cc",
+    "renderer_prelauncher.h",
     "service/cast_service_simple.cc",
     "service/cast_service_simple.h",
     "url_request_context_factory.cc",
@@ -235,6 +237,7 @@
   testonly = true
   sources = [
     "cast_media_blocker_browsertest.cc",
+    "renderer_prelauncher_test.cc",
     "test/cast_navigation_browsertest.cc",
   ]
 
@@ -243,6 +246,8 @@
   deps = [
     ":test_support",
     "//chromecast:chromecast_features",
+    "//chromecast/base:chromecast_switches",
+    "//chromecast/base/metrics",
     "//media/base:test_support",
   ]
 }
diff --git a/chromecast/browser/android/cast_content_window_android.cc b/chromecast/browser/android/cast_content_window_android.cc
index b5d7a7b..a82992d6 100644
--- a/chromecast/browser/android/cast_content_window_android.cc
+++ b/chromecast/browser/android/cast_content_window_android.cc
@@ -72,7 +72,8 @@
 
 std::unique_ptr<content::WebContents>
 CastContentWindowAndroid::CreateWebContents(
-    content::BrowserContext* browser_context) {
+    content::BrowserContext* browser_context,
+    scoped_refptr<content::SiteInstance> site_instance) {
   CHECK(display::Screen::GetScreen());
   gfx::Size display_size =
       display::Screen::GetScreen()->GetPrimaryDisplay().size();
@@ -80,6 +81,7 @@
   content::WebContents::CreateParams create_params(browser_context, nullptr);
   create_params.routing_id = MSG_ROUTING_NONE;
   create_params.initial_size = display_size;
+  create_params.site_instance = site_instance;
   std::unique_ptr<content::WebContents> web_contents(
       content::WebContents::Create(create_params));
 
diff --git a/chromecast/browser/android/cast_content_window_android.h b/chromecast/browser/android/cast_content_window_android.h
index cd3f7ed..d1cf85d 100644
--- a/chromecast/browser/android/cast_content_window_android.h
+++ b/chromecast/browser/android/cast_content_window_android.h
@@ -36,7 +36,8 @@
   void ShowWebContents(content::WebContents* web_contents,
                        CastWindowManager* window_manager) override;
   std::unique_ptr<content::WebContents> CreateWebContents(
-      content::BrowserContext* browser_context) override;
+      content::BrowserContext* browser_context,
+      scoped_refptr<content::SiteInstance> site_instance) override;
 
   // content::WebContentsObserver implementation:
   void DidFirstVisuallyNonEmptyPaint() override;
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index e878725..dae8b315 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -86,6 +86,7 @@
                      base::Unretained(browser_client)),
           base::Bind(&CastContentBrowserClient::CreateCdmFactory,
                      base::Unretained(browser_client)),
+          browser_client->GetVideoModeSwitcher(),
           browser_client->GetVideoResolutionPolicy(),
           browser_client->media_resource_tracker()));
   return std::unique_ptr<service_manager::Service>(
@@ -138,6 +139,10 @@
                                              window_manager);
 }
 
+media::VideoModeSwitcher* CastContentBrowserClient::GetVideoModeSwitcher() {
+  return nullptr;
+}
+
 #if !defined(OS_ANDROID)
 media::VideoResolutionPolicy*
 CastContentBrowserClient::GetVideoResolutionPolicy() {
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index ae925bb..ce2ba763 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -46,6 +46,7 @@
 struct MediaPipelineDeviceParams;
 class MediaResourceTracker;
 class VideoPlaneController;
+class VideoModeSwitcher;
 class VideoResolutionPolicy;
 }
 
@@ -81,6 +82,8 @@
       media::VideoPlaneController* video_plane_controller,
       CastWindowManager* window_manager);
 
+  virtual media::VideoModeSwitcher* GetVideoModeSwitcher();
+
 #if !defined(OS_ANDROID)
   // Gets object for enforcing video resolution policy restrictions.
   virtual media::VideoResolutionPolicy* GetVideoResolutionPolicy();
diff --git a/chromecast/browser/cast_content_window.h b/chromecast/browser/cast_content_window.h
index b53b5650..9047a52 100644
--- a/chromecast/browser/cast_content_window.h
+++ b/chromecast/browser/cast_content_window.h
@@ -8,10 +8,13 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "content/public/browser/web_contents.h"
 #include "ui/events/event.h"
 
 namespace content {
 class BrowserContext;
+class SiteInstance;
 class WebContents;
 }
 
@@ -55,7 +58,12 @@
   // TODO(derekjchow): remove this function from this class, since it doesn't
   // have anything to do with displaying web_contents.
   virtual std::unique_ptr<content::WebContents> CreateWebContents(
-      content::BrowserContext* browser_context) = 0;
+      content::BrowserContext* browser_context,
+      scoped_refptr<content::SiteInstance> site_instance) = 0;
+  std::unique_ptr<content::WebContents> CreateWebContents(
+      content::BrowserContext* browser_context) {
+    return CreateWebContents(browser_context, nullptr);
+  }
 };
 
 }  // namespace shell
diff --git a/chromecast/browser/cast_content_window_linux.cc b/chromecast/browser/cast_content_window_linux.cc
index a34f170..b57c412d 100644
--- a/chromecast/browser/cast_content_window_linux.cc
+++ b/chromecast/browser/cast_content_window_linux.cc
@@ -41,7 +41,8 @@
 }
 
 std::unique_ptr<content::WebContents> CastContentWindowLinux::CreateWebContents(
-    content::BrowserContext* browser_context) {
+    content::BrowserContext* browser_context,
+    scoped_refptr<content::SiteInstance> site_instance) {
   CHECK(display::Screen::GetScreen());
   gfx::Size display_size =
       display::Screen::GetScreen()->GetPrimaryDisplay().size();
@@ -49,6 +50,7 @@
   content::WebContents::CreateParams create_params(browser_context, NULL);
   create_params.routing_id = MSG_ROUTING_NONE;
   create_params.initial_size = display_size;
+  create_params.site_instance = site_instance;
   content::WebContents* web_contents =
       content::WebContents::Create(create_params);
 
diff --git a/chromecast/browser/cast_content_window_linux.h b/chromecast/browser/cast_content_window_linux.h
index fe8cecd..a083a11 100644
--- a/chromecast/browser/cast_content_window_linux.h
+++ b/chromecast/browser/cast_content_window_linux.h
@@ -31,7 +31,8 @@
   void ShowWebContents(content::WebContents* web_contents,
                        CastWindowManager* window_manager) override;
   std::unique_ptr<content::WebContents> CreateWebContents(
-      content::BrowserContext* browser_context) override;
+      content::BrowserContext* browser_context,
+      scoped_refptr<content::SiteInstance> site_instance) override;
 
   // content::WebContentsObserver implementation:
   void DidStartNavigation(
diff --git a/chromecast/browser/renderer_prelauncher.cc b/chromecast/browser/renderer_prelauncher.cc
new file mode 100644
index 0000000..6bde6fe
--- /dev/null
+++ b/chromecast/browser/renderer_prelauncher.cc
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/renderer_prelauncher.h"
+
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/common/child_process_host.h"
+
+namespace chromecast {
+
+RendererPrelauncher::RendererPrelauncher(
+    content::BrowserContext* browser_context,
+    const GURL& gurl)
+    : browser_context_(browser_context),
+      gurl_(gurl),
+      rph_routing_id_(MSG_ROUTING_NONE) {}
+
+RendererPrelauncher::~RendererPrelauncher() {
+  if (rph_routing_id_ != MSG_ROUTING_NONE) {
+    DCHECK(site_instance_);
+    site_instance_->GetProcess()->RemoveRoute(rph_routing_id_);
+  }
+}
+
+void RendererPrelauncher::Prelaunch() {
+  DLOG(INFO) << "Prelaunching for: " << gurl_;
+  site_instance_ = content::SiteInstance::CreateForURL(browser_context_, gurl_);
+  content::RenderProcessHost* rph = site_instance_->GetProcess();
+  rph_routing_id_ = rph->GetNextRoutingID();
+  rph->AddRoute(rph_routing_id_, this);
+  rph->Init();
+}
+
+// We don't process any IPC messages, but we do register as an IPC receiver to
+// keep the RenderProcessHost alive.
+bool RendererPrelauncher::OnMessageReceived(const IPC::Message& message) {
+  return false;
+}
+
+}  // namespace chromecast
diff --git a/chromecast/browser/renderer_prelauncher.h b/chromecast/browser/renderer_prelauncher.h
new file mode 100644
index 0000000..c2a85c7
--- /dev/null
+++ b/chromecast/browser/renderer_prelauncher.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_BROWSER_RENDERER_PRELAUNCHER_H_
+#define CHROMECAST_BROWSER_RENDERER_PRELAUNCHER_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "ipc/ipc_listener.h"
+#include "url/gurl.h"
+
+namespace content {
+class BrowserContext;
+class RenderProcessHost;
+class SiteInstance;
+}
+
+namespace chromecast {
+
+// This class pre-launches a renderer process for the SiteInstance of a URL,
+// and retains a handle on its RenderProcessHost to keep it alive even when
+// there is no WebContents using the renderer process.  To release the
+// RenderProcessHost, this class must be deleted.
+class RendererPrelauncher : private IPC::Listener {
+ public:
+  RendererPrelauncher(content::BrowserContext* browser_context,
+                      const GURL& gurl);
+  ~RendererPrelauncher() override;
+
+  void Prelaunch();
+
+  scoped_refptr<content::SiteInstance> site_instance() {
+    return site_instance_;
+  }
+
+ private:
+  // IPC::Listener implementation:
+  bool OnMessageReceived(const IPC::Message& message) override;
+
+  content::BrowserContext* const browser_context_;
+  scoped_refptr<content::SiteInstance> site_instance_;
+  GURL gurl_;
+  int32_t rph_routing_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(RendererPrelauncher);
+};
+
+}  // namespace chromecast
+
+#endif  // CHROMECAST_BROWSER_RENDERER_PRELAUNCHER_H_
diff --git a/chromecast/browser/renderer_prelauncher_test.cc b/chromecast/browser/renderer_prelauncher_test.cc
new file mode 100644
index 0000000..3e36800c
--- /dev/null
+++ b/chromecast/browser/renderer_prelauncher_test.cc
@@ -0,0 +1,95 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/browser/renderer_prelauncher.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "chromecast/base/chromecast_switches.h"
+#include "chromecast/base/metrics/cast_metrics_helper.h"
+#include "chromecast/browser/cast_browser_context.h"
+#include "chromecast/browser/cast_browser_process.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_base.h"
+
+namespace chromecast {
+
+class RendererPrelauncherTest : public content::BrowserTestBase {
+ public:
+  RendererPrelauncherTest() {}
+  ~RendererPrelauncherTest() override {}
+
+ protected:
+  // content::BrowserTestBase implementation:
+  void SetUp() override;
+  void RunTestOnMainThreadLoop() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RendererPrelauncherTest);
+};
+
+void RendererPrelauncherTest::SetUp() {
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  command_line->AppendSwitch(switches::kNoWifi);
+  command_line->AppendSwitchASCII(switches::kTestType, "browser");
+
+  BrowserTestBase::SetUp();
+}
+
+void RendererPrelauncherTest::RunTestOnMainThreadLoop() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  base::RunLoop().RunUntilIdle();
+
+  metrics::CastMetricsHelper::GetInstance()->SetDummySessionIdForTesting();
+
+  SetUpOnMainThread();
+  RunTestOnMainThread();
+  TearDownOnMainThread();
+}
+
+IN_PROC_BROWSER_TEST_F(RendererPrelauncherTest, ReusedRenderer) {
+  GURL gurl("https://www.google.com/");
+  content::BrowserContext* browser_context =
+      shell::CastBrowserProcess::GetInstance()->browser_context();
+  EXPECT_TRUE(browser_context);
+
+  // Prelaunch a renderer process for the url.
+  std::unique_ptr<RendererPrelauncher> prelauncher(
+      new RendererPrelauncher(browser_context, gurl));
+  prelauncher->Prelaunch();
+  scoped_refptr<content::SiteInstance> site_instance =
+      prelauncher->site_instance();
+  EXPECT_TRUE(site_instance->HasProcess());
+
+  // Launch a web contents for the site instance.
+  content::WebContents::CreateParams create_params(browser_context, NULL);
+  create_params.site_instance = site_instance;
+  std::unique_ptr<content::WebContents> web_contents(
+      content::WebContents::Create(create_params));
+  EXPECT_EQ(site_instance->GetProcess(),
+            web_contents->GetSiteInstance()->GetProcess());
+
+  // Nativgate to the url.
+  content::NavigationController::LoadURLParams params(gurl);
+  web_contents->GetController().LoadURLWithParams(params);
+  EXPECT_EQ(site_instance->GetProcess(),
+            web_contents->GetSiteInstance()->GetProcess());
+
+  // Ensure that the renderer process terminates.
+  prelauncher.reset();
+  web_contents.reset();
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSingleProcess)) {
+    EXPECT_FALSE(site_instance->HasProcess());
+  }
+}
+
+}  // namespace chromecast
diff --git a/chromecast/browser/service/cast_service_simple.cc b/chromecast/browser/service/cast_service_simple.cc
index 92de391..d2ac5b75 100644
--- a/chromecast/browser/service/cast_service_simple.cc
+++ b/chromecast/browser/service/cast_service_simple.cc
@@ -11,6 +11,7 @@
 #include "base/memory/ptr_util.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
 #include "net/base/filename_util.h"
 #include "net/url_request/url_request_context_getter.h"
 
@@ -55,6 +56,10 @@
 }
 
 void CastServiceSimple::StartInternal() {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
+    return;
+  }
+
   window_ = CastContentWindow::Create(this);
   web_contents_ = window_->CreateWebContents(browser_context());
   window_->ShowWebContents(web_contents_.get(), window_manager_);
@@ -66,9 +71,13 @@
 }
 
 void CastServiceSimple::StopInternal() {
-  web_contents_->ClosePage();
-  web_contents_.reset();
-  window_.reset();
+  if (web_contents_) {
+    web_contents_->ClosePage();
+    web_contents_.reset();
+  }
+  if (window_) {
+    window_.reset();
+  }
 }
 
 void CastServiceSimple::OnWindowDestroyed() {}
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc
index 5dd6955a..5b938fb4 100644
--- a/chromecast/browser/url_request_context_factory.cc
+++ b/chromecast/browser/url_request_context_factory.cc
@@ -128,8 +128,8 @@
       content::BrowserContext* browser_context,
       content::ProtocolHandlerMap* protocol_handlers,
       content::URLRequestInterceptorScopedVector request_interceptors)
-      : browser_context_(browser_context),
-        factory_(factory),
+      : factory_(factory),
+        cookie_path_(browser_context->GetPath().Append(kCookieStoreFile)),
         request_interceptors_(std::move(request_interceptors)) {
     std::swap(protocol_handlers_, *protocol_handlers);
   }
@@ -137,8 +137,7 @@
   net::URLRequestContext* GetURLRequestContext() override {
     if (!request_context_) {
       request_context_.reset(factory_->CreateMainRequestContext(
-          browser_context_, &protocol_handlers_,
-          std::move(request_interceptors_)));
+          cookie_path_, &protocol_handlers_, std::move(request_interceptors_)));
       protocol_handlers_.clear();
     }
     return request_context_.get();
@@ -153,8 +152,8 @@
  private:
   ~MainURLRequestContextGetter() override {}
 
-  content::BrowserContext* const browser_context_;
   URLRequestContextFactory* const factory_;
+  base::FilePath cookie_path_;
   content::ProtocolHandlerMap protocol_handlers_;
   content::URLRequestInterceptorScopedVector request_interceptors_;
   std::unique_ptr<net::URLRequestContext> request_context_;
@@ -386,7 +385,7 @@
 }
 
 net::URLRequestContext* URLRequestContextFactory::CreateMainRequestContext(
-    content::BrowserContext* browser_context,
+    const base::FilePath& cookie_path,
     content::ProtocolHandlerMap* protocol_handlers,
     content::URLRequestInterceptorScopedVector request_interceptors) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -406,8 +405,8 @@
       protocol_handlers, std::move(request_interceptors));
 
   content::CookieStoreConfig cookie_config(
-      browser_context->GetPath().Append(kCookieStoreFile),
-      content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, nullptr, nullptr);
+      cookie_path, content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES,
+      nullptr, nullptr);
   main_cookie_store_ = content::CreateCookieStore(cookie_config);
 
   net::URLRequestContext* main_context = new net::URLRequestContext();
diff --git a/chromecast/browser/url_request_context_factory.h b/chromecast/browser/url_request_context_factory.h
index b18f31c..18f5d87 100644
--- a/chromecast/browser/url_request_context_factory.h
+++ b/chromecast/browser/url_request_context_factory.h
@@ -13,6 +13,10 @@
 
 class PrefProxyConfigTracker;
 
+namespace base {
+class FilePath;
+}
+
 namespace net {
 class CookieStore;
 class HttpTransactionFactory;
@@ -88,7 +92,7 @@
   net::URLRequestContext* CreateSystemRequestContext();
   net::URLRequestContext* CreateMediaRequestContext();
   net::URLRequestContext* CreateMainRequestContext(
-      content::BrowserContext* browser_context,
+      const base::FilePath& cookie_path,
       content::ProtocolHandlerMap* protocol_handlers,
       content::URLRequestInterceptorScopedVector request_interceptors);
 
diff --git a/chromecast/media/base/BUILD.gn b/chromecast/media/base/BUILD.gn
index 4f85c03..1b8f1a4 100644
--- a/chromecast/media/base/BUILD.gn
+++ b/chromecast/media/base/BUILD.gn
@@ -34,6 +34,8 @@
     "media_codec_support.h",
     "media_resource_tracker.cc",
     "media_resource_tracker.h",
+    "video_mode_switcher.cc",
+    "video_mode_switcher.h",
     "video_plane_controller.cc",
     "video_plane_controller.h",
   ]
diff --git a/chromecast/media/base/video_mode_switcher.cc b/chromecast/media/base/video_mode_switcher.cc
new file mode 100644
index 0000000..0fe9561f3
--- /dev/null
+++ b/chromecast/media/base/video_mode_switcher.cc
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/base/video_mode_switcher.h"
+
+namespace chromecast {
+namespace media {
+
+VideoModeSwitcher::~VideoModeSwitcher() {}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/base/video_mode_switcher.h b/chromecast/media/base/video_mode_switcher.h
new file mode 100644
index 0000000..11df341
--- /dev/null
+++ b/chromecast/media/base/video_mode_switcher.h
@@ -0,0 +1,40 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_BASE_VIDEO_MODE_SWITCHER_H_
+#define CHROMECAST_MEDIA_BASE_VIDEO_MODE_SWITCHER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+
+namespace media {
+class VideoDecoderConfig;
+}  // namespace media
+
+namespace chromecast {
+namespace media {
+
+// Interface that implements video mode switching for CastRenderer.
+class VideoModeSwitcher {
+ public:
+  virtual ~VideoModeSwitcher();
+
+  // Input parameter is true if mode switch succeeded (or wasn't needed) and
+  // playback should proceed. False indicates failed mode switch.
+  using CompletionCB = base::Callback<void(bool)>;
+
+  // The |video_configs| describe input streams (potentially multiple streams in
+  // case of dual layer content). The |mode_switch_completion_cb| will be
+  // invoked to notify the caller about mode switch result.
+  virtual void SwitchMode(
+      const std::vector<::media::VideoDecoderConfig>& video_configs,
+      const CompletionCB& mode_switch_completion_cb) = 0;
+};
+
+}  // namespace media
+}  // namespace chromecast
+
+#endif  // CHROMECAST_MEDIA_BASE_VIDEO_MODE_SWITCHER_H_
diff --git a/chromecast/media/cma/backend/alsa/audio_decoder_alsa.cc b/chromecast/media/cma/backend/alsa/audio_decoder_alsa.cc
index a83d6a4..e288cc5 100644
--- a/chromecast/media/cma/backend/alsa/audio_decoder_alsa.cc
+++ b/chromecast/media/cma/backend/alsa/audio_decoder_alsa.cc
@@ -153,10 +153,18 @@
   }
   LOG(INFO) << "SetPlaybackRate to " << rate;
 
-  while (!rate_shifter_info_.empty() &&
-         rate_shifter_info_.back().input_frames == 0) {
-    rate_shifter_info_.pop_back();
+  // Remove info for rates that have no pending output left.
+  while (!rate_shifter_info_.empty()) {
+    RateShifterInfo* rate_info = &rate_shifter_info_.back();
+    int64_t possible_output_frames = rate_info->input_frames / rate_info->rate;
+    DCHECK_GE(possible_output_frames, rate_info->output_frames);
+    if (rate_info->output_frames == possible_output_frames) {
+      rate_shifter_info_.pop_back();
+    } else {
+      break;
+    }
   }
+
   rate_shifter_info_.push_back(RateShifterInfo(rate));
   return true;
 }
@@ -351,7 +359,8 @@
     // Bypass rate shifter if the rate is 1.0, and there are no frames queued
     // in the rate shifter.
     if (rate_info->rate == 1.0 && rate_shifter_->frames_buffered() == 0 &&
-        pending_output_frames_ == kNoPendingOutput) {
+        pending_output_frames_ == kNoPendingOutput &&
+        rate_shifter_info_.size() == 1) {
       DCHECK_EQ(rate_info->output_frames, rate_info->input_frames);
       pending_output_frames_ = input_frames;
       if (got_eos_) {
@@ -463,7 +472,7 @@
   mixer_input_->WritePcm(output_buffer);
 
   if (rate_shifter_info_.size() > 1 &&
-      possible_output_frames == rate_info->output_frames) {
+      rate_info->output_frames == possible_output_frames) {
     double remaining_input_frames =
         rate_info->input_frames - (rate_info->output_frames * rate_info->rate);
     rate_shifter_info_.pop_front();
diff --git a/chromecast/media/cma/pipeline/media_pipeline_impl.cc b/chromecast/media/cma/pipeline/media_pipeline_impl.cc
index 14ced50..6b278f9 100644
--- a/chromecast/media/cma/pipeline/media_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/media_pipeline_impl.cc
@@ -360,14 +360,10 @@
   DCHECK_EQ(is_buffering, buffering_controller_->IsBuffering());
 
   if (!client_.buffering_state_cb.is_null()) {
-    if (is_buffering) {
-      // TODO(alokp): WebMediaPlayerImpl currently only handles HAVE_ENOUGH.
-      // See WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
-      // http://crbug.com/144683.
-      NOTIMPLEMENTED();
-    } else {
-      client_.buffering_state_cb.Run(::media::BUFFERING_HAVE_ENOUGH);
-    }
+    ::media::BufferingState state = is_buffering
+                                        ? ::media::BUFFERING_HAVE_NOTHING
+                                        : ::media::BUFFERING_HAVE_ENOUGH;
+    client_.buffering_state_cb.Run(state);
   }
 
   if (is_buffering && (backend_state_ == BACKEND_STATE_PLAYING)) {
diff --git a/chromecast/media/service/cast_mojo_media_client.cc b/chromecast/media/service/cast_mojo_media_client.cc
index 42e9bcef..7fae2e0 100644
--- a/chromecast/media/service/cast_mojo_media_client.cc
+++ b/chromecast/media/service/cast_mojo_media_client.cc
@@ -56,10 +56,12 @@
  public:
   CastRendererFactory(const CreateMediaPipelineBackendCB& create_backend_cb,
                       const scoped_refptr<::media::MediaLog>& media_log,
+                      VideoModeSwitcher* video_mode_switcher,
                       VideoResolutionPolicy* video_resolution_policy,
                       MediaResourceTracker* media_resource_tracker)
       : create_backend_cb_(create_backend_cb),
         media_log_(media_log),
+        video_mode_switcher_(video_mode_switcher),
         video_resolution_policy_(video_resolution_policy),
         media_resource_tracker_(media_resource_tracker) {}
   ~CastRendererFactory() final {}
@@ -75,12 +77,14 @@
     return base::MakeUnique<CastRenderer>(
         create_backend_cb_, media_task_runner,
         audio_renderer_sink->GetOutputDeviceInfo().device_id(),
-        video_resolution_policy_, media_resource_tracker_);
+        video_mode_switcher_, video_resolution_policy_,
+        media_resource_tracker_);
   }
 
  private:
   const CreateMediaPipelineBackendCB create_backend_cb_;
   scoped_refptr<::media::MediaLog> media_log_;
+  VideoModeSwitcher* video_mode_switcher_;
   VideoResolutionPolicy* video_resolution_policy_;
   MediaResourceTracker* media_resource_tracker_;
   DISALLOW_COPY_AND_ASSIGN(CastRendererFactory);
@@ -90,11 +94,13 @@
 CastMojoMediaClient::CastMojoMediaClient(
     const CreateMediaPipelineBackendCB& create_backend_cb,
     const CreateCdmFactoryCB& create_cdm_factory_cb,
+    VideoModeSwitcher* video_mode_switcher,
     VideoResolutionPolicy* video_resolution_policy,
     MediaResourceTracker* media_resource_tracker)
     : connector_(nullptr),
       create_backend_cb_(create_backend_cb),
       create_cdm_factory_cb_(create_cdm_factory_cb),
+      video_mode_switcher_(video_mode_switcher),
       video_resolution_policy_(video_resolution_policy),
       media_resource_tracker_(media_resource_tracker) {}
 
@@ -115,9 +121,9 @@
 std::unique_ptr<::media::RendererFactory>
 CastMojoMediaClient::CreateRendererFactory(
     const scoped_refptr<::media::MediaLog>& media_log) {
-  return base::MakeUnique<CastRendererFactory>(create_backend_cb_, media_log,
-                                               video_resolution_policy_,
-                                               media_resource_tracker_);
+  return base::MakeUnique<CastRendererFactory>(
+      create_backend_cb_, media_log, video_mode_switcher_,
+      video_resolution_policy_, media_resource_tracker_);
 }
 
 std::unique_ptr<::media::CdmFactory> CastMojoMediaClient::CreateCdmFactory(
diff --git a/chromecast/media/service/cast_mojo_media_client.h b/chromecast/media/service/cast_mojo_media_client.h
index 46d2693b..fc856ad 100644
--- a/chromecast/media/service/cast_mojo_media_client.h
+++ b/chromecast/media/service/cast_mojo_media_client.h
@@ -12,6 +12,7 @@
 namespace media {
 
 class MediaResourceTracker;
+class VideoModeSwitcher;
 class VideoResolutionPolicy;
 
 class CastMojoMediaClient : public ::media::MojoMediaClient {
@@ -21,6 +22,7 @@
 
   CastMojoMediaClient(const CreateMediaPipelineBackendCB& create_backend_cb,
                       const CreateCdmFactoryCB& create_cdm_factory_cb,
+                      VideoModeSwitcher* video_mode_switcher,
                       VideoResolutionPolicy* video_resolution_policy,
                       MediaResourceTracker* media_resource_tracker);
   ~CastMojoMediaClient() override;
@@ -38,6 +40,7 @@
   service_manager::Connector* connector_;
   const CreateMediaPipelineBackendCB create_backend_cb_;
   const CreateCdmFactoryCB create_cdm_factory_cb_;
+  VideoModeSwitcher* video_mode_switcher_;
   VideoResolutionPolicy* video_resolution_policy_;
   MediaResourceTracker* media_resource_tracker_;
 
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc
index 42964ba..5c30c5eb 100644
--- a/chromecast/media/service/cast_renderer.cc
+++ b/chromecast/media/service/cast_renderer.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/single_thread_task_runner.h"
 #include "chromecast/base/task_runner_impl.h"
+#include "chromecast/media/base/video_mode_switcher.h"
 #include "chromecast/media/base/video_resolution_policy.h"
 #include "chromecast/media/cdm/cast_cdm_context.h"
 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
@@ -29,17 +30,30 @@
 // Maximum difference between audio frame PTS and video frame PTS
 // for frames read from the DemuxerStream.
 const base::TimeDelta kMaxDeltaFetcher(base::TimeDelta::FromMilliseconds(2000));
+
+void VideoModeSwitchCompletionCb(const ::media::PipelineStatusCB& init_cb,
+                                 bool success) {
+  if (!success) {
+    LOG(ERROR) << "Video mode switch failed.";
+    init_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
+    return;
+  }
+  VLOG(1) << "Video mode switched successfully.";
+  init_cb.Run(::media::PIPELINE_OK);
+}
 }  // namespace
 
 CastRenderer::CastRenderer(
     const CreateMediaPipelineBackendCB& create_backend_cb,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     const std::string& audio_device_id,
+    VideoModeSwitcher* video_mode_switcher,
     VideoResolutionPolicy* video_resolution_policy,
     MediaResourceTracker* media_resource_tracker)
     : create_backend_cb_(create_backend_cb),
       task_runner_(task_runner),
       audio_device_id_(audio_device_id),
+      video_mode_switcher_(video_mode_switcher),
       video_resolution_policy_(video_resolution_policy),
       media_resource_tracker_(media_resource_tracker),
       client_(nullptr),
@@ -154,9 +168,29 @@
   }
 
   client_ = client;
-  init_cb.Run(::media::PIPELINE_OK);
 
-  if (video_stream) {
+  if (video_stream && video_mode_switcher_) {
+    std::vector<::media::VideoDecoderConfig> video_configs;
+    video_configs.push_back(video_stream->video_decoder_config());
+    auto mode_switch_completion_cb =
+        base::Bind(&CastRenderer::OnVideoInitializationFinished,
+                   weak_factory_.GetWeakPtr(), init_cb);
+    video_mode_switcher_->SwitchMode(
+        video_configs,
+        base::Bind(&VideoModeSwitchCompletionCb, mode_switch_completion_cb));
+  } else if (video_stream) {
+    // No mode switch needed.
+    OnVideoInitializationFinished(init_cb, ::media::PIPELINE_OK);
+  } else {
+    init_cb.Run(::media::PIPELINE_OK);
+  }
+}
+
+void CastRenderer::OnVideoInitializationFinished(
+    const ::media::PipelineStatusCB& init_cb,
+    ::media::PipelineStatus status) {
+  init_cb.Run(status);
+  if (status == ::media::PIPELINE_OK) {
     // Force compositor to treat video as opaque (needed for overlay codepath).
     OnVideoOpacityChange(true);
   }
@@ -240,7 +274,11 @@
 
 void CastRenderer::OnBufferingStateChange(::media::BufferingState state) {
   DCHECK(task_runner_->BelongsToCurrentThread());
-  client_->OnBufferingStateChange(state);
+  // TODO(alokp): WebMediaPlayerImpl currently only handles HAVE_ENOUGH.
+  // See WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
+  // http://crbug.com/144683.
+  if (state == ::media::BUFFERING_HAVE_ENOUGH)
+    client_->OnBufferingStateChange(state);
 }
 
 void CastRenderer::OnWaitingForDecryptionKey() {
diff --git a/chromecast/media/service/cast_renderer.h b/chromecast/media/service/cast_renderer.h
index 61b722d0..22cdf85 100644
--- a/chromecast/media/service/cast_renderer.h
+++ b/chromecast/media/service/cast_renderer.h
@@ -23,6 +23,7 @@
 class BalancedMediaTaskRunnerFactory;
 class CastCdmContext;
 class MediaPipelineImpl;
+class VideoModeSwitcher;
 
 class CastRenderer : public ::media::Renderer,
                      public VideoResolutionPolicy::Observer {
@@ -30,6 +31,7 @@
   CastRenderer(const CreateMediaPipelineBackendCB& create_backend_cb,
                const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
                const std::string& audio_device_id,
+               VideoModeSwitcher* video_mode_switcher,
                VideoResolutionPolicy* video_resolution_policy,
                MediaResourceTracker* media_resource_tracker);
   ~CastRenderer() final;
@@ -60,9 +62,13 @@
   void OnVideoOpacityChange(bool opaque);
   void CheckVideoResolutionPolicy();
 
+  void OnVideoInitializationFinished(const ::media::PipelineStatusCB& init_cb,
+                                     ::media::PipelineStatus status);
+
   const CreateMediaPipelineBackendCB create_backend_cb_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   std::string audio_device_id_;
+  VideoModeSwitcher* video_mode_switcher_;
   VideoResolutionPolicy* video_resolution_policy_;
   MediaResourceTracker* media_resource_tracker_;
   // Must outlive |pipeline_| to properly count resource usage.
diff --git a/chromeos/PRESUBMIT.py b/chromeos/PRESUBMIT.py
deleted file mode 100644
index 64582bf0..0000000
--- a/chromeos/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for chromeos.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/chromeos/printing/printer_configuration.h b/chromeos/printing/printer_configuration.h
index d0343842..27f047bdb 100644
--- a/chromeos/printing/printer_configuration.h
+++ b/chromeos/printing/printer_configuration.h
@@ -50,7 +50,7 @@
   explicit Printer(const std::string& id);
 
   // Copy constructor and assignment.
-  explicit Printer(const Printer& printer);
+  Printer(const Printer& printer);
   Printer& operator=(const Printer& printer);
 
   ~Printer();
diff --git a/components/arc/kiosk/arc_kiosk_bridge.cc b/components/arc/kiosk/arc_kiosk_bridge.cc
index a928f67c..7837d98a 100644
--- a/components/arc/kiosk/arc_kiosk_bridge.cc
+++ b/components/arc/kiosk/arc_kiosk_bridge.cc
@@ -27,12 +27,17 @@
 }
 
 void ArcKioskBridge::OnMaintenanceSessionCreated(int32_t session_id) {
+  session_id_ = session_id;
   delegate_->OnMaintenanceSessionCreated();
   // TODO(poromov@) Show appropriate splash screen.
 }
 
 void ArcKioskBridge::OnMaintenanceSessionFinished(int32_t session_id,
                                                   bool success) {
+  // Filter only callbacks for the started kiosk session.
+  if (session_id != session_id_)
+    return;
+  session_id_ = -1;
   delegate_->OnMaintenanceSessionFinished();
 }
 
diff --git a/components/arc/kiosk/arc_kiosk_bridge.h b/components/arc/kiosk/arc_kiosk_bridge.h
index fa04fe9b..2c46e05 100644
--- a/components/arc/kiosk/arc_kiosk_bridge.h
+++ b/components/arc/kiosk/arc_kiosk_bridge.h
@@ -44,6 +44,9 @@
   mojo::Binding<mojom::KioskHost> binding_;
   Delegate* const delegate_;
 
+  // Tracks current maintenance session id.
+  int32_t session_id_ = -1;
+
   DISALLOW_COPY_AND_ASSIGN(ArcKioskBridge);
 };
 
diff --git a/components/autofill/content/common/autofill_types.mojom b/components/autofill/content/common/autofill_types.mojom
index 9142c617..0ff43e1 100644
--- a/components/autofill/content/common/autofill_types.mojom
+++ b/components/autofill/content/common/autofill_types.mojom
@@ -167,6 +167,7 @@
   string new_password_value;
   bool new_password_value_is_default;
   bool new_password_marked_by_site;
+  string confirmation_password_element;
   bool preferred;
   mojo.common.mojom.Time date_created;
   mojo.common.mojom.Time date_synced;
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc
index dce12aa..1b3d8ab6 100644
--- a/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -506,6 +506,11 @@
 
   out->new_password_value_is_default = data.new_password_value_is_default();
   out->new_password_marked_by_site = data.new_password_marked_by_site();
+
+  if (!data.ReadConfirmationPasswordElement(
+          &out->confirmation_password_element))
+    return false;
+
   out->preferred = data.preferred();
 
   if (!data.ReadDateCreated(&out->date_created) ||
diff --git a/components/autofill/content/common/autofill_types_struct_traits.h b/components/autofill/content/common/autofill_types_struct_traits.h
index ba126b37..f5156bb8 100644
--- a/components/autofill/content/common/autofill_types_struct_traits.h
+++ b/components/autofill/content/common/autofill_types_struct_traits.h
@@ -454,6 +454,11 @@
     return r.new_password_marked_by_site;
   }
 
+  static const base::string16& confirmation_password_element(
+      const autofill::PasswordForm& r) {
+    return r.confirmation_password_element;
+  }
+
   static bool preferred(const autofill::PasswordForm& r) { return r.preferred; }
 
   static const base::Time& date_created(const autofill::PasswordForm& r) {
diff --git a/components/autofill/content/common/autofill_types_struct_traits_unittest.cc b/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
index 1ac7a74..f4ab58b 100644
--- a/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
+++ b/components/autofill/content/common/autofill_types_struct_traits_unittest.cc
@@ -92,6 +92,7 @@
   form->new_password_value = base::ASCIIToUTF16("new_password_value");
   form->new_password_value_is_default = false;
   form->new_password_marked_by_site = false;
+  form->new_password_element = base::ASCIIToUTF16("confirmation_password");
   form->preferred = false;
   form->date_created = base::Time::Now();
   form->date_synced = base::Time::Now();
diff --git a/components/autofill/core/browser/payments/payments_service_url.cc b/components/autofill/core/browser/payments/payments_service_url.cc
index 2ea46233d..f545e9a 100644
--- a/components/autofill/core/browser/payments/payments_service_url.cc
+++ b/components/autofill/core/browser/payments/payments_service_url.cc
@@ -21,10 +21,10 @@
 namespace autofill {
 namespace {
 
-const char kProdPaymentsServiceUrl[] = "https://wallet.google.com/";
+const char kProdPaymentsServiceUrl[] = "https://payments.google.com/";
 
 const char kSandboxPaymentsSecureServiceUrl[] =
-    "https://wallet-web.sandbox.google.com/";
+    "https://payments.sandbox.google.com/";
 
 }  // namespace
 
@@ -46,14 +46,13 @@
 
 GURL GetManageInstrumentsUrl(size_t user_index) {
   std::string path =
-      base::StringPrintf("manage/w/%" PRIuS "/paymentMethods", user_index);
+      base::StringPrintf("u/%" PRIuS "#paymentMethods", user_index);
   return GetBaseSecureUrl().Resolve(path);
 }
 
 GURL GetManageAddressesUrl(size_t user_index) {
-  std::string path =
-      base::StringPrintf("manage/w/%" PRIuS "/settings/addresses", user_index);
-  return GetBaseSecureUrl().Resolve(path);
+  // Billing addresses are now managed as a part of the payment instrument.
+  return GetManageInstrumentsUrl(user_index);
 }
 
 }  // namespace payments
diff --git a/components/autofill/core/browser/payments/payments_service_url_unittest.cc b/components/autofill/core/browser/payments/payments_service_url_unittest.cc
index 09dc91b..8cdc500 100644
--- a/components/autofill/core/browser/payments/payments_service_url_unittest.cc
+++ b/components/autofill/core/browser/payments/payments_service_url_unittest.cc
@@ -15,21 +15,21 @@
   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kWalletServiceUseSandbox, "1");
 
-  EXPECT_EQ("https://wallet-web.sandbox.google.com/manage/w/1/paymentMethods",
-            GetManageInstrumentsUrl(1).spec());
-  EXPECT_EQ("https://wallet-web.sandbox.google.com/manage/w/1/settings/"
-            "addresses",
-            GetManageAddressesUrl(1).spec());
+  const char kExpectedSandboxURL[] =
+      "https://payments.sandbox.google.com/u/1#paymentMethods";
+
+  EXPECT_EQ(kExpectedSandboxURL, GetManageInstrumentsUrl(1).spec());
+  EXPECT_EQ(kExpectedSandboxURL, GetManageAddressesUrl(1).spec());
 }
 
 TEST(PaymentsServiceSandboxUrl, CheckProdUrls) {
   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
       switches::kWalletServiceUseSandbox, "0");
 
-  EXPECT_EQ("https://wallet.google.com/manage/w/1/paymentMethods",
-            GetManageInstrumentsUrl(1).spec());
-  EXPECT_EQ("https://wallet.google.com/manage/w/1/settings/addresses",
-            GetManageAddressesUrl(1).spec());
+  const char kExpectedURL[] = "https://payments.google.com/u/1#paymentMethods";
+
+  EXPECT_EQ(kExpectedURL, GetManageInstrumentsUrl(1).spec());
+  EXPECT_EQ(kExpectedURL, GetManageAddressesUrl(1).spec());
 }
 
 }  // namespace payments
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
index 326ddc4..f230512 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -33,6 +33,10 @@
 
 namespace {
 
+// The length of the GUIDs used for local autofill data. It is different than
+// the length used for server autofill data.
+const int kLocalGuidSize = 36;
+
 void* UserDataKey() {
   // Use the address of a static so that COMDAT folding won't ever fold
   // with something else.
@@ -201,6 +205,20 @@
                       is_local_modified);
 }
 
+// Whether the |current_billing_address_id| is considered outdated compared to
+// the |proposed_billing_address_id|.
+bool IsBillingAddressOutdated(const std::string& current_billing_address_id,
+                              const std::string& proposed_billing_address_id) {
+  DCHECK(current_billing_address_id != proposed_billing_address_id);
+
+  // If the current billing address is empty, or if the current one refers to a
+  // server address and the proposed one refers to a local address, the current
+  // billing address is considered outdated.
+  return current_billing_address_id.empty() ||
+         (current_billing_address_id.size() != kLocalGuidSize &&
+          proposed_billing_address_id.size() == kLocalGuidSize);
+}
+
 // Merges the metadata of the remote and local versions of the credit card.
 void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
                    CreditCard* local_card,
@@ -213,18 +231,21 @@
                      &remote_billing_address_id);
 
   if (local_card->billing_address_id() != remote_billing_address_id) {
-    // If one of the values is empty, update it with the non empty value.
-    if (local_card->billing_address_id().empty()) {
+    if (IsBillingAddressOutdated(local_card->billing_address_id(),
+                                 remote_billing_address_id)) {
       local_card->set_billing_address_id(remote_billing_address_id);
       *is_local_modified = true;
-    } else if (remote_billing_address_id.empty()) {
+    } else if (IsBillingAddressOutdated(remote_billing_address_id,
+                                        local_card->billing_address_id())) {
       *is_remote_outdated = true;
     } else {
-      // The cards have a different non-empty billing address id. Keep the
-      // billing address id of the most recently used card.
+      // The cards have a different non-empty billing address id and both refer
+      // to the same type of address. Keep the billing address id of the most
+      // recently used card. If both have the same timestamp, the remote version
+      // should be kept in order to stabilize the values.
       base::Time remote_use_date =
           base::Time::FromInternalValue(remote_metadata.use_date());
-      if (local_card->use_date() < remote_use_date) {
+      if (local_card->use_date() <= remote_use_date) {
         local_card->set_billing_address_id(remote_billing_address_id);
         *is_local_modified = true;
       } else {
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
index 89439d7..462f7bb6 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
@@ -59,6 +59,12 @@
 const char kCard1SyncTag[] = "card-Y2FyZDHvv74=";
 const char kCard2SyncTag[] = "card-Y2FyZDLvv74=";
 
+// Local profile GUID in UTF8 and non-UTF8.
+const char kLocalAddr1[] = "e171e3ed-858a-4dd5-9bf3-8517f14ba5fc";
+const char kLocalAddr2[] = "fa232b9a-f248-4e5a-8d76-d46f821c0c5f";
+const char kLocalAddr1Utf8[] =
+    "ZTE3MWUzZWQtODU4YS00ZGQ1LTliZjMtODUxN2YxNGJhNWZj";
+
 // Map values are owned by the caller to GetLocalData.
 ACTION_P2(GetCopiesOf, profiles, cards) {
   for (const auto& profile : *profiles) {
@@ -1025,9 +1031,10 @@
 }
 
 // Verify that if both local and server have a different non empty billing
-// address id, the one with the most recent (bigger) use date is kept.
+// address id refering to a Wallet address, the one with the most recent
+// (bigger) use date is kept.
 TEST_F(AutofillWalletMetadataSyncableServiceTest,
-       SaveHigherValues_DifferentBillingAddressId_LocalMostRecent) {
+       DifferentServerBillingAddressId_LocalMostRecent) {
   local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
   remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
 
@@ -1044,9 +1051,10 @@
 }
 
 // Verify that if both local and server have a different non empty billing
-// address id, the one with the most recent (bigger) use date is kept.
+// address id refering to a Wallet address, the one with the most recent
+// (bigger) use date is kept.
 TEST_F(AutofillWalletMetadataSyncableServiceTest,
-       SaveHigherValues_DifferentBillingAddressId_RemoteMostRecent) {
+       DifferentServerBillingAddressId_RemoteMostRecent) {
   local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
   remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr2));
 
@@ -1059,5 +1067,155 @@
   MergeMetadata(&local_, &remote_);
 }
 
+// Verify that if both local and server have a different non empty billing
+// address id refering to a local profile, the one with the most recent (bigger)
+// use date is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       DifferentLocalBillingAddressId_LocalMostRecent) {
+  local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kLocalAddr1));
+  remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr2));
+
+  // The value from the local should be kept because it has a more recent use
+  // date.
+  EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
+  EXPECT_CALL(local_, SendChangesToSyncServer(
+                          UnorderedElementsAre(SyncCardChangeAndDataMatch(
+                              syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+                              sync_pb::WalletMetadataSpecifics::CARD,
+                              kCard1Utf8, 3, 40, kLocalAddr1Utf8))));
+
+  MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id refering to a local profile, the one with the most recent (bigger)
+// use date is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       DifferentLocalBillingAddressId_RemoteMostRecent) {
+  local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+  remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kLocalAddr2));
+
+  // The value from the remote should be kept because it has a more recent use
+  // date.
+  EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+                          kCard1, 3, 40, kLocalAddr2)));
+  EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+  MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       DifferentBillingAddressId_KeepLocalId_Local) {
+  local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+  remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
+
+  // The billing address from the local version of the card should be kept since
+  // it refers to a local autofill profile.
+  EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
+  EXPECT_CALL(local_, SendChangesToSyncServer(
+                          UnorderedElementsAre(SyncCardChangeAndDataMatch(
+                              syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+                              sync_pb::WalletMetadataSpecifics::CARD,
+                              kCard1Utf8, 3, 4, kLocalAddr1Utf8))));
+
+  MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept, even id the
+// other was used more recently.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       DifferentBillingAddressId_KeepLocalId_Remote) {
+  local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
+  remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+
+  // The billing address from the remote version of the card should be kept
+  // since it refers to a local autofill profile.
+  EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+                          kCard1, 3, 4, kLocalAddr1)));
+  EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+  MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept, even id the
+// other was used more recently. Also makes sure that for the rest of the fields
+// the highest values are kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       SaveHigherValues_DifferentBillingAddressId_KeepLocalId_Local) {
+  local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+  remote_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr2));
+
+  // The billing address from the local version of the card should be kept since
+  // it refers to a local autofill profile. The highest use stats should
+  // be kept.
+  EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+                          kCard1, 30, 40, kLocalAddr1)));
+  EXPECT_CALL(local_, SendChangesToSyncServer(
+                          UnorderedElementsAre(SyncCardChangeAndDataMatch(
+                              syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+                              sync_pb::WalletMetadataSpecifics::CARD,
+                              kCard1Utf8, 30, 40, kLocalAddr1Utf8))));
+
+  MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept. Also makes
+// sure that for the rest of the fields the highest values are kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       SaveHigherValues_DifferentBillingAddressId_KeepLocalId_Remote) {
+  local_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr2));
+  remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+
+  // The billing address from the remote version of the card should be kept
+  // since it refers to a local autofill profile. The highest use stats should
+  // be kept.
+  EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+                          kCard1, 30, 40, kLocalAddr1)));
+  EXPECT_CALL(local_, SendChangesToSyncServer(
+                          UnorderedElementsAre(SyncCardChangeAndDataMatch(
+                              syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+                              sync_pb::WalletMetadataSpecifics::CARD,
+                              kCard1Utf8, 30, 40, kLocalAddr1Utf8))));
+
+  MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id refering to a Wallet address with the same timestamp, the remote
+// one is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       DifferentServerBillingAddressId_BothSameTimestamp) {
+  local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+  remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
+
+  // The value from the remote should be kept to promote a stable set of values.
+  EXPECT_CALL(local_, UpdateCardStats(
+                          AutofillCardMetadataMatches(kCard1, 3, 4, kAddr2)));
+  EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+  MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id refering to a local profile with the same timestamp, the remote
+// one is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+       DifferentLocalBillingAddressId_BothSameTimestamp) {
+  local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+  remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr2));
+
+  // The value from the remote should be kept to promote a stable set of values.
+  EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+                          kCard1, 3, 4, kLocalAddr2)));
+  EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+  MergeMetadata(&local_, &remote_);
+}
+
 }  // namespace
 }  // namespace autofill
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp
index e2a1b8e..6aedacd 100644
--- a/components/autofill_strings.grdp
+++ b/components/autofill_strings.grdp
@@ -14,9 +14,6 @@
   <message name="IDS_AUTOFILL_CLEAR_LOCAL_COPY_BUTTON" desc="The label of the button that clears the local copy of a Wallet Credit Card." formatter_data="android_java">
     Clear copy
   </message>
-  <message name="IDS_AUTOFILL_WARNING_FORM_DISABLED" desc="Warning text to show when autofill is disabled by the website for a given form.">
-    This webpage has disabled automatic filling for this form.
-  </message>
   <message name="IDS_AUTOFILL_WARNING_PAYMENT_DISABLED" desc="Warning text to show when credit card autofill is disabled because the website is not using a secure connection. This warning text is shown below a separate warning indicating that the form is not secure, so this message indicates just that payment autofilling has been disabled (not why).">
     Payment autofilling disabled
   </message>
@@ -84,9 +81,6 @@
   <message name="IDS_AUTOFILL_CC_GENERIC" desc="Generic credit card name.">
     Card
   </message>
-  <message name="IDS_AUTOFILL_ADDRESS_LINE_SEPARATOR" desc="The separator character used to join multi-line addresses.">
-    , '''
-  </message>
   <message name="IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR" desc="The separator character used in the summary of an address." formatter_data="android_java">
     , '''
   </message>
@@ -130,9 +124,6 @@
   <message name="IDS_AUTOFILL_FIELD_LABEL_POSTAL_CODE" desc="The label of the Postal code entry.">
     Postal code
   </message>
-  <message name="IDS_AUTOFILL_FIELD_LABEL_COUNTRY" desc="The label of the Country entry.">
-    Country
-  </message>
 
   <message translateable="false" name="IDS_AUTOFILL_SHOW_PREDICTIONS_TITLE" desc="The title for form elements when annotated with Autofill predictions.">
     overall type: <ph name="OVERALL_TYPE">$1<ex>NAME_FIRST</ex></ph>
@@ -144,11 +135,6 @@
     form signature: <ph name="FORM_SIGNATURE">$7<ex>1234567812345678</ex></ph>
   </message>
 
-  <!-- Autofill dialog: legal documents -->
-  <message name="IDS_AUTOFILL_DIALOG_PRIVACY_POLICY_LINK" desc="The text of an extra link that is appended to the end of whatever other legal documents need to be accepted or updated.">
-    Privacy Policy
-  </message>
-
   <if expr="_google_chrome">
     <message name="IDS_AUTOFILL_OPTIONS_POPUP" desc="The text displayed in the Autofill popup to direct the user to the Autofill settings UI.">
      Chrome Autofill settings...
@@ -175,20 +161,6 @@
     settings
   </message>
 
-  <message name="IDS_AUTOFILL_CREDIT_CARD_NOT_SUPPORTED_BY_WALLET" desc="Message displayed to user when user entered a credit card number that is not supported by Google Payments.">
-    This type of card is not supported by Google Payments. Please select a different card.
-  </message>
-  <message name="IDS_AUTOFILL_CREDIT_CARD_NOT_SUPPORTED_BY_WALLET_FOR_MERCHANT" desc="Message displayed to user when user entered a credit card number that is not supported by Google Payments for the particular merchant site the user is on.">
-    This type of card is not supported by Google Payments for this merchant. Please select a different card.
-  </message>
-
-  <!-- Autofill on OSX -->
-  <if expr="is_macosx">
-    <message name="IDS_AUTOFILL_ACCESS_MAC_CONTACTS" desc="When the user selects this Autofill entry, the browser prompts the user for access to the user's OSX contacts.">
-      Enable Autofill using Contacts…
-    </message>
-  </if>
-
   <message name="IDS_AUTOFILL_SCAN_CREDIT_CARD" desc="An item in the autofill popup that triggers a new credit card to be scanned using the camera on the device." formatter_data="android_java">
     Scan new card
   </message>
diff --git a/components/browser_sync/PRESUBMIT.py b/components/browser_sync/PRESUBMIT.py
index c9212e9..d072c723 100644
--- a/components/browser_sync/PRESUBMIT.py
+++ b/components/browser_sync/PRESUBMIT.py
@@ -26,7 +26,6 @@
 def CheckChanges(input_api, output_api):
   results = []
   results += CheckChangeLintsClean(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
 
 def CheckChangeOnUpload(input_api, output_api):
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index ba1f82b..2d93319 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -283,6 +283,14 @@
             ui_thread_));
   }
 
+#if defined(OS_CHROMEOS)
+  if (!disabled_types.Has(syncer::PRINTERS)) {
+    sync_service->RegisterDataTypeController(
+        base::MakeUnique<ModelTypeController>(syncer::PRINTERS, sync_client_,
+                                              ui_thread_));
+  }
+#endif
+
   // Reading list sync is enabled by default only on iOS. Register unless
   // Reading List or Reading List Sync is explicitly disabled.
   if (!disabled_types.Has(syncer::READING_LIST) &&
diff --git a/components/browser_watcher/postmortem_report_collector_unittest.cc b/components/browser_watcher/postmortem_report_collector_unittest.cc
index 6f79bbb..c05283e 100644
--- a/components/browser_watcher/postmortem_report_collector_unittest.cc
+++ b/components/browser_watcher/postmortem_report_collector_unittest.cc
@@ -567,7 +567,7 @@
   // Record some global user data.
   GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
                                         "", 3);
-  ActivityUserData& global_data = GlobalActivityTracker::Get()->user_data();
+  ActivityUserData& global_data = GlobalActivityTracker::Get()->global_data();
   global_data.Set("raw", "foo", 3);
   global_data.SetString("string", "bar");
   global_data.SetChar("char", '9');
diff --git a/components/browser_watcher/stability_debugging.cc b/components/browser_watcher/stability_debugging.cc
index 4341ffe..59dc4fb 100644
--- a/components/browser_watcher/stability_debugging.cc
+++ b/components/browser_watcher/stability_debugging.cc
@@ -97,7 +97,7 @@
   if (!global_tracker)
     return;  // Activity tracking isn't enabled.
 
-  global_tracker->user_data().SetInt(name, value);
+  global_tracker->global_data().SetInt(name, value);
 }
 
 }  // namespace browser_watcher
diff --git a/components/crash/core/common/crash_keys.cc b/components/crash/core/common/crash_keys.cc
index 6c2d382..9e3346bfd 100644
--- a/components/crash/core/common/crash_keys.cc
+++ b/components/crash/core/common/crash_keys.cc
@@ -93,12 +93,12 @@
       base::StringPrintf("%" PRIuS, variations.size()));
 
   std::string variations_string;
-  variations_string.reserve(kLargeSize);
+  variations_string.reserve(kHugeSize);
 
   for (size_t i = 0; i < variations.size(); ++i) {
     const std::string& variation = variations[i];
     // Do not truncate an individual experiment.
-    if (variations_string.size() + variation.size() >= kLargeSize)
+    if (variations_string.size() + variation.size() >= kHugeSize)
       break;
     variations_string += variation;
     variations_string += ",";
diff --git a/components/crash/core/common/crash_keys.h b/components/crash/core/common/crash_keys.h
index fdd1ee53..4596fce 100644
--- a/components/crash/core/common/crash_keys.h
+++ b/components/crash/core/common/crash_keys.h
@@ -65,6 +65,10 @@
 // used sparingly.
 const size_t kLargeSize = kSmallSize * 16;
 
+// A very large crash key, which will be chunked on all platforms. This should
+// be used very sparingly.
+const size_t kHugeSize = kLargeSize * 2;
+
 // Crash Key Name Constants ////////////////////////////////////////////////////
 
 // The GUID used to identify this client to the crash system.
diff --git a/components/crash/core/common/crash_keys_unittest.cc b/components/crash/core/common/crash_keys_unittest.cc
index fb9d519..6c2bda01 100644
--- a/components/crash/core/common/crash_keys_unittest.cc
+++ b/components/crash/core/common/crash_keys_unittest.cc
@@ -23,12 +23,19 @@
     self_ = this;
     base::debug::SetCrashKeyReportingFunctions(
         &SetCrashKeyValue, &ClearCrashKey);
+  }
 
+  bool InitSwitchesCrashKeys() {
     std::vector<base::debug::CrashKey> keys;
     crash_keys::GetCrashKeysForCommandLineSwitches(&keys);
-    base::debug::InitCrashKeys(keys.data(), keys.size(),
-                               crash_keys::kChunkMaxLength);
-    ASSERT_FALSE(keys.empty());
+    return InitCrashKeys(keys);
+  }
+
+  bool InitVariationsCrashKeys() {
+    std::vector<base::debug::CrashKey> keys = {
+        {crash_keys::kNumVariations, crash_keys::kSmallSize},
+        {crash_keys::kVariations, crash_keys::kHugeSize}};
+    return InitCrashKeys(keys);
   }
 
   void TearDown() override {
@@ -48,6 +55,12 @@
   }
 
  private:
+  bool InitCrashKeys(const std::vector<base::debug::CrashKey>& keys) {
+    base::debug::InitCrashKeys(keys.data(), keys.size(),
+                               crash_keys::kChunkMaxLength);
+    return !keys.empty();
+  }
+
   static void SetCrashKeyValue(const base::StringPiece& key,
                                const base::StringPiece& value) {
     self_->keys_[key.as_string()] = value.as_string();
@@ -65,6 +78,8 @@
 CrashKeysTest* CrashKeysTest::self_ = NULL;
 
 TEST_F(CrashKeysTest, Switches) {
+  ASSERT_TRUE(InitSwitchesCrashKeys());
+
   // Set three switches.
   {
     base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
@@ -118,6 +133,8 @@
 }  // namespace
 
 TEST_F(CrashKeysTest, FilterFlags) {
+  ASSERT_TRUE(InitSwitchesCrashKeys());
+
   using crash_keys::kSwitchesMaxCount;
 
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
@@ -140,3 +157,35 @@
         switch_name;
   }
 }
+
+TEST_F(CrashKeysTest, VariationsCapacity) {
+  ASSERT_TRUE(InitVariationsCrashKeys());
+
+  // Variation encoding: two 32bit numbers encorded as hex with a '-' separator.
+  const char kSampleVariation[] = "12345678-12345678";
+  const size_t kVariationLen = std::strlen(kSampleVariation);
+  const size_t kSeparatedVariationLen = kVariationLen + 1U;
+  ASSERT_EQ(17U, kVariationLen);
+
+  // The expected capacity factors in a separator (',').
+  const size_t kExpectedCapacity = 112U;
+  ASSERT_EQ(kExpectedCapacity,
+            crash_keys::kHugeSize / (kSeparatedVariationLen));
+
+  // Create some variations and set the crash keys.
+  std::vector<std::string> variations;
+  for (size_t i = 0; i < kExpectedCapacity + 2; ++i)
+    variations.push_back(kSampleVariation);
+  crash_keys::SetVariationsList(variations);
+
+  // Validate crash keys.
+  ASSERT_TRUE(HasCrashKey(crash_keys::kNumVariations));
+  EXPECT_EQ("114", GetKeyValue(crash_keys::kNumVariations));
+
+  const size_t kExpectedChunks = (kSeparatedVariationLen * kExpectedCapacity) /
+                                 crash_keys::kChunkMaxLength;
+  for (size_t i = 0; i < kExpectedChunks; ++i) {
+    ASSERT_TRUE(HasCrashKey(
+        base::StringPrintf("%s-%" PRIuS, crash_keys::kVariations, i + 1)));
+  }
+}
diff --git a/components/cronet/PRESUBMIT.py b/components/cronet/PRESUBMIT.py
index e722191e..59aaafa4 100644
--- a/components/cronet/PRESUBMIT.py
+++ b/components/cronet/PRESUBMIT.py
@@ -79,8 +79,6 @@
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results.extend(_PyLintChecks(input_api, output_api))
-  results.extend(
-      input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
   results.extend(_PackageChecks(input_api, output_api))
   results.extend(_RunUnittests(input_api, output_api))
   return results
diff --git a/components/cronet/ios/Cronet.mm b/components/cronet/ios/Cronet.mm
index 65d5e87c..135398a 100644
--- a/components/cronet/ios/Cronet.mm
+++ b/components/cronet/ios/Cronet.mm
@@ -76,6 +76,8 @@
   // net::HTTPProtocolHandlerDelegate implementation:
   bool CanHandleRequest(NSURLRequest* request) override {
     base::AutoLock auto_lock(lock_);
+    if (!IsRequestSupported(request))
+      return false;
     if (filter_) {
       RequestFilterBlock block = filter_.get();
       return block(request);
diff --git a/components/cronet/ios/test/cronet_http_test.mm b/components/cronet/ios/test/cronet_http_test.mm
index e1b1e72..011132e 100644
--- a/components/cronet/ios/test/cronet_http_test.mm
+++ b/components/cronet/ios/test/cronet_http_test.mm
@@ -322,6 +322,39 @@
   EXPECT_TRUE([[delegate_ responseBody] containsString:cookieValue]);
 }
 
+TEST_F(HttpTest, SystemCookieWithNullCreationTime) {
+  const char kCookieHeader[] = "Cookie";
+  NSString* cookieName = [NSString
+      stringWithFormat:@"SetSystemCookie-%@", [[NSUUID UUID] UUIDString]];
+  NSString* cookieValue = [[NSUUID UUID] UUIDString];
+  NSHTTPCookieStorage* systemCookieStorage =
+      [NSHTTPCookieStorage sharedHTTPCookieStorage];
+  NSURL* echoCookieUrl =
+      net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL(kCookieHeader)));
+  NSHTTPCookie* nullCreationTimeCookie = [NSHTTPCookie cookieWithProperties:@{
+    NSHTTPCookiePath : [echoCookieUrl path],
+    NSHTTPCookieName : cookieName,
+    NSHTTPCookieValue : cookieValue,
+    NSHTTPCookieDomain : [echoCookieUrl host],
+    @"Created" : [NSNumber numberWithDouble:0.0],
+  }];
+  [systemCookieStorage setCookie:nullCreationTimeCookie];
+  NSHTTPCookie* normalCookie = [NSHTTPCookie cookieWithProperties:@{
+    NSHTTPCookiePath : [echoCookieUrl path],
+    NSHTTPCookieName : [cookieName stringByAppendingString:@"-normal"],
+    NSHTTPCookieValue : cookieValue,
+    NSHTTPCookieDomain : [echoCookieUrl host],
+  }];
+  [systemCookieStorage setCookie:normalCookie];
+  StartDataTaskAndWaitForCompletion([session_ dataTaskWithURL:echoCookieUrl]);
+  [systemCookieStorage deleteCookie:nullCreationTimeCookie];
+  [systemCookieStorage deleteCookie:normalCookie];
+  EXPECT_EQ(nil, [delegate_ error]);
+  // Verify that cookie set in system store was sent to the serever.
+  EXPECT_TRUE([[delegate_ responseBody] containsString:cookieName]);
+  EXPECT_TRUE([[delegate_ responseBody] containsString:cookieValue]);
+}
+
 TEST_F(HttpTest, FilterOutRequest) {
   NSURL* url =
       net::NSURLWithGURL(GURL(TestServer::GetEchoHeaderURL("User-Agent")));
@@ -340,4 +373,29 @@
   EXPECT_TRUE([[delegate_ responseBody] containsString:@"CFNetwork"]);
 }
 
+TEST_F(HttpTest, FileSchemeNotSupported) {
+  NSString* fileData = @"Hello, World!";
+  NSString* documentsDirectory = [NSSearchPathForDirectoriesInDomains(
+      NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+  NSString* filePath = [documentsDirectory
+      stringByAppendingPathComponent:[[NSProcessInfo processInfo]
+                                         globallyUniqueString]];
+  [fileData writeToFile:filePath
+             atomically:YES
+               encoding:NSUTF8StringEncoding
+                  error:nil];
+
+  NSURL* url = [NSURL fileURLWithPath:filePath];
+  NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
+  [Cronet setRequestFilterBlock:^(NSURLRequest* request) {
+    [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
+    EXPECT_TRUE(false) << "Block should not be called for unsupported requests";
+    return YES;
+  }];
+  StartDataTaskAndWaitForCompletion(task);
+  [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
+  EXPECT_EQ(nil, [delegate_ error]);
+  EXPECT_TRUE([[delegate_ responseBody] containsString:fileData]);
+}
+
 }  // namespace cronet
diff --git a/components/data_reduction_proxy/PRESUBMIT.py b/components/data_reduction_proxy/PRESUBMIT.py
deleted file mode 100644
index b918678..0000000
--- a/components/data_reduction_proxy/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for the data_reduction_proxy component.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/data_usage/PRESUBMIT.py b/components/data_usage/PRESUBMIT.py
deleted file mode 100644
index 60e8fdf..0000000
--- a/components/data_usage/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for the data_usage component.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/display_compositor/gpu_compositor_frame_sink.cc b/components/display_compositor/gpu_compositor_frame_sink.cc
index e5d2781b5..9a6347f 100644
--- a/components/display_compositor/gpu_compositor_frame_sink.cc
+++ b/components/display_compositor/gpu_compositor_frame_sink.cc
@@ -12,7 +12,8 @@
     GpuCompositorFrameSinkDelegate* delegate,
     cc::SurfaceManager* surface_manager,
     const cc::FrameSinkId& frame_sink_id,
-    cc::Display* display,
+    std::unique_ptr<cc::Display> display,
+    std::unique_ptr<cc::BeginFrameSource> begin_frame_source,
     cc::mojom::MojoCompositorFrameSinkPrivateRequest
         compositor_frame_sink_private_request,
     cc::mojom::MojoCompositorFrameSinkClientPtr client)
@@ -20,9 +21,8 @@
       support_(this,
                surface_manager,
                frame_sink_id,
-               display,
-               true /* handles_frame_sink_id_invalidation */,
-               true /* needs_sync_points */),
+               std::move(display),
+               std::move(begin_frame_source)),
       surface_manager_(surface_manager),
       surface_tracker_(frame_sink_id),
       client_(std::move(client)),
diff --git a/components/display_compositor/gpu_compositor_frame_sink.h b/components/display_compositor/gpu_compositor_frame_sink.h
index df2a51c..2ccac29 100644
--- a/components/display_compositor/gpu_compositor_frame_sink.h
+++ b/components/display_compositor/gpu_compositor_frame_sink.h
@@ -35,7 +35,8 @@
       GpuCompositorFrameSinkDelegate* delegate,
       cc::SurfaceManager* surface_manager,
       const cc::FrameSinkId& frame_sink_id,
-      cc::Display* display,
+      std::unique_ptr<cc::Display> display,
+      std::unique_ptr<cc::BeginFrameSource> begin_frame_source,
       cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request,
       cc::mojom::MojoCompositorFrameSinkClientPtr client);
 
diff --git a/components/display_compositor/gpu_display_compositor_frame_sink.cc b/components/display_compositor/gpu_display_compositor_frame_sink.cc
index a69dbe43..892409a 100644
--- a/components/display_compositor/gpu_display_compositor_frame_sink.cc
+++ b/components/display_compositor/gpu_display_compositor_frame_sink.cc
@@ -20,40 +20,38 @@
     : GpuCompositorFrameSink(delegate,
                              surface_manager,
                              frame_sink_id,
-                             display.get(),
+                             std::move(display),
+                             std::move(begin_frame_source),
                              std::move(compositor_frame_sink_private_request),
                              std::move(client)),
       binding_(this, std::move(request)),
-      display_private_binding_(this, std::move(display_private_request)),
-      display_begin_frame_source_(std::move(begin_frame_source)),
-      display_(std::move(display)) {
+      display_private_binding_(this, std::move(display_private_request)) {
   binding_.set_connection_error_handler(
       base::Bind(&GpuDisplayCompositorFrameSink::OnClientConnectionLost,
                  base::Unretained(this)));
-  display_->SetVisible(true);
 }
 
 GpuDisplayCompositorFrameSink::~GpuDisplayCompositorFrameSink() = default;
 
 void GpuDisplayCompositorFrameSink::SetDisplayVisible(bool visible) {
   DCHECK(support_.display());
-  display_->SetVisible(visible);
+  support_.display()->SetVisible(visible);
 }
 
 void GpuDisplayCompositorFrameSink::ResizeDisplay(const gfx::Size& size) {
   DCHECK(support_.display());
-  display_->Resize(size);
+  support_.display()->Resize(size);
 }
 
 void GpuDisplayCompositorFrameSink::SetDisplayColorSpace(
     const gfx::ColorSpace& color_space) {
   DCHECK(support_.display());
-  display_->SetColorSpace(color_space);
+  support_.display()->SetColorSpace(color_space);
 }
 
 void GpuDisplayCompositorFrameSink::SetOutputIsSecure(bool secure) {
   DCHECK(support_.display());
-  display_->SetOutputIsSecure(secure);
+  support_.display()->SetOutputIsSecure(secure);
 }
 
 }  // namespace display_compositor
diff --git a/components/display_compositor/gpu_display_compositor_frame_sink.h b/components/display_compositor/gpu_display_compositor_frame_sink.h
index ac3ad8b..588ef75 100644
--- a/components/display_compositor/gpu_display_compositor_frame_sink.h
+++ b/components/display_compositor/gpu_display_compositor_frame_sink.h
@@ -38,12 +38,6 @@
   mojo::AssociatedBinding<cc::mojom::MojoCompositorFrameSink> binding_;
   mojo::AssociatedBinding<cc::mojom::DisplayPrivate> display_private_binding_;
 
-  // GpuCompositorFrameSink holds a Display and its BeginFrameSource. In the
-  // window server, the display root window's CompositorFrameSink will have a
-  // valid gpu::SurfaceHandle.
-  std::unique_ptr<cc::BeginFrameSource> display_begin_frame_source_;
-  std::unique_ptr<cc::Display> display_;
-
   DISALLOW_COPY_AND_ASSIGN(GpuDisplayCompositorFrameSink);
 };
 
diff --git a/components/display_compositor/gpu_offscreen_compositor_frame_sink.cc b/components/display_compositor/gpu_offscreen_compositor_frame_sink.cc
index f14f8db..e47474d 100644
--- a/components/display_compositor/gpu_offscreen_compositor_frame_sink.cc
+++ b/components/display_compositor/gpu_offscreen_compositor_frame_sink.cc
@@ -18,6 +18,7 @@
                              surface_manager,
                              frame_sink_id,
                              nullptr,
+                             nullptr,
                              std::move(compositor_frame_sink_private_request),
                              std::move(client)),
       binding_(this, std::move(request)) {
diff --git a/components/exo/PRESUBMIT.py b/components/exo/PRESUBMIT.py
deleted file mode 100644
index 1f71871..0000000
--- a/components/exo/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for Exosphere.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/exo/compositor_frame_sink.cc b/components/exo/compositor_frame_sink.cc
index 28e94a8..59a3ea4a 100644
--- a/components/exo/compositor_frame_sink.cc
+++ b/components/exo/compositor_frame_sink.cc
@@ -18,12 +18,7 @@
 CompositorFrameSink::CompositorFrameSink(const cc::FrameSinkId& frame_sink_id,
                                          cc::SurfaceManager* surface_manager,
                                          CompositorFrameSinkHolder* client)
-    : support_(this,
-               surface_manager,
-               frame_sink_id,
-               nullptr,
-               true /* handles_frame_sink_id_invalidation */,
-               true /* needs_sync_points */),
+    : support_(this, surface_manager, frame_sink_id, nullptr, nullptr),
       client_(client) {}
 
 CompositorFrameSink::~CompositorFrameSink() {}
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index a0c2a59..c9927a8 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -11,7 +11,6 @@
 #include "ash/common/wm/window_resizer.h"
 #include "ash/common/wm/window_state.h"
 #include "ash/common/wm/window_state_delegate.h"
-#include "ash/common/wm_shell.h"
 #include "ash/common/wm_window.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/wm/window_state_aura.h"
@@ -57,11 +56,6 @@
     {ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN},
     {ui::VKEY_F4, ui::EF_ALT_DOWN}};
 
-void UpdateShelfStateForFullscreenChange(views::Widget* widget) {
-  for (ash::WmWindow* root_window : ash::WmShell::Get()->GetAllRootWindows())
-    ash::WmShelf::ForWindow(root_window)->UpdateVisibilityState();
-}
-
 class CustomFrameView : public views::NonClientFrameView {
  public:
   explicit CustomFrameView(views::Widget* widget) : widget_(widget) {}
@@ -171,7 +165,6 @@
       ash::wm::WindowState* window_state =
           ash::wm::GetWindowState(widget_->GetNativeWindow());
       window_state->set_in_immersive_fullscreen(enter_fullscreen);
-      UpdateShelfStateForFullscreenChange(widget_);
     }
     return true;
   }
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc
index 1112715..dc67d75 100644
--- a/components/exo/surface_unittest.cc
+++ b/components/exo/surface_unittest.cc
@@ -98,7 +98,7 @@
   cc::SurfaceManager* surface_manager =
       aura::Env::GetInstance()->context_factory_private()->GetSurfaceManager();
   const cc::CompositorFrame& frame =
-      surface_manager->GetSurfaceForId(surface_id)->GetEligibleFrame();
+      surface_manager->GetSurfaceForId(surface_id)->GetActiveFrame();
   return frame;
 }
 
diff --git a/components/favicon/core/fallback_icon_service.cc b/components/favicon/core/fallback_icon_service.cc
index 195614a..5164f97 100644
--- a/components/favicon/core/fallback_icon_service.cc
+++ b/components/favicon/core/fallback_icon_service.cc
@@ -58,15 +58,15 @@
     gfx::Canvas* canvas) {
   const int kOffsetX = 0;
   const int kOffsetY = 0;
-  cc::PaintFlags paint;
-  paint.setStyle(cc::PaintFlags::kFill_Style);
-  paint.setAntiAlias(true);
+  cc::PaintFlags flags;
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setAntiAlias(true);
 
   // Draw a filled, colored rounded square.
-  paint.setColor(style.background_color);
+  flags.setColor(style.background_color);
   int corner_radius = static_cast<int>(size * style.roundness * 0.5 + 0.5);
-  canvas->DrawRoundRect(
-      gfx::Rect(kOffsetX, kOffsetY, size, size), corner_radius, paint);
+  canvas->DrawRoundRect(gfx::Rect(kOffsetX, kOffsetY, size, size),
+                        corner_radius, flags);
 
   // Draw text.
   base::string16 icon_text = GetFallbackIconText(icon_url);
diff --git a/components/history/core/test/history_client_fake_bookmarks.cc b/components/history/core/test/history_client_fake_bookmarks.cc
index 6759650..e54087c 100644
--- a/components/history/core/test/history_client_fake_bookmarks.cc
+++ b/components/history/core/test/history_client_fake_bookmarks.cc
@@ -15,7 +15,8 @@
 
 namespace history {
 
-class FakeBookmarkDatabase : public base::RefCounted<FakeBookmarkDatabase> {
+class FakeBookmarkDatabase
+    : public base::RefCountedThreadSafe<FakeBookmarkDatabase> {
  public:
   FakeBookmarkDatabase() {}
 
@@ -27,7 +28,7 @@
   void GetBookmarks(std::vector<URLAndTitle>* bookmarks);
 
  private:
-  friend class base::RefCounted<FakeBookmarkDatabase>;
+  friend class base::RefCountedThreadSafe<FakeBookmarkDatabase>;
 
   ~FakeBookmarkDatabase() {}
 
diff --git a/components/leveldb/leveldb_mojo_proxy.cc b/components/leveldb/leveldb_mojo_proxy.cc
index 97fcde7e6..c3c9943 100644
--- a/components/leveldb/leveldb_mojo_proxy.cc
+++ b/components/leveldb/leveldb_mojo_proxy.cc
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/single_thread_task_runner.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
 
 namespace leveldb {
 
@@ -184,6 +185,7 @@
                                           std::string name,
                                           uint32_t open_flags,
                                           base::File* output_file) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   base::File file;
   filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
   bool completed =
@@ -201,6 +203,7 @@
     OpaqueDir* dir,
     std::string name,
     filesystem::mojom::FileError* out_error) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   filesystem::mojom::DirectoryPtr target;
   bool completed = dir->directory->OpenDirectory(
       name, MakeRequest(&target),
@@ -217,6 +220,7 @@
 void LevelDBMojoProxy::FileExistsImpl(OpaqueDir* dir,
                                       std::string name,
                                       bool* exists) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
   bool completed = dir->directory->Exists(name, &error, exists);
   DCHECK(completed);
@@ -227,6 +231,7 @@
     std::string name,
     std::vector<std::string>* out_contents,
     filesystem::mojom::FileError* out_error) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   filesystem::mojom::DirectoryPtr target;
   filesystem::mojom::DirectoryRequest proxy(&target);
   bool completed = dir->directory->OpenDirectory(
@@ -252,6 +257,7 @@
                                   std::string name,
                                   uint32_t delete_flags,
                                   filesystem::mojom::FileError* out_error) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   bool completed = dir->directory->Delete(name, delete_flags, out_error);
   DCHECK(completed);
 }
@@ -259,6 +265,7 @@
 void LevelDBMojoProxy::CreateDirImpl(OpaqueDir* dir,
                                      std::string name,
                                      filesystem::mojom::FileError* out_error) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   bool completed = dir->directory->OpenDirectory(
       name, nullptr,
       filesystem::mojom::kFlagRead | filesystem::mojom::kFlagWrite |
@@ -272,6 +279,7 @@
     const std::string& path,
     uint64_t* file_size,
     filesystem::mojom::FileError* out_error) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   filesystem::mojom::FileInformationPtr info;
   bool completed = dir->directory->StatFile(path, out_error, &info);
   DCHECK(completed);
@@ -283,6 +291,7 @@
                                       const std::string& old_path,
                                       const std::string& new_path,
                                       filesystem::mojom::FileError* out_error) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   bool completed = dir->directory->Rename(old_path, new_path, out_error);
   DCHECK(completed);
 }
@@ -291,6 +300,7 @@
                                     const std::string& path,
                                     filesystem::mojom::FileError* out_error,
                                     OpaqueLock** out_lock) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   // Since a lock is associated with a file descriptor, we need to open and
   // have a persistent file on the other side of the connection.
   filesystem::mojom::FilePtr target;
@@ -317,6 +327,7 @@
 
 void LevelDBMojoProxy::UnlockFileImpl(std::unique_ptr<OpaqueLock> lock,
                                       filesystem::mojom::FileError* out_error) {
+  mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync;
   lock->lock_file->Unlock(out_error);
 }
 
diff --git a/components/metrics/proto/omnibox_event.proto b/components/metrics/proto/omnibox_event.proto
index 2f8f24d..ea002f54 100644
--- a/components/metrics/proto/omnibox_event.proto
+++ b/components/metrics/proto/omnibox_event.proto
@@ -16,7 +16,13 @@
 
 // Next tag: 17
 message OmniboxEventProto {
-  // The timestamp for the event, in seconds since the epoch.
+  // The timestamp for the event, in seconds.
+  // This value comes from Chromium's TimeTicks::Now(), which is an abstract
+  // time value that is guaranteed to always be non-decreasing (regardless of
+  // Daylight Saving Time or any other changes to the system clock).
+  // These numbers are only comparable within a session.  To sequence events
+  // across sessions, order by the |session_id| from the
+  // ChromeUserMetricsExtension message.
   optional int64 time = 1;
 
   // The id of the originating tab for this omnibox interaction.
diff --git a/components/metrics/proto/user_action_event.proto b/components/metrics/proto/user_action_event.proto
index 30a93180..b7baa17 100644
--- a/components/metrics/proto/user_action_event.proto
+++ b/components/metrics/proto/user_action_event.proto
@@ -18,6 +18,12 @@
   // The name of the action, hashed.
   optional fixed64 name_hash = 1;
 
-  // The timestamp for the event, in seconds since the epoch.
+  // The timestamp for the event, in seconds.
+  // This value comes from Chromium's TimeTicks::Now(), which is an abstract
+  // time value that is guaranteed to always be non-decreasing (regardless of
+  // Daylight Saving Time or any other changes to the system clock).
+  // These numbers are only comparable within a session.  To sequence events
+  // across sessions, order by the |session_id| from the
+  // ChromeUserMetricsExtension message.
   optional int64 time = 2;
 }
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc
index b2e884b..2dd7aad 100644
--- a/components/omnibox/browser/autocomplete_result.cc
+++ b/components/omnibox/browser/autocomplete_result.cc
@@ -134,17 +134,11 @@
   CompareWithDemoteByType<AutocompleteMatch> comparing_object(
       input.current_page_classification());
   std::sort(matches_.begin(), matches_.end(), comparing_object);
-  if (!matches_.empty() && !matches_.begin()->allowed_to_be_default_match) {
-    // Top match is not allowed to be the default match.  Find the most
-    // relevant legal match and shift it to the front.
-    for (AutocompleteResult::iterator it = matches_.begin() + 1;
-         it != matches_.end(); ++it) {
-      if (it->allowed_to_be_default_match) {
-        std::rotate(matches_.begin(), it, it + 1);
-        break;
-      }
-    }
-  }
+  // Top match is not allowed to be the default match.  Find the most
+  // relevant legal match and shift it to the front.
+  ACMatches::iterator it = FindTopMatch(&matches_);
+  if (it != matches_.end())
+    std::rotate(matches_.begin(), it, it + 1);
   // In the process of trimming, drop all matches with a demoted relevance
   // score of 0.
   size_t num_matches;
@@ -259,6 +253,23 @@
   return true;
 }
 
+// static
+ACMatches::const_iterator AutocompleteResult::FindTopMatch(
+    const ACMatches& matches) {
+  ACMatches::const_iterator it = matches.begin();
+  while ((it != matches.end()) && !it->allowed_to_be_default_match)
+    ++it;
+  return it;
+}
+
+// static
+ACMatches::iterator AutocompleteResult::FindTopMatch(ACMatches* matches) {
+  ACMatches::iterator it = matches->begin();
+  while ((it != matches->end()) && !it->allowed_to_be_default_match)
+    ++it;
+  return it;
+}
+
 void AutocompleteResult::Reset() {
   matches_.clear();
   default_match_ = end();
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h
index 160aa3c..499d97d 100644
--- a/components/omnibox/browser/autocomplete_result.h
+++ b/components/omnibox/browser/autocomplete_result.h
@@ -106,6 +106,10 @@
   // some kind of verbatim match.
   bool TopMatchIsStandaloneVerbatimMatch() const;
 
+  // Returns the first match in |matches| which might be chosen as default.
+  static ACMatches::const_iterator FindTopMatch(const ACMatches& matches);
+  static ACMatches::iterator FindTopMatch(ACMatches* matches);
+
   const GURL& alternate_nav_url() const { return alternate_nav_url_; }
 
   // Clears the matches for this result set.
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
index 113ed9e..e18d9064 100644
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -210,14 +210,6 @@
   }
 }
 
-// static
-ACMatches::iterator SearchProvider::FindTopMatch(ACMatches* matches) {
-  ACMatches::iterator it = matches->begin();
-  while ((it != matches->end()) && !it->allowed_to_be_default_match)
-    ++it;
-  return it;
-}
-
 void SearchProvider::Start(const AutocompleteInput& input,
                            bool minimal_changes) {
   TRACE_EVENT0("omnibox", "SearchProvider::Start");
@@ -517,7 +509,7 @@
     const bool is_extension_keyword = (keyword_url != NULL) &&
         (keyword_url->type() == TemplateURL::OMNIBOX_API_EXTENSION);
     if ((keyword_url != NULL) && !is_extension_keyword &&
-        (FindTopMatch() == matches_.end())) {
+        (AutocompleteResult::FindTopMatch(&matches_) == matches_.end())) {
       // In non-extension keyword mode, disregard the keyword verbatim suggested
       // relevance if necessary, so at least one match is allowed to be default.
       // (In extension keyword mode this is not necessary because the extension
@@ -538,7 +530,8 @@
       keyword_results_.verbatim_relevance = -1;
       ConvertResultsToAutocompleteMatches();
     }
-    if (!is_extension_keyword && (FindTopMatch() == matches_.end())) {
+    if (!is_extension_keyword &&
+        (AutocompleteResult::FindTopMatch(&matches_) == matches_.end())) {
       // Guarantee that SearchProvider returns a legal default match (except
       // when in extension-based keyword mode).  The omnibox always needs at
       // least one legal default match, and it relies on SearchProvider in
@@ -553,7 +546,8 @@
       ConvertResultsToAutocompleteMatches();
     }
     DCHECK(!IsTopMatchSearchWithURLInput());
-    DCHECK(is_extension_keyword || (FindTopMatch() != matches_.end()));
+    DCHECK(is_extension_keyword ||
+           (AutocompleteResult::FindTopMatch(&matches_) != matches_.end()));
   }
   UMA_HISTOGRAM_CUSTOM_COUNTS(
       "Omnibox.SearchProviderMatches", matches_.size(), 1, 6, 7);
@@ -561,7 +555,8 @@
   // Record the top suggestion (if any) for future use.
   top_query_suggestion_match_contents_ = base::string16();
   top_navigation_suggestion_ = GURL();
-  ACMatches::const_iterator first_match = FindTopMatch();
+  ACMatches::const_iterator first_match =
+      AutocompleteResult::FindTopMatch(matches_);
   if ((first_match != matches_.end()) &&
       !first_match->inline_autocompletion.empty()) {
     // Identify if this match came from a query suggestion or a navsuggestion.
@@ -1007,7 +1002,8 @@
   // Guarantee that if there's a legal default match anywhere in the result
   // set that it'll get returned.  The rotate() call does this by moving the
   // default match to the front of the list.
-  ACMatches::iterator default_match = FindTopMatch(&matches);
+  ACMatches::iterator default_match =
+      AutocompleteResult::FindTopMatch(&matches);
   if (default_match != matches.end())
     std::rotate(matches.begin(), default_match, default_match + 1);
 
@@ -1062,15 +1058,9 @@
   }
 }
 
-ACMatches::const_iterator SearchProvider::FindTopMatch() const {
-  ACMatches::const_iterator it = matches_.begin();
-  while ((it != matches_.end()) && !it->allowed_to_be_default_match)
-    ++it;
-  return it;
-}
-
 bool SearchProvider::IsTopMatchSearchWithURLInput() const {
-  ACMatches::const_iterator first_match = FindTopMatch();
+  ACMatches::const_iterator first_match =
+      AutocompleteResult::FindTopMatch(matches_);
   return (input_.type() == metrics::OmniboxInputType::URL) &&
       (first_match != matches_.end()) &&
       (first_match->relevance > CalculateRelevanceForVerbatim()) &&
diff --git a/components/omnibox/browser/search_provider.h b/components/omnibox/browser/search_provider.h
index 5895cfe3..330a9f3 100644
--- a/components/omnibox/browser/search_provider.h
+++ b/components/omnibox/browser/search_provider.h
@@ -155,9 +155,6 @@
   static void UpdateOldResults(bool minimal_changes,
                                SearchSuggestionParser::Results* results);
 
-  // Returns the first match in |matches| which might be chosen as default.
-  static ACMatches::iterator FindTopMatch(ACMatches* matches);
-
   // AutocompleteProvider:
   void Start(const AutocompleteInput& input, bool minimal_changes) override;
   void Stop(bool clear_cached_results,
@@ -258,10 +255,6 @@
   // that appears.
   static void RemoveExtraAnswers(ACMatches* matches);
 
-  // Returns an iterator to the first match in |matches_| which might
-  // be chosen as default.
-  ACMatches::const_iterator FindTopMatch() const;
-
   // Checks if suggested relevances violate an expected constraint.
   // See UpdateMatches() for the use and explanation of this constraint
   // and other constraints enforced without the use of helper functions.
diff --git a/components/password_manager/PRESUBMIT.py b/components/password_manager/PRESUBMIT.py
deleted file mode 100644
index c48fc83c..0000000
--- a/components/password_manager/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for components/password_manager
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 152630f..f6670796 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -178,14 +178,14 @@
                  autofill::ServerFieldTypeSet* available_field_types) {
   for (size_t i = 0; i < form_structure->field_count(); ++i) {
     autofill::AutofillField* field = form_structure->field(i);
-    if (field->name.empty())
-      continue;
 
     autofill::ServerFieldType type = autofill::UNKNOWN_TYPE;
-    auto iter = field_types.find(field->name);
-    if (iter != field_types.end()) {
-      type = iter->second;
-      available_field_types->insert(type);
+    if (!field->name.empty()) {
+      auto iter = field_types.find(field->name);
+      if (iter != field_types.end()) {
+        type = iter->second;
+        available_field_types->insert(type);
+      }
     }
 
     autofill::ServerFieldTypeSet types;
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index be93b49..4676a6c 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -458,6 +458,8 @@
     field.name = ASCIIToUTF16("NewPasswd");
     field.form_control_type = "password";
     observed_form()->form_data.fields.push_back(field);
+    autofill::FormFieldData empty_field;
+    observed_form()->form_data.fields.push_back(empty_field);
     if (has_confirmation_field) {
       field.label = ASCIIToUTF16("ConfPwd");
       field.name = ASCIIToUTF16("ConfPwd");
@@ -500,6 +502,7 @@
     expected_types[observed_form_.username_element] = autofill::UNKNOWN_TYPE;
     expected_types[observed_form_.password_element] = autofill::PASSWORD;
     expected_types[observed_form_.new_password_element] = field_type;
+    expected_types[base::string16()] = autofill::UNKNOWN_TYPE;
 
     autofill::ServerFieldTypeSet expected_available_field_types;
     expected_available_field_types.insert(autofill::PASSWORD);
@@ -2801,6 +2804,8 @@
       pending, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
 
   EXPECT_FALSE(form_manager()->IsNewLogin());
+  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
+              StartUploadRequest(_, false, _, _, true));
 
   base::UserActionTester tester;
   EXPECT_EQ(0, tester.GetActionCount("PasswordManager_LoginFollowingAutofill"));
diff --git a/components/payments/OWNERS b/components/payments/OWNERS
index 0268867..0ae9d75 100644
--- a/components/payments/OWNERS
+++ b/components/payments/OWNERS
@@ -1,5 +1,4 @@
-jdonnelly@chromium.org
-krb@chromium.org
+mathp@chromium.org
 rouslan@chromium.org
 
 per-file *.mojom=set noparent
diff --git a/components/previews/PRESUBMIT.py b/components/previews/PRESUBMIT.py
deleted file mode 100644
index e23e2abf..0000000
--- a/components/previews/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +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.
-
-"""Top-level presubmit script for the previews component.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/proximity_auth/PRESUBMIT.py b/components/proximity_auth/PRESUBMIT.py
deleted file mode 100644
index bf46ab3..0000000
--- a/components/proximity_auth/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2014 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.
-
-"""Top-level presubmit script for the proximity_auth component.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/safe_browsing_db/PRESUBMIT.py b/components/safe_browsing_db/PRESUBMIT.py
deleted file mode 100644
index 9a395c9..0000000
--- a/components/safe_browsing_db/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +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.
-
-"""Presubmit script for components/safe_browsing_db
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/safe_browsing_db/safebrowsing.proto b/components/safe_browsing_db/safebrowsing.proto
index fbe1e57..989cd2d2 100644
--- a/components/safe_browsing_db/safebrowsing.proto
+++ b/components/safe_browsing_db/safebrowsing.proto
@@ -285,7 +285,7 @@
 
   // Patterns to be used for activating the subresource filter. Interstitial
   // will not be shown for patterns from this list.
-  SUBRESOURCE_FILTER = 11;
+  SUBRESOURCE_FILTER = 13;
 }
 
 // Types of platforms.
diff --git a/components/security_state/core/security_state.cc b/components/security_state/core/security_state.cc
index 64274e0..36ac2a7e 100644
--- a/components/security_state/core/security_state.cc
+++ b/components/security_state/core/security_state.cc
@@ -120,9 +120,9 @@
     return DANGEROUS;
   }
 
-  GURL url = visible_security_state.url;
+  const GURL url = visible_security_state.url;
 
-  bool is_cryptographic_with_certificate =
+  const bool is_cryptographic_with_certificate =
       (url.SchemeIsCryptographic() && visible_security_state.certificate);
 
   // Set the security level to DANGEROUS for major certificate errors.
@@ -138,9 +138,13 @@
   if (url.SchemeIs(url::kDataScheme))
     return SecurityLevel::HTTP_SHOW_WARNING;
 
-  // Choose the appropriate security level for HTTP requests.
+  // Choose the appropriate security level for requests to HTTP and remaining
+  // pseudo URLs (blob:, filesystem:). filesystem: is a standard scheme so does
+  // not need to be explicitly listed here.
+  // TODO(meacer): Remove special case for blob (crbug.com/684751).
   if (!is_cryptographic_with_certificate) {
-    if (!is_origin_secure_callback.Run(url) && url.IsStandard()) {
+    if (!is_origin_secure_callback.Run(url) &&
+        (url.IsStandard() || url.SchemeIs(url::kBlobScheme))) {
       return GetSecurityLevelForNonSecureFieldTrial(
           visible_security_state.displayed_password_field_on_http ||
           visible_security_state.displayed_credit_card_field_on_http);
diff --git a/components/security_state/core/security_state_unittest.cc b/components/security_state/core/security_state_unittest.cc
index 54b7cd3..00753de0 100644
--- a/components/security_state/core/security_state_unittest.cc
+++ b/components/security_state/core/security_state_unittest.cc
@@ -26,6 +26,12 @@
 const char kHttpsUrl[] = "https://foo.test/";
 const char kHttpUrl[] = "http://foo.test/";
 
+// This list doesn't include data: URL, as data: URLs will be explicitly marked
+// as not secure.
+const char* const kPseudoUrls[] = {
+    "blob:http://test/some-guid", "filesystem:http://test/some-guid",
+};
+
 bool IsOriginSecure(const GURL& url) {
   return url == kHttpsUrl;
 }
@@ -273,6 +279,22 @@
   EXPECT_EQ(HTTP_SHOW_WARNING, security_info.security_level);
 }
 
+// Tests that password fields cause the security level to be downgraded
+// to HTTP_SHOW_WARNING on pseudo URLs when the command-line switch is set.
+TEST(SecurityStateTest, PasswordFieldWarningOnPseudoUrls) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kMarkHttpAs, switches::kMarkHttpWithPasswordsOrCcWithChip);
+  for (const char* const url : kPseudoUrls) {
+    TestSecurityStateHelper helper;
+    helper.SetUrl(GURL(url));
+    helper.set_displayed_password_field_on_http(true);
+    SecurityInfo security_info;
+    helper.GetSecurityInfo(&security_info);
+    EXPECT_TRUE(security_info.displayed_password_field_on_http);
+    EXPECT_EQ(HTTP_SHOW_WARNING, security_info.security_level);
+  }
+}
+
 // Tests that credit card fields cause the security level to be downgraded
 // to HTTP_SHOW_WARNING when the command-line switch is set.
 TEST(SecurityStateTest, CreditCardFieldWarning) {
@@ -287,6 +309,22 @@
   EXPECT_EQ(HTTP_SHOW_WARNING, security_info.security_level);
 }
 
+// Tests that credit card fields cause the security level to be downgraded
+// to HTTP_SHOW_WARNING on pseudo URLs when the command-line switch is set.
+TEST(SecurityStateTest, CreditCardFieldWarningOnPseudoUrls) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kMarkHttpAs, switches::kMarkHttpWithPasswordsOrCcWithChip);
+  for (const char* const url : kPseudoUrls) {
+    TestSecurityStateHelper helper;
+    helper.SetUrl(GURL(url));
+    helper.set_displayed_credit_card_field_on_http(true);
+    SecurityInfo security_info;
+    helper.GetSecurityInfo(&security_info);
+    EXPECT_TRUE(security_info.displayed_credit_card_field_on_http);
+    EXPECT_EQ(HTTP_SHOW_WARNING, security_info.security_level);
+  }
+}
+
 // Tests that neither |displayed_password_field_on_http| nor
 // |displayed_credit_card_field_on_http| is set when the corresponding
 // VisibleSecurityState flags are not set.
@@ -300,6 +338,21 @@
   EXPECT_EQ(NONE, security_info.security_level);
 }
 
+// Tests that neither |displayed_password_field_on_http| nor
+// |displayed_credit_card_field_on_http| is set on pseudo URLs when the
+// corresponding VisibleSecurityState flags are not set.
+TEST(SecurityStateTest, PrivateUserDataNotSetOnPseudoUrls) {
+  for (const char* const url : kPseudoUrls) {
+    TestSecurityStateHelper helper;
+    helper.SetUrl(GURL(url));
+    SecurityInfo security_info;
+    helper.GetSecurityInfo(&security_info);
+    EXPECT_FALSE(security_info.displayed_password_field_on_http);
+    EXPECT_FALSE(security_info.displayed_credit_card_field_on_http);
+    EXPECT_EQ(NONE, security_info.security_level);
+  }
+}
+
 // Tests that SSL.MarkHttpAsStatus histogram is updated when security state is
 // computed for a page.
 TEST(SecurityStateTest, MarkHttpAsStatusHistogram) {
diff --git a/components/subresource_filter/PRESUBMIT.py b/components/subresource_filter/PRESUBMIT.py
deleted file mode 100644
index 9f22710..0000000
--- a/components/subresource_filter/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +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.
-
-"""Presubmit script for components/subresource_filter
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/components/subresource_filter/content/browser/BUILD.gn b/components/subresource_filter/content/browser/BUILD.gn
index e49864e..31d7f480 100644
--- a/components/subresource_filter/content/browser/BUILD.gn
+++ b/components/subresource_filter/content/browser/BUILD.gn
@@ -24,6 +24,9 @@
     "//ipc",
     "//url",
   ]
+  public_deps = [
+    "//ui/base",
+  ]
 }
 
 source_set("unit_tests") {
diff --git a/components/subresource_filter/content/browser/DEPS b/components/subresource_filter/content/browser/DEPS
index f5b44b7b..fdf9670 100644
--- a/components/subresource_filter/content/browser/DEPS
+++ b/components/subresource_filter/content/browser/DEPS
@@ -2,4 +2,5 @@
   "+components/keyed_service/core",
   "+content/public/browser",
   "+components/safe_browsing_db",
+  "+ui/base/page_transition_types.h",
 ]
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
index c9125d2..0ba6bf3 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
@@ -41,6 +41,14 @@
   return rate == 1 || (rate > 0 && base::RandDouble() < rate);
 }
 
+bool NavigationIsPageReload(const GURL& url,
+                            const content::Referrer& referrer,
+                            ui::PageTransition transition) {
+  return ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD) ||
+         // Some pages 'reload' from JavaScript by navigating to themselves.
+         url == referrer.url;
+}
+
 }  // namespace
 
 // static
@@ -193,17 +201,20 @@
   return iterator == frame_drivers_.end() ? nullptr : iterator->second.get();
 }
 
+void ContentSubresourceFilterDriverFactory::ResetActivationState() {
+  navigation_chain_.clear();
+  activation_list_matches_.clear();
+  activation_level_ = ActivationLevel::DISABLED;
+  measure_performance_ = false;
+  aggregated_document_statistics_ = DocumentLoadStatistics();
+}
+
 void ContentSubresourceFilterDriverFactory::DidStartNavigation(
     content::NavigationHandle* navigation_handle) {
   if (navigation_handle->IsInMainFrame() && !navigation_handle->IsSamePage()) {
-    navigation_chain_.clear();
-    activation_list_matches_.clear();
+    ResetActivationState();
     navigation_chain_.push_back(navigation_handle->GetURL());
-
     client_->ToggleNotificationVisibility(false);
-    activation_level_ = ActivationLevel::DISABLED;
-    measure_performance_ = false;
-    aggregated_document_statistics_ = DocumentLoadStatistics();
   }
 }
 
@@ -230,7 +241,9 @@
   content::RenderFrameHost* render_frame_host =
       navigation_handle->GetRenderFrameHost();
   GURL url = navigation_handle->GetURL();
-  ReadyToCommitNavigationInternal(render_frame_host, url);
+  const content::Referrer& referrer = navigation_handle->GetReferrer();
+  ui::PageTransition transition = navigation_handle->GetPageTransition();
+  ReadyToCommitNavigationInternal(render_frame_host, url, referrer, transition);
 }
 
 void ContentSubresourceFilterDriverFactory::DidFinishLoad(
@@ -290,22 +303,31 @@
 
 void ContentSubresourceFilterDriverFactory::ReadyToCommitNavigationInternal(
     content::RenderFrameHost* render_frame_host,
-    const GURL& url) {
-  if (!render_frame_host->GetParent()) {
-    RecordRedirectChainMatchPattern();
-    if (ShouldActivateForMainFrameURL(url)) {
-      activation_level_ = GetMaximumActivationLevel();
-      measure_performance_ = activation_level_ != ActivationLevel::DISABLED &&
-                             ShouldMeasurePerformanceForPageLoad();
-      ActivateForFrameHostIfNeeded(render_frame_host, url);
-    } else {
-      activation_level_ = ActivationLevel::DISABLED;
-      measure_performance_ = false;
-      aggregated_document_statistics_ = DocumentLoadStatistics();
-    }
-  } else {
+    const GURL& url,
+    const content::Referrer& referrer,
+    ui::PageTransition transition) {
+  if (render_frame_host->GetParent()) {
     ActivateForFrameHostIfNeeded(render_frame_host, url);
+    return;
   }
+
+  RecordRedirectChainMatchPattern();
+
+  if (ShouldWhitelistSiteOnReload() &&
+      NavigationIsPageReload(url, referrer, transition)) {
+    // Whitelist this host for the current as well as subsequent navigations.
+    AddHostOfURLToWhitelistSet(url);
+  }
+
+  if (!ShouldActivateForMainFrameURL(url)) {
+    ResetActivationState();
+    return;
+  }
+
+  activation_level_ = GetMaximumActivationLevel();
+  measure_performance_ = activation_level_ != ActivationLevel::DISABLED &&
+                         ShouldMeasurePerformanceForPageLoad();
+  ActivateForFrameHostIfNeeded(render_frame_host, url);
 }
 
 bool ContentSubresourceFilterDriverFactory::DidURLMatchCurrentActivationList(
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h
index 49727a6..0ec55f4 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h
+++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h
@@ -17,6 +17,7 @@
 #include "components/safe_browsing_db/util.h"
 #include "components/subresource_filter/content/common/document_load_statistics.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -91,6 +92,8 @@
   ContentSubresourceFilterDriver* DriverFromFrameHost(
       content::RenderFrameHost* render_frame_host);
 
+  void ResetActivationState();
+
   void OnFirstSubresourceLoadDisallowed();
 
   void OnDocumentLoadStatistics(const DocumentLoadStatistics& statistics);
@@ -121,7 +124,9 @@
   // NavigationHandle to ease unit tests.
   void ReadyToCommitNavigationInternal(
       content::RenderFrameHost* render_frame_host,
-      const GURL& url);
+      const GURL& url,
+      const content::Referrer& referrer,
+      ui::PageTransition page_transition);
 
   bool DidURLMatchCurrentActivationList(const GURL& url) const;
 
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
index fa76b0dc..0109d4f 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
@@ -211,6 +211,8 @@
       const std::vector<GURL>& navigation_chain,
       safe_browsing::SBThreatType threat_type,
       safe_browsing::ThreatPatternType threat_type_metadata,
+      const content::Referrer& referrer,
+      ui::PageTransition transition,
       RedirectChainMatchPattern expected_pattern,
       bool expected_activation) {
     base::HistogramTester tester;
@@ -238,9 +240,12 @@
                 ActivateForProvisionalLoad(::testing::_, ::testing::_,
                                            expected_measure_performance()))
         .Times(expected_activation);
+    // TODO(crbug.com/688393): remove the call to
+    // ReadyToCommitNavigationInternal once WCO::ReadyToCommitNavigation is
+    // invoked consistently for tests in PlzNavigate and non-PlzNavigate.
     if (!content::IsBrowserSideNavigationEnabled()) {
-      factory()->ReadyToCommitNavigationInternal(main_rfh(),
-                                                 navigation_chain.back());
+      factory()->ReadyToCommitNavigationInternal(
+          main_rfh(), navigation_chain.back(), referrer, transition);
     }
 
     rfh_tester->SimulateNavigationCommit(navigation_chain.back());
@@ -268,7 +273,8 @@
         .Times(expected_activation);
     EXPECT_CALL(*client(), ToggleNotificationVisibility(::testing::_)).Times(0);
 
-    factory()->ReadyToCommitNavigationInternal(subframe_rfh(), url);
+    factory()->ReadyToCommitNavigationInternal(
+        subframe_rfh(), url, content::Referrer(), ui::PAGE_TRANSITION_LINK);
     ::testing::Mock::VerifyAndClearExpectations(subframe_driver());
     ::testing::Mock::VerifyAndClearExpectations(client());
   }
@@ -278,11 +284,13 @@
       const std::vector<GURL>& navigation_chain,
       safe_browsing::SBThreatType threat_type,
       safe_browsing::ThreatPatternType threat_type_metadata,
+      const content::Referrer& referrer,
+      ui::PageTransition transition,
       RedirectChainMatchPattern expected_pattern,
       bool expected_activation) {
     BlacklistURLWithRedirectsNavigateAndCommit(
         blacklisted_urls, navigation_chain, threat_type, threat_type_metadata,
-        expected_pattern, expected_activation);
+        referrer, transition, expected_pattern, expected_activation);
 
     NavigateAndCommitSubframe(GURL(kExampleLoginUrl), expected_activation);
   }
@@ -295,7 +303,8 @@
         blacklisted_urls, navigation_chain,
         safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
         safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS,
-        expected_pattern, expected_activation);
+        content::Referrer(), ui::PAGE_TRANSITION_LINK, expected_pattern,
+        expected_activation);
   }
 
   void EmulateDidDisallowFirstSubresourceMessage() {
@@ -506,6 +515,7 @@
         test_data.blacklisted_urls, test_data.navigation_chain,
         safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
         safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS,
+        content::Referrer(), ui::PAGE_TRANSITION_LINK,
         test_data.hit_expected_pattern, test_data.expected_activation);
     NavigateAndExpectActivation({false}, {GURL("https://dummy.com")}, EMPTY,
                                 false);
@@ -539,6 +549,50 @@
   EmulateDidDisallowFirstSubresourceMessage();
 }
 
+TEST_F(ContentSubresourceFilterDriverFactoryTest, WhitelistSiteOnReload) {
+  // TODO(crbug.com/688393): enable this test for PlzNavigate once
+  // WCO::ReadyToCommitNavigation is invoked consistently for tests in
+  // PlzNavigate and non-PlzNavigate.
+  if (content::IsBrowserSideNavigationEnabled())
+    return;
+
+  const struct {
+    content::Referrer referrer;
+    ui::PageTransition transition;
+    bool expect_activation;
+  } kTestCases[] = {
+      {content::Referrer(), ui::PAGE_TRANSITION_LINK, true},
+      {content::Referrer(GURL(kUrlA), blink::WebReferrerPolicyDefault),
+       ui::PAGE_TRANSITION_LINK, true},
+      {content::Referrer(GURL(kExampleUrl), blink::WebReferrerPolicyDefault),
+       ui::PAGE_TRANSITION_LINK, false},
+      {content::Referrer(), ui::PAGE_TRANSITION_RELOAD, false}};
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(::testing::Message("referrer = \"")
+                 << test_case.referrer.url << "\""
+                 << " transition = \"" << test_case.transition << "\"");
+
+    base::FieldTrialList field_trial_list(nullptr);
+    testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
+        base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationLevelEnabled,
+        kActivationScopeAllSites, "" /* activation_lists */,
+        "" /* performance_measurement_rate */, "" /* suppress_notifications */,
+        "true" /* whitelist_site_on_reload */);
+
+    NavigateAndExpectActivation(
+        {false}, {GURL(kExampleUrl)},
+        safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
+        safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS,
+        test_case.referrer, test_case.transition, EMPTY,
+        test_case.expect_activation);
+    // Verify that if the first URL failed to activate, subsequent same-origin
+    // navigations also fail to activate.
+    NavigateAndExpectActivation({false}, {GURL(kExampleUrlWithParams)}, EMPTY,
+                                test_case.expect_activation);
+  }
+}
+
 TEST_P(ContentSubresourceFilterDriverFactoryActivationLevelTest,
        ActivateForFrameState) {
   const ActivationLevelTestData& test_data = GetParam();
@@ -570,12 +624,12 @@
   const GURL test_url("https://example.com/nonsoceng?q=engsocnon");
   std::vector<GURL> navigation_chain;
 
-  NavigateAndExpectActivation({false, false, false, true},
-                              {GURL(kUrlA), GURL(kUrlB), GURL(kUrlC), test_url},
-                              test_data.threat_type,
-                              test_data.threat_type_metadata,
-                              test_data.expected_activation ? F0M0L1 : EMPTY,
-                              test_data.expected_activation);
+  NavigateAndExpectActivation(
+      {false, false, false, true},
+      {GURL(kUrlA), GURL(kUrlB), GURL(kUrlC), test_url}, test_data.threat_type,
+      test_data.threat_type_metadata, content::Referrer(),
+      ui::PAGE_TRANSITION_LINK, test_data.expected_activation ? F0M0L1 : EMPTY,
+      test_data.expected_activation);
 };
 
 TEST_P(ContentSubresourceFilterDriverFactoryActivationScopeTest,
diff --git a/components/subresource_filter/core/browser/subresource_filter_features.cc b/components/subresource_filter/core/browser/subresource_filter_features.cc
index f141869..ef13cad 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features.cc
+++ b/components/subresource_filter/core/browser/subresource_filter_features.cc
@@ -40,6 +40,8 @@
 
 const char kSuppressNotificationsParameterName[] = "suppress_notifications";
 
+const char kWhitelistSiteOnReloadParameterName[] = "whitelist_site_on_reload";
+
 ActivationLevel GetMaximumActivationLevel() {
   std::string activation_level = variations::GetVariationParamValueByFeature(
       kSafeBrowsingSubresourceFilter, kActivationLevelParameterName);
@@ -101,4 +103,10 @@
       subresource_filter::kRulesetFlavorParameterName);
 }
 
+bool ShouldWhitelistSiteOnReload() {
+  return base::GetFieldTrialParamByFeatureAsBool(
+      kSafeBrowsingSubresourceFilter, kWhitelistSiteOnReloadParameterName,
+      false /* default value */);
+}
+
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/core/browser/subresource_filter_features.h b/components/subresource_filter/core/browser/subresource_filter_features.h
index a73408d..86b56aa 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features.h
+++ b/components/subresource_filter/core/browser/subresource_filter_features.h
@@ -36,6 +36,8 @@
 
 extern const char kSuppressNotificationsParameterName[];
 
+extern const char kWhitelistSiteOnReloadParameterName[];
+
 // Returns the maximum degree to which subresource filtering should be activated
 // on any RenderFrame. This will be ActivationLevel::DISABLED unless the feature
 // is enabled and variation parameters prescribe a higher activation level.
@@ -65,6 +67,9 @@
 // be used.
 std::string GetRulesetFlavor();
 
+// Returns whether the site of reloaded pages should be whitelisted.
+bool ShouldWhitelistSiteOnReload();
+
 }  // namespace subresource_filter
 
 #endif  // COMPONENTS_SUBRESOURCE_FILTER_CORE_BROWSER_SUBRESOURCE_FILTER_FEATURES_H_
diff --git a/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc b/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc
index adcf692..47ef01a 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc
+++ b/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc
@@ -26,7 +26,8 @@
     const std::string& activation_scope,
     const std::string& activation_lists,
     const std::string& performance_measurement_rate,
-    const std::string& suppress_notifications)
+    const std::string& suppress_notifications,
+    const std::string& whitelist_site_on_reload)
     : ScopedSubresourceFilterFeatureToggle(
           feature_state,
           {{kActivationLevelParameterName, maximum_activation_level},
@@ -34,7 +35,8 @@
            {kActivationListsParameterName, activation_lists},
            {kPerformanceMeasurementRateParameterName,
             performance_measurement_rate},
-           {kSuppressNotificationsParameterName, suppress_notifications}}) {}
+           {kSuppressNotificationsParameterName, suppress_notifications},
+           {kWhitelistSiteOnReloadParameterName, whitelist_site_on_reload}}) {}
 
 ScopedSubresourceFilterFeatureToggle::ScopedSubresourceFilterFeatureToggle(
     base::FeatureList::OverrideState feature_state,
diff --git a/components/subresource_filter/core/browser/subresource_filter_features_test_support.h b/components/subresource_filter/core/browser/subresource_filter_features_test_support.h
index 6da330ad1..080bf61 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features_test_support.h
+++ b/components/subresource_filter/core/browser/subresource_filter_features_test_support.h
@@ -26,7 +26,8 @@
       const std::string& activation_scope,
       const std::string& activation_lists = std::string(),
       const std::string& performance_measurement_rate = std::string(),
-      const std::string& suppress_notifications = std::string());
+      const std::string& suppress_notifications = std::string(),
+      const std::string& whitelist_site_on_reload = std::string());
 
   ScopedSubresourceFilterFeatureToggle(
       base::FeatureList::OverrideState feature_state,
diff --git a/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc b/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
index 55fb1981..1918d8c 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
+++ b/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
@@ -252,4 +252,37 @@
   }
 }
 
+TEST(SubresourceFilterFeaturesTest, WhitelistSiteOnReload) {
+  const struct {
+    bool feature_enabled;
+    const char* whitelist_site_on_reload_param;
+    bool expected_whitelist_site_on_reload_value;
+  } kTestCases[] = {{false, "", false},
+                    {false, "true", false},
+                    {false, "false", false},
+                    {false, "invalid value", false},
+                    {true, "", false},
+                    {true, "false", false},
+                    {true, "invalid value", false},
+                    {true, "True", false},
+                    {true, "TRUE", false},
+                    {true, "true", true}};
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(::testing::Message("Enabled = ") << test_case.feature_enabled);
+    SCOPED_TRACE(::testing::Message("WhitelistSiteOnReloadParam = \"")
+                 << test_case.whitelist_site_on_reload_param << "\"");
+
+    base::FieldTrialList field_trial_list(nullptr /* entropy_provider */);
+    testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
+        test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
+                                  : base::FeatureList::OVERRIDE_USE_DEFAULT,
+        {{kWhitelistSiteOnReloadParameterName,
+          test_case.whitelist_site_on_reload_param}});
+
+    EXPECT_EQ(test_case.expected_whitelist_site_on_reload_value,
+              ShouldWhitelistSiteOnReload());
+  }
+}
+
 }  // namespace subresource_filter
diff --git a/components/sync/PRESUBMIT.py b/components/sync/PRESUBMIT.py
index 276449b..59a138b 100644
--- a/components/sync/PRESUBMIT.py
+++ b/components/sync/PRESUBMIT.py
@@ -377,7 +377,6 @@
 def CheckChanges(input_api, output_api):
   results = []
   results += CheckChangeLintsClean(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   for f in input_api.AffectedFiles():
     if f.LocalPath().endswith(MODEL_TYPE_FILE_NAME):
       return CheckModelTypeInfoMap(input_api, output_api, f)
diff --git a/components/sync_bookmarks/PRESUBMIT.py b/components/sync_bookmarks/PRESUBMIT.py
index db47db9..44c9101 100644
--- a/components/sync_bookmarks/PRESUBMIT.py
+++ b/components/sync_bookmarks/PRESUBMIT.py
@@ -27,7 +27,6 @@
 def CheckChanges(input_api, output_api):
   results = []
   results += CheckChangeLintsClean(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
 
 def CheckChangeOnUpload(input_api, output_api):
diff --git a/components/sync_sessions/PRESUBMIT.py b/components/sync_sessions/PRESUBMIT.py
index ae142e02..e4ed675 100644
--- a/components/sync_sessions/PRESUBMIT.py
+++ b/components/sync_sessions/PRESUBMIT.py
@@ -26,7 +26,6 @@
 def CheckChanges(input_api, output_api):
   results = []
   results += CheckChangeLintsClean(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
 
 def CheckChangeOnUpload(input_api, output_api):
diff --git a/components/test_runner/mock_web_theme_engine.cc b/components/test_runner/mock_web_theme_engine.cc
index 80f6a29..009836e 100644
--- a/components/test_runner/mock_web_theme_engine.cc
+++ b/components/test_runner/mock_web_theme_engine.cc
@@ -118,15 +118,15 @@
 }
 
 void box(cc::PaintCanvas* canvas, const SkIRect& rect, SkColor fillColor) {
-  cc::PaintFlags paint;
+  cc::PaintFlags flags;
 
-  paint.setStyle(cc::PaintFlags::kFill_Style);
-  paint.setColor(fillColor);
-  canvas->drawIRect(rect, paint);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setColor(fillColor);
+  canvas->drawIRect(rect, flags);
 
-  paint.setColor(edgeColor);
-  paint.setStyle(cc::PaintFlags::kStroke_Style);
-  canvas->drawIRect(rect, paint);
+  flags.setColor(edgeColor);
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  canvas->drawIRect(rect, flags);
 }
 
 void line(cc::PaintCanvas* canvas,
@@ -135,10 +135,10 @@
           int x1,
           int y1,
           SkColor color) {
-  cc::PaintFlags paint;
-  paint.setColor(color);
+  cc::PaintFlags flags;
+  flags.setColor(color);
   canvas->drawLine(SkIntToScalar(x0), SkIntToScalar(y0), SkIntToScalar(x1),
-                   SkIntToScalar(y1), paint);
+                   SkIntToScalar(y1), flags);
 }
 
 void triangle(cc::PaintCanvas* canvas,
@@ -150,49 +150,49 @@
               int y2,
               SkColor color) {
   SkPath path;
-  cc::PaintFlags paint;
+  cc::PaintFlags flags;
 
-  paint.setColor(color);
-  paint.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setColor(color);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
   path.incReserve(4);
   path.moveTo(SkIntToScalar(x0), SkIntToScalar(y0));
   path.lineTo(SkIntToScalar(x1), SkIntToScalar(y1));
   path.lineTo(SkIntToScalar(x2), SkIntToScalar(y2));
   path.close();
-  canvas->drawPath(path, paint);
+  canvas->drawPath(path, flags);
 
-  paint.setColor(edgeColor);
-  paint.setStyle(cc::PaintFlags::kStroke_Style);
-  canvas->drawPath(path, paint);
+  flags.setColor(edgeColor);
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  canvas->drawPath(path, flags);
 }
 
 void roundRect(cc::PaintCanvas* canvas, SkIRect irect, SkColor color) {
   SkRect rect;
   SkScalar radius = SkIntToScalar(5);
-  cc::PaintFlags paint;
+  cc::PaintFlags flags;
 
   rect.set(irect);
-  paint.setColor(color);
-  paint.setStyle(cc::PaintFlags::kFill_Style);
-  canvas->drawRoundRect(rect, radius, radius, paint);
+  flags.setColor(color);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  canvas->drawRoundRect(rect, radius, radius, flags);
 
-  paint.setColor(edgeColor);
-  paint.setStyle(cc::PaintFlags::kStroke_Style);
-  canvas->drawRoundRect(rect, radius, radius, paint);
+  flags.setColor(edgeColor);
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  canvas->drawRoundRect(rect, radius, radius, flags);
 }
 
 void oval(cc::PaintCanvas* canvas, SkIRect irect, SkColor color) {
   SkRect rect;
-  cc::PaintFlags paint;
+  cc::PaintFlags flags;
 
   rect.set(irect);
-  paint.setColor(color);
-  paint.setStyle(cc::PaintFlags::kFill_Style);
-  canvas->drawOval(rect, paint);
+  flags.setColor(color);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  canvas->drawOval(rect, flags);
 
-  paint.setColor(edgeColor);
-  paint.setStyle(cc::PaintFlags::kStroke_Style);
-  canvas->drawOval(rect, paint);
+  flags.setColor(edgeColor);
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  canvas->drawOval(rect, flags);
 }
 
 void circle(cc::PaintCanvas* canvas,
@@ -206,15 +206,15 @@
 
   SkScalar cy = SkIntToScalar(top + height / 2);
   SkScalar cx = SkIntToScalar(left + width / 2);
-  cc::PaintFlags paint;
+  cc::PaintFlags flags;
 
-  paint.setColor(color);
-  paint.setStyle(cc::PaintFlags::kFill_Style);
-  canvas->drawCircle(cx, cy, radius, paint);
+  flags.setColor(color);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  canvas->drawCircle(cx, cy, radius, flags);
 
-  paint.setColor(edgeColor);
-  paint.setStyle(cc::PaintFlags::kStroke_Style);
-  canvas->drawCircle(cx, cy, radius, paint);
+  flags.setColor(edgeColor);
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  canvas->drawCircle(cx, cy, radius, flags);
 }
 
 void nestedBoxes(cc::PaintCanvas* canvas,
@@ -305,7 +305,7 @@
                                const blink::WebRect& rect,
                                const WebThemeEngine::ExtraParams* extraParams) {
   SkIRect irect = webRectToSkIRect(rect);
-  cc::PaintFlags paint;
+  cc::PaintFlags flags;
 
   // Indent amounts for the check in a checkbox or radio button.
   const int checkIndent = 3;
@@ -431,11 +431,11 @@
     case WebThemeEngine::PartScrollbarCorner: {
       SkIRect cornerRect = {rect.x, rect.y, rect.x + rect.width,
                             rect.y + rect.height};
-      paint.setColor(SK_ColorWHITE);
-      paint.setStyle(cc::PaintFlags::kFill_Style);
-      paint.setBlendMode(SkBlendMode::kSrc);
-      paint.setAntiAlias(true);
-      canvas->drawIRect(cornerRect, paint);
+      flags.setColor(SK_ColorWHITE);
+      flags.setStyle(cc::PaintFlags::kFill_Style);
+      flags.setBlendMode(SkBlendMode::kSrc);
+      flags.setAntiAlias(true);
+      canvas->drawIRect(cornerRect, flags);
       break;
     }
 
@@ -471,13 +471,13 @@
       break;
 
     case WebThemeEngine::PartTextField:
-      paint.setColor(extraParams->textField.backgroundColor);
-      paint.setStyle(cc::PaintFlags::kFill_Style);
-      canvas->drawIRect(irect, paint);
+      flags.setColor(extraParams->textField.backgroundColor);
+      flags.setStyle(cc::PaintFlags::kFill_Style);
+      canvas->drawIRect(irect, flags);
 
-      paint.setColor(edgeColor);
-      paint.setStyle(cc::PaintFlags::kStroke_Style);
-      canvas->drawIRect(irect, paint);
+      flags.setColor(edgeColor);
+      flags.setStyle(cc::PaintFlags::kStroke_Style);
+      canvas->drawIRect(irect, flags);
 
       markState(canvas, irect, state);
       break;
@@ -486,10 +486,10 @@
       if (extraParams->menuList.fillContentArea) {
         box(canvas, irect, extraParams->menuList.backgroundColor);
       } else {
-        cc::PaintFlags paint;
-        paint.setColor(edgeColor);
-        paint.setStyle(cc::PaintFlags::kStroke_Style);
-        canvas->drawIRect(irect, paint);
+        cc::PaintFlags flags;
+        flags.setColor(edgeColor);
+        flags.setStyle(cc::PaintFlags::kStroke_Style);
+        canvas->drawIRect(irect, flags);
       }
 
       // clip the drop-down arrow to be inside the select box
@@ -571,9 +571,9 @@
       break;
     }
     case WebThemeEngine::PartProgressBar: {
-      paint.setColor(bgColors(state));
-      paint.setStyle(cc::PaintFlags::kFill_Style);
-      canvas->drawIRect(irect, paint);
+      flags.setColor(bgColors(state));
+      flags.setStyle(cc::PaintFlags::kFill_Style);
+      canvas->drawIRect(irect, flags);
 
       // Emulate clipping
       SkIRect tofill = irect;
@@ -589,9 +589,9 @@
       if (!tofill.intersect(irect))
         tofill.setEmpty();
 
-      paint.setColor(edgeColor);
-      paint.setStyle(cc::PaintFlags::kFill_Style);
-      canvas->drawIRect(tofill, paint);
+      flags.setColor(edgeColor);
+      flags.setStyle(cc::PaintFlags::kFill_Style);
+      canvas->drawIRect(tofill, flags);
 
       markState(canvas, irect, state);
       break;
diff --git a/components/test_runner/pixel_dump.cc b/components/test_runner/pixel_dump.cc
index 508bda2..6b47a14 100644
--- a/components/test_runner/pixel_dump.cc
+++ b/components/test_runner/pixel_dump.cc
@@ -78,14 +78,14 @@
   if (wr.isEmpty())
     return;
   // Render a red rectangle bounding selection rect
-  cc::PaintFlags paint;
-  paint.setColor(0xFFFF0000);  // Fully opaque red
-  paint.setStyle(cc::PaintFlags::kStroke_Style);
-  paint.setAntiAlias(true);
-  paint.setStrokeWidth(1.0f);
+  cc::PaintFlags flags;
+  flags.setColor(0xFFFF0000);  // Fully opaque red
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  flags.setAntiAlias(true);
+  flags.setStrokeWidth(1.0f);
   SkIRect rect;  // Bounding rect
   rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height);
-  canvas->drawIRect(rect, paint);
+  canvas->drawIRect(rect, flags);
 }
 
 void CapturePixelsForPrinting(std::unique_ptr<PixelsDumpRequest> dump_request) {
diff --git a/components/test_runner/test_interfaces.cc b/components/test_runner/test_interfaces.cc
index 994ae7a7..4258c3fe 100644
--- a/components/test_runner/test_interfaces.cc
+++ b/components/test_runner/test_interfaces.cc
@@ -31,7 +31,7 @@
       main_view_(nullptr) {
   blink::setLayoutTestMode(true);
   // NOTE: please don't put feature specific enable flags here,
-  // instead add them to RuntimeEnabledFeatures.in
+  // instead add them to RuntimeEnabledFeatures.json5
 
   ResetAll();
 }
diff --git a/components/translate_strings.grdp b/components/translate_strings.grdp
index b4de758..87a0b1bb 100644
--- a/components/translate_strings.grdp
+++ b/components/translate_strings.grdp
@@ -28,11 +28,6 @@
       This page is in <ph name="SOURCE_LANGUAGE">$1<ex>English</ex></ph>. Translate it to <ph name="TARGET_LANGUAGE">$2<ex>French</ex></ph>?
     </message>
   </if>
-  <if expr="is_android">
-    <message name="IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE_MOBILE" desc="Mobile: Message that page is in specified language and ask if should translate.">
-      Translate from <ph name="original_language">$1<ex>French</ex></ph> to <ph name="target_language">$2<ex>English</ex></ph>?
-    </message>
-  </if>
   <message name="IDS_TRANSLATE_INFOBAR_ACCEPT" desc="Text to show for the translate infobar button to accept translation.">
     Translate
   </message>
@@ -54,11 +49,6 @@
   <message name="IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_AUTODETERMINED_SOURCE_LANGUAGE" desc="Message that page has been translated to another with server side auto language detection">
     This page has been translated to <ph name="target_language">$1<ex>German</ex></ph>
   </message>
-  <if expr="is_android">
-  <message name="IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_MOBILE" desc="Mobile: Message that page has been translated from one language to another">
-    This page has been translated to <ph name="target_language">$1<ex>German</ex></ph>
-  </message>
-  </if>
   <message name="IDS_TRANSLATE_INFOBAR_REVERT" desc="Text to show for translate infobar to revert translation of translated page">
     Show original
   </message>
@@ -80,10 +70,5 @@
   <message name="IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE" desc="Error message shown when the translate server translated the page and returned the page was in a language the browser does not know.">
     This page has been translated from an unknown language to <ph name="language_language">$1<ex>English</ex></ph>
   </message>
-  <if expr="is_android">
-  <message name="IDS_TRANSLATE_INFOBAR_ERROR_MOBILE" desc="Mobile: Translate Error message">
-    The translation to <ph name="target_language">$1<ex>German</ex></ph> failed.
-  </message>
-  </if>
 
 </grit-part>
diff --git a/components/webcrypto/PRESUBMIT.py b/components/webcrypto/PRESUBMIT.py
deleted file mode 100644
index ec245acd..0000000
--- a/components/webcrypto/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2014 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.
-
-"""Presubmit script for WebCrypto (chromium-side).
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 129396c..934bac4 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -220,7 +220,7 @@
 
 #endif  // OS_POSIX
 
-void CommonSubprocessInit(const std::string& process_type) {
+void CommonSubprocessInit() {
 #if defined(OS_WIN)
   // HACK: Let Windows know that we have started.  This is needed to suppress
   // the IDC_APPSTARTING cursor from being displayed for a prolonged period
@@ -241,18 +241,10 @@
   setlocale(LC_NUMERIC, "C");
 #endif
 
-#if !defined(OFFICIAL_BUILD)
-  // Print stack traces to stderr when crashes occur. This opens up security
-  // holes so it should never be enabled for official builds.
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableInProcessStackTraces)) {
-    base::debug::EnableInProcessStackDumping();
-  }
-#if defined(OS_WIN)
+#if !defined(OFFICIAL_BUILD) && defined(OS_WIN)
   base::RouteStdioToConsole(false);
   LoadLibraryA("dbghelp.dll");
 #endif
-#endif
 }
 
 class ContentClientInitializer {
@@ -756,11 +748,28 @@
 #endif  // OS_POSIX && !OS_MACOSX
 #endif  // V8_USE_EXTERNAL_STARTUP_DATA
 
+#if !defined(OFFICIAL_BUILD)
+#if defined(OS_WIN)
+    bool should_enable_stack_dump = !process_type.empty();
+#else
+    bool should_enable_stack_dump = true;
+#endif
+    // Print stack traces to stderr when crashes occur. This opens up security
+    // holes so it should never be enabled for official builds. This needs to
+    // happen before crash reporting is initialized (which for chrome happens in
+    // the call to PreSandboxStartup() on the delegate below), because otherwise
+    // this would interfere with signal handlers used by crash reporting.
+    if (should_enable_stack_dump && !command_line.HasSwitch(
+            switches::kDisableInProcessStackTraces)) {
+      base::debug::EnableInProcessStackDumping();
+    }
+#endif  // !defined(OFFICIAL_BUILD)
+
     if (delegate_)
       delegate_->PreSandboxStartup();
 
     if (!process_type.empty())
-      CommonSubprocessInit(process_type);
+      CommonSubprocessInit();
 
 #if defined(OS_WIN)
     CHECK(InitializeSandbox(params.sandbox_info));
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index ee3c5e6..d42b36b6 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -105,7 +105,7 @@
     "//printing/features",
     "//services/catalog/public/interfaces:constants",
     "//services/device:lib",
-    "//services/device/public/interfaces",
+    "//services/device/public/interfaces:constants",
     "//services/file:lib",
     "//services/file/public/interfaces",
     "//services/service_manager",
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 9d97ff3..4b5bbdf0 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -419,8 +419,6 @@
     const gfx::SizeF& viewport_size,
     const float top_controls_height,
     const float top_controls_shown_ratio,
-    const float bottom_controls_height,
-    const float bottom_controls_shown_ratio,
     bool is_mobile_optimized_hint,
     const gfx::SelectionBound& selection_start) {
   JNIEnv* env = AttachCurrentThread();
@@ -450,20 +448,11 @@
       page_scale_factor_limits.x(), page_scale_factor_limits.y(),
       content_size.width(), content_size.height(), viewport_size.width(),
       viewport_size.height(), top_controls_height, top_controls_shown_ratio,
-      bottom_controls_height, bottom_controls_shown_ratio,
       is_mobile_optimized_hint, has_insertion_marker,
       is_insertion_marker_visible, insertion_marker_horizontal,
       insertion_marker_top, insertion_marker_bottom);
 }
 
-void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
-    return;
-  Java_ContentViewCore_onBackgroundColorChanged(env, obj, color);
-}
-
 void ContentViewCoreImpl::ShowSelectPopupMenu(
     RenderFrameHost* frame,
     const gfx::Rect& bounds,
@@ -653,18 +642,6 @@
                                       y_dip);
 }
 
-void ContentViewCoreImpl::StartContentIntent(const GURL& content_url,
-                                             bool is_main_frame) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
-  if (j_obj.is_null())
-    return;
-  ScopedJavaLocalRef<jstring> jcontent_url =
-      ConvertUTF8ToJavaString(env, content_url.spec());
-  Java_ContentViewCore_startContentIntent(env, j_obj, jcontent_url,
-                                          is_main_frame);
-}
-
 void ContentViewCoreImpl::ShowDisambiguationPopup(
     const gfx::Rect& rect_pixels,
     const SkBitmap& zoomed_bitmap) {
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index 603fd441..7973a15 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -307,8 +307,6 @@
                        const gfx::SizeF& viewport_size,
                        const float top_controls_height,
                        const float top_controls_shown_ratio,
-                       const float bottom_controls_height,
-                       const float bottom_controls_shown_ratio,
                        bool is_mobile_optimized_hint,
                        const gfx::SelectionBound& selection_start);
 
@@ -324,7 +322,6 @@
                         int composition_end,
                         bool show_ime_if_needed,
                         bool reply_to_request);
-  void OnBackgroundColorChanged(SkColor color);
 
   bool HasFocus();
   void RequestDisallowInterceptTouchEvent();
@@ -336,8 +333,6 @@
                         const gfx::PointF& selection_anchor,
                         const gfx::RectF& selection_rect);
 
-  void StartContentIntent(const GURL& content_url, bool is_main_frame);
-
   // Shows the disambiguation popup
   // |rect_pixels|   --> window coordinates which |zoomed_bitmap| represents
   // |zoomed_bitmap| --> magnified image of potential touch targets
diff --git a/content/browser/background_sync/PRESUBMIT.py b/content/browser/background_sync/PRESUBMIT.py
deleted file mode 100644
index 192a8c4..0000000
--- a/content/browser/background_sync/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for src/content/browser/background_sync/
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/browser/bluetooth/PRESUBMIT.py b/content/browser/bluetooth/PRESUBMIT.py
deleted file mode 100644
index 3f9babe..0000000
--- a/content/browser/bluetooth/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/browser/cache_storage/PRESUBMIT.py b/content/browser/cache_storage/PRESUBMIT.py
deleted file mode 100644
index fdfe054..0000000
--- a/content/browser/cache_storage/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for cache_storage.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/browser/dom_storage/dom_storage_browsertest.cc b/content/browser/dom_storage/dom_storage_browsertest.cc
index 326c91e9..106834e 100644
--- a/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -3,8 +3,12 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
+#include "content/browser/dom_storage/local_storage_context_mojo.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/dom_storage/dom_storage_types.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
@@ -43,6 +47,24 @@
     ContentBrowserTest::SetUpCommandLine(command_line);
     command_line->AppendSwitch(switches::kMojoLocalStorage);
   }
+
+  void Flush() {
+    // First make sure a connection to the database was set up.
+    LocalStorageContextMojo* context =
+        static_cast<DOMStorageContextWrapper*>(
+            BrowserContext::GetDefaultStoragePartition(
+                shell()->web_contents()->GetBrowserContext())
+                ->GetDOMStorageContext())
+            ->mojo_state_.get();
+    base::RunLoop run_loop;
+    context->RunWhenConnected(run_loop.QuitClosure());
+    run_loop.Run();
+    // Then process any tasks that are currently queued, to ensure
+    // LevelDBWrapperImpl methods get called.
+    base::RunLoop().RunUntilIdle();
+    // And finally flush all the now queued up changes to leveldb.
+    context->Flush();
+  }
 };
 
 static const bool kIncognito = true;
@@ -56,6 +78,20 @@
   SimpleTest(GetTestUrl("dom_storage", "sanity_check.html"), kIncognito);
 }
 
+IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, PRE_DataPersists) {
+  SimpleTest(GetTestUrl("dom_storage", "store_data.html"), kNotIncognito);
+}
+
+// http://crbug.com/654704 PRE_ tests aren't supported on Android.
+#if defined(OS_ANDROID)
+#define MAYBE_DataPersists DISABLED_DataPersists
+#else
+#define MAYBE_DataPersists DataPersists
+#endif
+IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, MAYBE_DataPersists) {
+  SimpleTest(GetTestUrl("dom_storage", "verify_data.html"), kNotIncognito);
+}
+
 IN_PROC_BROWSER_TEST_F(MojoDOMStorageBrowserTest, SanityCheck) {
   SimpleTest(GetTestUrl("dom_storage", "sanity_check.html"), kNotIncognito);
 }
@@ -64,4 +100,13 @@
   SimpleTest(GetTestUrl("dom_storage", "sanity_check.html"), kIncognito);
 }
 
+IN_PROC_BROWSER_TEST_F(MojoDOMStorageBrowserTest, PRE_DataPersists) {
+  SimpleTest(GetTestUrl("dom_storage", "store_data.html"), kNotIncognito);
+  Flush();
+}
+
+IN_PROC_BROWSER_TEST_F(MojoDOMStorageBrowserTest, MAYBE_DataPersists) {
+  SimpleTest(GetTestUrl("dom_storage", "verify_data.html"), kNotIncognito);
+}
+
 }  // namespace content
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.cc b/content/browser/dom_storage/dom_storage_context_wrapper.cc
index c2023a6a..866cd8a2 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -134,7 +134,7 @@
         connector, context_->task_runner(),
         data_path.empty() ? data_path
                           : data_path.AppendASCII(kLocalStorageDirectory),
-        base::FilePath() /* storage_dir */));
+        storage_dir));
   }
 
   if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.h b/content/browser/dom_storage/dom_storage_context_wrapper.h
index 14efb451..332869f0 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -81,6 +81,7 @@
   friend class DOMStorageMessageFilter;  // for access to context()
   friend class SessionStorageNamespaceImpl;  // ditto
   friend class base::RefCountedThreadSafe<DOMStorageContextWrapper>;
+  friend class MojoDOMStorageBrowserTest;
 
   ~DOMStorageContextWrapper() override;
   DOMStorageContextImpl* context() const { return context_.get(); }
diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc
index 240958579..904a8e54 100644
--- a/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -271,6 +271,11 @@
 }
 
 void LocalStorageContextMojo::Flush() {
+  if (connection_state_ != CONNECTION_FINISHED) {
+    RunWhenConnected(base::BindOnce(&LocalStorageContextMojo::Flush,
+                                    weak_ptr_factory_.GetWeakPtr()));
+    return;
+  }
   for (const auto& it : level_db_wrappers_)
     it.second->level_db_wrapper()->ScheduleImmediateCommit();
 }
diff --git a/content/browser/dom_storage/local_storage_context_mojo.h b/content/browser/dom_storage/local_storage_context_mojo.h
index 98e8dc9..9099750 100644
--- a/content/browser/dom_storage/local_storage_context_mojo.h
+++ b/content/browser/dom_storage/local_storage_context_mojo.h
@@ -48,6 +48,8 @@
   leveldb::mojom::LevelDBDatabaseAssociatedRequest DatabaseRequestForTesting();
 
  private:
+  friend class MojoDOMStorageBrowserTest;
+
   class LevelDBWrapperHolder;
 
   // Runs |callback| immediately if already connected to a database, otherwise
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc
index 7b18af8ef..699f771d 100644
--- a/content/browser/download/download_request_core.cc
+++ b/content/browser/download/download_request_core.cc
@@ -37,6 +37,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/upload_bytes_element_reader.h"
+#include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_request_context.h"
@@ -158,19 +159,23 @@
   bool has_last_modified = !params->last_modified().empty();
   bool has_etag = !params->etag().empty();
 
-  // If we've asked for a range, we want to make sure that we only get that
-  // range if our current copy of the information is good.  We shouldn't be
-  // asked to continue if we don't have a verifier.
-  DCHECK(params->offset() == 0 || has_etag || has_last_modified);
+  // Strong validator(i.e. etag or last modified) is required in range requests
+  // for download resumption and parallel download.
+  DCHECK((params->offset() == 0 &&
+          params->length() == DownloadSaveInfo::kLengthFullContent) ||
+         has_etag || has_last_modified);
 
-  // If we're not at the beginning of the file, retrieve only the remaining
-  // portion.
-  if (params->offset() > 0 && (has_etag || has_last_modified)) {
+  // Add "Range" and "If-Range" request header fields if the range request is to
+  // retrieve bytes from {offset} to the end of the file.
+  // E.g. "Range:bytes=50-".
+  if (params->offset() > 0 &&
+      params->length() == DownloadSaveInfo::kLengthFullContent &&
+      (has_etag || has_last_modified)) {
     request->SetExtraRequestHeaderByName(
-        "Range", base::StringPrintf("bytes=%" PRId64 "-", params->offset()),
-        true);
+        net::HttpRequestHeaders::kRange,
+        base::StringPrintf("bytes=%" PRId64 "-", params->offset()), true);
 
-    // In accordance with RFC 2616 Section 14.27, use If-Range to specify that
+    // In accordance with RFC 7233 Section 3.2, use If-Range to specify that
     // the server return the entire entity if the validator doesn't match.
     // Last-Modified can be used in the absence of ETag as a validator if the
     // response headers satisfied the HttpUtil::HasStrongValidators() predicate.
@@ -178,7 +183,32 @@
     // This function assumes that HasStrongValidators() was true and that the
     // ETag and Last-Modified header values supplied are valid.
     request->SetExtraRequestHeaderByName(
-        "If-Range", has_etag ? params->etag() : params->last_modified(), true);
+        net::HttpRequestHeaders::kIfRange,
+        has_etag ? params->etag() : params->last_modified(), true);
+  }
+
+  // Add "Range", "If-Match", and "If-Unmodified-Since" for range requests with
+  // last byte position specified. e.g. "Range:bytes=50-59". If the file is
+  // updated on the server, we should get http 412 response code.
+  if (params->length() != DownloadSaveInfo::kLengthFullContent &&
+      (has_etag || has_last_modified)) {
+    request->SetExtraRequestHeaderByName(
+        net::HttpRequestHeaders::kRange,
+        base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(),
+                           params->offset() + params->length() - 1),
+        true);
+    if (has_etag) {
+      request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kIfMatch,
+                                           params->etag(), true);
+    }
+    // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for
+    // old servers that didn't implement "If-Match" and must be ignored when
+    // "If-Match" presents.
+    if (has_last_modified) {
+      request->SetExtraRequestHeaderByName(
+          net::HttpRequestHeaders::kIfUnmodifiedSince, params->last_modified(),
+          true);
+    }
   }
 
   // Downloads are treated as top level navigations. Hence the first-party
@@ -304,7 +334,7 @@
   const net::HttpResponseHeaders* headers = request()->response_headers();
   if (headers) {
     if (headers->HasStrongValidators()) {
-      // If we don't have strong validators as per RFC 2616 section 13.3.3, then
+      // If we don't have strong validators as per RFC 7232 section 2, then
       // we neither store nor use them for range requests.
       if (!headers->EnumerateHeader(nullptr, "Last-Modified",
                                     &create_info->last_modified))
@@ -545,7 +575,7 @@
 
     case net::HTTP_CREATED:
     case net::HTTP_ACCEPTED:
-      // Per RFC 2616 the entity being transferred is metadata about the
+      // Per RFC 7231 the entity being transferred is metadata about the
       // resource at the target URL and not the resource at that URL (or the
       // resource that would be at the URL once processing is completed in the
       // case of HTTP_ACCEPTED). However, we currently don't have special
@@ -555,7 +585,7 @@
 
     case net::HTTP_NO_CONTENT:
     case net::HTTP_RESET_CONTENT:
-    // These two status codes don't have an entity (or rather RFC 2616
+    // These two status codes don't have an entity (or rather RFC 7231
     // requires that there be no entity). They are treated the same as the
     // resource not being found since there is no entity to download.
 
@@ -580,16 +610,25 @@
     default:  // All other errors.
       // Redirection and informational codes should have been handled earlier
       // in the stack.
+      // TODO(xingliu): Handle HTTP_PRECONDITION_FAILED and resurrect
+      // DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION for range requests.
+      // This will change extensions::api::download::InterruptReason.
       DCHECK_NE(3, http_headers.response_code() / 100);
       DCHECK_NE(1, http_headers.response_code() / 100);
       return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
   }
 
-  if (save_info && save_info->offset > 0) {
-    // The caller is expecting a partial response.
-
+  // The caller is expecting a partial response.
+  if (save_info && (save_info->offset > 0 || save_info->length > 0)) {
     if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) {
-      // Requested a partial range, but received the entire response.
+      // Server should send partial content when "If-Match" or
+      // "If-Unmodified-Since" check passes, and the range request header has
+      // last byte position. e.g. "Range:bytes=50-99".
+      if (save_info->length != DownloadSaveInfo::kLengthFullContent)
+        return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+
+      // Requested a partial range, but received the entire response, when
+      // the range request header is "Range:bytes={offset}-".
       save_info->offset = 0;
       save_info->hash_of_partial_file.clear();
       save_info->hash_state.reset();
@@ -603,7 +642,9 @@
       return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
     DCHECK_GE(first_byte, 0);
 
-    if (first_byte != save_info->offset) {
+    if (first_byte != save_info->offset ||
+        (save_info->length > 0 &&
+         last_byte != save_info->offset + save_info->length - 1)) {
       // The server returned a different range than the one we requested. Assume
       // the response is bad.
       //
diff --git a/content/browser/download/download_request_core_unittest.cc b/content/browser/download/download_request_core_unittest.cc
new file mode 100644
index 0000000..71e45c2
--- /dev/null
+++ b/content/browser/download/download_request_core_unittest.cc
@@ -0,0 +1,140 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "content/browser/download/download_item_impl.h"
+#include "content/browser/download/download_request_core.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_url_parameters.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/http/http_request_headers.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class DownloadRequestCoreTest : public testing::Test {
+ public:
+  std::unique_ptr<DownloadUrlParameters> BuildDownloadParameters(
+      const std::string& url) const {
+    GURL gurl(url);
+    return base::MakeUnique<DownloadUrlParameters>(
+        gurl, request_context_getter_.get());
+  }
+
+  void CheckRequestHeaders(const std::string& name,
+                           const std::string& expected_header_value) const {
+    DCHECK(url_request_.get());
+    std::string header_value;
+    url_request_->extra_request_headers().GetHeader(name, &header_value);
+    EXPECT_EQ(expected_header_value, header_value);
+  }
+
+  bool HasRequestHeader(const std::string& name) {
+    DCHECK(url_request_.get());
+    return url_request_->extra_request_headers().HasHeader(name);
+  }
+
+  void CreateRequestOnIOThread(DownloadUrlParameters* params) {
+    url_request_ = DownloadRequestCore::CreateRequestOnIOThread(
+        DownloadItem::kInvalidId, params);
+    DCHECK(url_request_.get());
+  }
+
+  void SetUp() override {
+    request_context_getter_ = new net::TestURLRequestContextGetter(
+        content::BrowserThread::GetTaskRunnerForThread(
+            content::BrowserThread::UI));
+  }
+
+  void TearDown() override {
+    // URLRequest must be released before |request_context_getter_| gets
+    // destroyed.
+    url_request_.reset();
+  }
+
+  std::unique_ptr<net::URLRequest> url_request_;
+
+  // Used to test functions run on particular browser thread.
+  content::TestBrowserThreadBundle browser_threads_;
+  scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+};
+
+// Ensure "Range" header is built correctly for normal download.
+TEST_F(DownloadRequestCoreTest, BuildRangeRequest) {
+  std::unique_ptr<DownloadUrlParameters> params =
+      BuildDownloadParameters("example.com");
+
+  // Check initial states.
+  EXPECT_EQ(DownloadSaveInfo::kLengthFullContent, params->length());
+  EXPECT_EQ(0, params->offset());
+
+  // Non-range request.
+  CreateRequestOnIOThread(params.get());
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kRange));
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfRange));
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfMatch));
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfUnmodifiedSince));
+  url_request_.reset();
+
+  // Range request with header "Range:bytes=50-99", and etag.
+  params->set_etag("123");
+  params->set_offset(50);
+  params->set_length(50);
+  CreateRequestOnIOThread(params.get());
+  CheckRequestHeaders(net::HttpRequestHeaders::kRange, "bytes=50-99");
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfRange));
+  CheckRequestHeaders(net::HttpRequestHeaders::kIfMatch, "123");
+  CheckRequestHeaders(net::HttpRequestHeaders::kIfUnmodifiedSince, "");
+  url_request_.reset();
+
+  // Range request with header "Range:bytes=0-49" and last modified time.
+  std::string last_modified_time = "Tue, 15 Nov 1994 12:45:26 GMT";
+  params->set_etag("");
+  params->set_last_modified(last_modified_time);
+  params->set_offset(0);
+  params->set_length(50);
+  CreateRequestOnIOThread(params.get());
+  CheckRequestHeaders(net::HttpRequestHeaders::kRange, "bytes=0-49");
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfRange));
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfMatch));
+  CheckRequestHeaders(net::HttpRequestHeaders::kIfUnmodifiedSince,
+                      last_modified_time);
+  url_request_.reset();
+
+  // Range request with header "Range:bytes=10-59" and includes both etag and
+  // last modified time.
+  params->set_etag("123");
+  params->set_last_modified(last_modified_time);
+  params->set_offset(10);
+  params->set_length(50);
+  CreateRequestOnIOThread(params.get());
+  CheckRequestHeaders(net::HttpRequestHeaders::kRange, "bytes=10-59");
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfRange));
+  CheckRequestHeaders(net::HttpRequestHeaders::kIfMatch, "123");
+  CheckRequestHeaders(net::HttpRequestHeaders::kIfUnmodifiedSince,
+                      last_modified_time);
+  url_request_.reset();
+}
+
+// Ensure "Range" header is built correctly for download resumption.
+// Notice download resumption requires strong validator(i.e. etag or
+// last-modified).
+TEST_F(DownloadRequestCoreTest, BuildRangeRequestWithoutLength) {
+  std::unique_ptr<DownloadUrlParameters> params =
+      BuildDownloadParameters("example.com");
+  params->set_etag("123");
+  params->set_offset(50);
+  CreateRequestOnIOThread(params.get());
+  CheckRequestHeaders(net::HttpRequestHeaders::kRange, "bytes=50-");
+  CheckRequestHeaders(net::HttpRequestHeaders::kIfRange, "123");
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfMatch));
+  EXPECT_FALSE(HasRequestHeader(net::HttpRequestHeaders::kIfUnmodifiedSince));
+  url_request_.reset();
+}
+
+}  // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index 4ec94a66..26591467 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -389,9 +389,10 @@
   navigation_request_ = std::move(navigation_request);
   render_manager()->DidCreateNavigationRequest(navigation_request_.get());
 
-  // TODO(fdegans): Check if this is a same-document navigation and set the
-  // proper argument.
-  DidStartLoading(true, was_previously_loading);
+  bool to_different_document = !FrameMsg_Navigate_Type::IsSameDocument(
+      navigation_request_->common_params().navigation_type);
+
+  DidStartLoading(to_different_document, was_previously_loading);
 }
 
 void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
diff --git a/content/browser/frame_host/interstitial_page_navigator_impl.cc b/content/browser/frame_host/interstitial_page_navigator_impl.cc
index f015698..045d3f9 100644
--- a/content/browser/frame_host/interstitial_page_navigator_impl.cc
+++ b/content/browser/frame_host/interstitial_page_navigator_impl.cc
@@ -49,8 +49,8 @@
     RenderFrameHostImpl* render_frame_host,
     const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params,
     std::unique_ptr<NavigationHandleImpl> navigation_handle) {
-  navigation_handle->DidCommitNavigation(input_params, false, GURL(),
-                                         render_frame_host);
+  navigation_handle->DidCommitNavigation(
+      input_params, false, GURL(), NAVIGATION_TYPE_NEW_PAGE, render_frame_host);
   navigation_handle.reset();
 
   // TODO(nasko): Move implementation here, but for the time being call out
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index d361fef..deb886a 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -22,13 +22,13 @@
 #include "content/browser/frame_host/frame_navigation_entry.h"
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/frame_messages.h"
 #include "content/common/page_state_serialization.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/browser/resource_dispatcher_host_delegate.h"
@@ -578,9 +578,9 @@
       : WebContentsObserver(web_contents) {}
 
  private:
-  void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
-                           const LoadCommittedDetails& details,
-                           const FrameNavigateParams& params) override {
+  void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+    if (!navigation_handle->HasCommitted())
+      return;
     FAIL() << "No navigations should occur";
   }
 };
@@ -608,36 +608,43 @@
     message_loop_runner_->Run();
   }
 
-  const FrameNavigateParams& params() const {
-    EXPECT_EQ(1U, params_.size());
-    return params_[0];
+  ui::PageTransition transition() {
+    EXPECT_EQ(1U, transitions_.size());
+    return transitions_[0];
   }
 
-  const std::vector<FrameNavigateParams>& all_params() const {
-    return params_;
+  NavigationType navigation_type() {
+    EXPECT_EQ(1U, navigation_types_.size());
+    return navigation_types_[0];
   }
 
-  const LoadCommittedDetails& details() const {
-    EXPECT_EQ(1U, details_.size());
-    return details_[0];
+  bool is_in_page() {
+    EXPECT_EQ(1U, is_in_pages_.size());
+    return is_in_pages_[0];
   }
 
-  const std::vector<LoadCommittedDetails>& all_details() const {
-    return details_;
+  const std::vector<ui::PageTransition>& transitions() { return transitions_; }
+  const std::vector<GURL>& urls() { return urls_; }
+  const std::vector<NavigationType>& navigation_types() {
+    return navigation_types_;
   }
+  const std::vector<bool>& is_in_pages() { return is_in_pages_; }
 
  private:
-  void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
-                           const LoadCommittedDetails& details,
-                           const FrameNavigateParams& params) override {
-    RenderFrameHostImpl* rfh =
-        static_cast<RenderFrameHostImpl*>(render_frame_host);
-    if (rfh->frame_tree_node()->frame_tree_node_id() != frame_tree_node_id_)
+  void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+    if (!navigation_handle->HasCommitted())
+      return;
+
+    if (navigation_handle->GetFrameTreeNodeId() != frame_tree_node_id_)
       return;
 
     --navigations_remaining_;
-    params_.push_back(params);
-    details_.push_back(details);
+    transitions_.push_back(navigation_handle->GetPageTransition());
+    urls_.push_back(navigation_handle->GetURL());
+    navigation_types_.push_back(
+        static_cast<NavigationHandleImpl*>(navigation_handle)
+            ->navigation_type());
+    is_in_pages_.push_back(navigation_handle->IsSamePage());
     if (!navigations_remaining_ &&
         (!web_contents()->IsLoading() || !wait_for_load_))
       message_loop_runner_->Quit();
@@ -657,11 +664,10 @@
   // Whether to also wait for the load to complete.
   bool wait_for_load_;
 
-  // The params of the navigations.
-  std::vector<FrameNavigateParams> params_;
-
-  // The details of the navigations.
-  std::vector<LoadCommittedDetails> details_;
+  std::vector<ui::PageTransition> transitions_;
+  std::vector<GURL> urls_;
+  std::vector<NavigationType> navigation_types_;
+  std::vector<bool> is_in_pages_;
 
   // The MessageLoopRunner used to spin the message loop.
   scoped_refptr<MessageLoopRunner> message_loop_runner_;
@@ -916,7 +922,7 @@
     FrameNavigateParamsCapturer capturer(root);
     NavigateFrameToURL(root, error_url);
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
     NavigationEntry* entry = controller.GetLastCommittedEntry();
     EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
     EXPECT_EQ(2, controller.GetEntryCount());
@@ -931,7 +937,7 @@
     FrameNavigateParamsCapturer capturer(root);
     NavigateFrameToURL(root, error_url);
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
     NavigationEntry* entry = controller.GetLastCommittedEntry();
     EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
     EXPECT_EQ(2, controller.GetEntryCount());
@@ -949,7 +955,7 @@
     FrameNavigateParamsCapturer capturer(root);
     RendererLocationReplace(shell(), error_url);
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
     NavigationEntry* entry = controller.GetLastCommittedEntry();
     EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
     EXPECT_EQ(3, controller.GetEntryCount());
@@ -967,7 +973,7 @@
     FrameNavigateParamsCapturer capturer(root);
     RendererLocationReplace(shell(), error_url);
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
     NavigationEntry* entry = controller.GetLastCommittedEntry();
     EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
     EXPECT_EQ(4, controller.GetEntryCount());
@@ -997,9 +1003,9 @@
     // TODO(avi,creis): Why is this (and quite a few others below) a "link"
     // transition? Lots of these transitions should be cleaned up.
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1009,9 +1015,9 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   {
@@ -1021,9 +1027,9 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1035,11 +1041,11 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1050,11 +1056,11 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   if (AreAllSitesIsolatedForTesting()) {
@@ -1066,11 +1072,11 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 }
 
@@ -1095,12 +1101,12 @@
     shell()->web_contents()->GetController().GoBack();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1109,12 +1115,12 @@
     shell()->web_contents()->GetController().GoForward();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1123,12 +1129,12 @@
     EXPECT_TRUE(ExecuteScript(root, "history.back()"));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1137,12 +1143,12 @@
     EXPECT_TRUE(ExecuteScript(root, "history.forward()"));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1151,12 +1157,12 @@
     EXPECT_TRUE(ExecuteScript(root, "history.go(-1)"));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1165,12 +1171,12 @@
     EXPECT_TRUE(ExecuteScript(root, "history.go(1)"));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1179,9 +1185,9 @@
     shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_RELOAD));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_RELOAD));
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1190,11 +1196,11 @@
     EXPECT_TRUE(ExecuteScript(root, "location.reload()"));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   {
@@ -1208,11 +1214,11 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   // Now, various in-page navigations.
@@ -1225,11 +1231,11 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   // Back and forward across a fragment navigation.
@@ -1247,12 +1253,12 @@
     shell()->web_contents()->GetController().GoBack();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   {
@@ -1261,11 +1267,11 @@
     shell()->web_contents()->GetController().GoForward();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_FORWARD_BACK)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   // Back and forward across a pushState-created navigation.
@@ -1281,12 +1287,12 @@
     shell()->web_contents()->GetController().GoBack();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
                                   ui::PAGE_TRANSITION_FORWARD_BACK |
                                   ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   {
@@ -1295,11 +1301,11 @@
     shell()->web_contents()->GetController().GoForward();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_FORWARD_BACK)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 }
 
@@ -1323,8 +1329,8 @@
     NavigateFrameToURL(root, frame_url);
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, capturer.navigation_type());
   }
 }
 
@@ -1368,8 +1374,8 @@
     NavigateFrameToURL(root, GURL());
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
   }
 }
 
@@ -1408,8 +1414,8 @@
     NavigateFrameToURL(root->child_at(0), frame_url);
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -1418,8 +1424,8 @@
     shell()->web_contents()->GetController().GoBack();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -1428,8 +1434,8 @@
     shell()->web_contents()->GetController().GoForward();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -1440,8 +1446,8 @@
     NavigateFrameToURL(root->child_at(0), frame_url);
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -1451,8 +1457,8 @@
     EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -1464,8 +1470,8 @@
     EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -1488,8 +1494,8 @@
     EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -1547,18 +1553,16 @@
     NavigateFrameToURL(root, frame_url);
     capturer.Wait();
 
-    std::vector<FrameNavigateParams> params = capturer.all_params();
-    std::vector<LoadCommittedDetails> details = capturer.all_details();
-    ASSERT_EQ(2U, params.size());
-    ASSERT_EQ(2U, details.size());
+    ASSERT_EQ(2U, capturer.transitions().size());
+    ASSERT_EQ(2U, capturer.navigation_types().size());
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        params[0].transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, details[0].type);
+        capturer.transitions()[0], ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_types()[0]);
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        params[1].transition,
+        capturer.transitions()[1],
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, details[1].type);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_types()[1]);
   }
 }
 
@@ -1583,9 +1587,9 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   {
@@ -1595,9 +1599,9 @@
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_LINK));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_LINK));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   // Second verse, same as the first. (But in a subframe.)
@@ -1622,9 +1626,9 @@
     EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   {
@@ -1634,9 +1638,9 @@
     EXPECT_TRUE(ExecuteScript(root->child_at(0), script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 }
 
@@ -1919,8 +1923,8 @@
     std::string script = "history.pushState({}, 'foo', 'foo')";
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   // 2. Create an iframe.
@@ -2211,8 +2215,8 @@
     NavigateFrameToURL(root->child_at(0), frame_url2);
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   // We should have created a new NavigationEntry with the same main frame URL.
@@ -2262,8 +2266,8 @@
       deleted_observer.WaitUntilDeleted();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   // We should have created a new NavigationEntry with the same main frame URL.
@@ -2298,8 +2302,8 @@
       deleted_observer.WaitUntilDeleted();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   // We should have created a new NavigationEntry with the same main frame URL.
@@ -2448,8 +2452,8 @@
     shell()->web_contents()->GetController().GoBack();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.navigation_type());
   }
   EXPECT_EQ(3, controller.GetEntryCount());
   EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -2465,8 +2469,8 @@
     shell()->web_contents()->GetController().GoBack();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.navigation_type());
   }
   EXPECT_EQ(3, controller.GetEntryCount());
   EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
@@ -2482,8 +2486,8 @@
     shell()->web_contents()->GetController().GoForward();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.navigation_type());
   }
   EXPECT_EQ(3, controller.GetEntryCount());
   EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -2499,8 +2503,8 @@
     shell()->web_contents()->GetController().GoForward();
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_AUTO_SUBFRAME));
-    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type);
+        capturer.transition(), ui::PAGE_TRANSITION_AUTO_SUBFRAME));
+    EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.navigation_type());
   }
   EXPECT_EQ(3, controller.GetEntryCount());
   EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
@@ -4056,9 +4060,9 @@
     controller.Reload(ReloadType::NORMAL, false);
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition, ui::PAGE_TRANSITION_RELOAD));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_FALSE(capturer.details().is_in_page);
+        capturer.transition(), ui::PAGE_TRANSITION_RELOAD));
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_FALSE(capturer.is_in_page());
   }
 
   // 4. Add the iframe again.
@@ -4382,8 +4386,8 @@
 
     // The fact that there was a pending entry shouldn't interfere with the
     // classification.
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   ResourceDispatcherHost::Get()->SetDelegate(nullptr);
@@ -4468,8 +4472,8 @@
     std::string script = "history.pushState({}, '', 'pushed')";
     EXPECT_TRUE(ExecuteScript(root, script));
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
-    EXPECT_TRUE(capturer.details().is_in_page);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.navigation_type());
+    EXPECT_TRUE(capturer.is_in_page());
   }
 
   // The in-page navigation should not have replaced the previous entry.
@@ -4549,7 +4553,7 @@
         "/navigation_controller/simple_page_2.html"));
     NavigateFrameToURL(root->child_at(0), frame_url);
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -4646,7 +4650,7 @@
         "/navigation_controller/simple_page_2.html"));
     NavigateFrameToURL(root->child_at(0), frame_url);
     capturer.Wait();
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.navigation_type());
   }
 
   {
@@ -4801,10 +4805,10 @@
     EXPECT_TRUE(ExecuteScript(shell(), script));
     capturer.Wait();
     EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
-        capturer.params().transition,
+        capturer.transition(),
         ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
                                   ui::PAGE_TRANSITION_CLIENT_REDIRECT)));
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.navigation_type());
   }
 
   // Modify an entry in the session history and reload the original request.
@@ -4832,9 +4836,9 @@
     capturer.set_wait_for_load(false);
     capturer.set_navigations_remaining(2);
     capturer.Wait();
-    EXPECT_EQ(2U, capturer.all_details().size());
-    EXPECT_EQ(modified_url, capturer.all_params()[0].url);
-    EXPECT_EQ(original_url, capturer.all_params()[1].url);
+    EXPECT_EQ(2U, capturer.urls().size());
+    EXPECT_EQ(modified_url, capturer.urls()[0]);
+    EXPECT_EQ(original_url, capturer.urls()[1]);
     EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
   }
 
@@ -6152,17 +6156,47 @@
   EXPECT_EQ(cross_origin_url, web_contents->GetLastCommittedURL());
   EXPECT_EQ(2, web_contents->GetController().GetLastCommittedEntryIndex());
 
-  // Wait for the back navigation to commit as well.
-  history_commit_observer.Wait();
-  EXPECT_EQ(start_url, web_contents->GetLastCommittedURL());
-  EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex());
+  if (IsBrowserSideNavigationEnabled()) {
+    // With browser-side-navigation, the history navigation is dropped.
+    EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+    EXPECT_EQ(2, web_contents->GetController().GetLastCommittedEntryIndex());
+    EXPECT_EQ(3, web_contents->GetController().GetEntryCount());
 
-  // Verify the expected origin through JavaScript. It also has the additional
-  // verification of the process also being still alive.
-  std::string origin;
-  EXPECT_TRUE(ExecuteScriptAndExtractString(
-      web_contents, "domAutomationController.send(document.origin)", &origin));
-  EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/");
+    // Verify the expected origin through JavaScript. It also has the additional
+    // verification of the process also being still alive.
+    std::string origin;
+    EXPECT_TRUE(ExecuteScriptAndExtractString(
+        web_contents, "domAutomationController.send(document.origin)",
+        &origin));
+    EXPECT_EQ(cross_origin_url.GetOrigin().spec(), origin + "/");
+
+    // Navigate back again.
+    web_contents->GetController().GoBack();
+    EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+    EXPECT_EQ(1, web_contents->GetController().GetLastCommittedEntryIndex());
+    EXPECT_EQ(3, web_contents->GetController().GetEntryCount());
+
+    // Verify the expected origin through JavaScript. It also has the additional
+    // verification of the process also being still alive.
+    EXPECT_TRUE(ExecuteScriptAndExtractString(
+        web_contents, "domAutomationController.send(document.origin)",
+        &origin));
+    EXPECT_EQ(same_page_url.GetOrigin().spec(), origin + "/");
+  } else {
+    // Wait for the back navigation to commit as well.
+    history_commit_observer.Wait();
+    EXPECT_EQ(start_url, web_contents->GetLastCommittedURL());
+    EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex());
+    EXPECT_EQ(3, web_contents->GetController().GetEntryCount());
+
+    // Verify the expected origin through JavaScript. It also has the additional
+    // verification of the process also being still alive.
+    std::string origin;
+    EXPECT_TRUE(ExecuteScriptAndExtractString(
+        web_contents, "domAutomationController.send(document.origin)",
+        &origin));
+    EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/");
+  }
 }
 
 // Test that verifies that Referer and Origin http headers are correctly sent
@@ -6279,10 +6313,10 @@
     void SetCallback(Callback callback) { callback_ = callback; }
 
    private:
-    void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
-                             const LoadCommittedDetails& details,
-                             const FrameNavigateParams& params) override {
+    void DidFinishNavigation(NavigationHandle* navigation_handle) override {
       DCHECK_CURRENTLY_ON(BrowserThread::UI);
+      if (!navigation_handle->HasCommitted())
+        return;
 
       // Resume the message.
       callback_.Run();
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 0abf640..c8b31922 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -23,6 +23,7 @@
 #include "content/browser/frame_host/frame_navigation_entry.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
 #include "content/browser/frame_host/navigation_request.h"
 #include "content/browser/frame_host/navigator.h"
 #include "content/browser/frame_host/navigator_impl.h"
@@ -32,7 +33,6 @@
 #include "content/common/frame_owner_properties.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/common/view_messages.h"
-#include "content/public/browser/navigation_details.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_view_host.h"
@@ -311,18 +311,36 @@
  public:
   // Observes navigation for the specified |web_contents|.
   explicit LoadCommittedDetailsObserver(WebContents* web_contents)
-      : WebContentsObserver(web_contents) {}
+      : WebContentsObserver(web_contents),
+        navigation_type_(NAVIGATION_TYPE_UNKNOWN),
+        is_in_page_(false),
+        is_main_frame_(false),
+        did_replace_entry_(false) {}
 
-  const LoadCommittedDetails& details() { return details_; }
+  NavigationType navigation_type() { return navigation_type_; }
+  const GURL& previous_url() { return previous_url_; }
+  bool is_in_page() { return is_in_page_; }
+  bool is_main_frame() { return is_main_frame_; }
+  bool did_replace_entry() { return did_replace_entry_; }
 
  private:
-  void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
-                           const LoadCommittedDetails& details,
-                           const FrameNavigateParams& params) override {
-    details_ = details;
+  void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+    if (!navigation_handle->HasCommitted())
+      return;
+
+    navigation_type_ = static_cast<NavigationHandleImpl*>(navigation_handle)
+                           ->navigation_type();
+    previous_url_ = navigation_handle->GetPreviousURL();
+    is_in_page_ = navigation_handle->IsSamePage();
+    is_main_frame_ = navigation_handle->IsInMainFrame();
+    did_replace_entry_ = navigation_handle->DidReplaceEntry();
   }
 
-  LoadCommittedDetails details_;
+  NavigationType navigation_type_;
+  GURL previous_url_;
+  bool is_in_page_;
+  bool is_main_frame_;
+  bool did_replace_entry_;
 };
 
 // PlzNavigate
@@ -2018,7 +2036,7 @@
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
 
-  EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.details().type);
+  EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.navigation_type());
   EXPECT_EQ(controller.GetEntryCount(), 1);
   EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
   EXPECT_TRUE(controller.GetLastCommittedEntry());
@@ -2086,7 +2104,7 @@
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
 
-  EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.details().type);
+  EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.navigation_type());
   EXPECT_EQ(controller.GetEntryCount(), 1);
   EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
   EXPECT_TRUE(controller.GetLastCommittedEntry());
@@ -2137,7 +2155,7 @@
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
 
-  EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, observer.details().type);
+  EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, observer.navigation_type());
   EXPECT_EQ(controller.GetEntryCount(), 1);
   EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
   EXPECT_TRUE(controller.GetLastCommittedEntry());
@@ -2197,7 +2215,7 @@
 
   main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&params);
-  EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, observer.details().type);
+  EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, observer.navigation_type());
 }
 
 // Tests navigation via link click within a subframe. A new navigation entry
@@ -2262,14 +2280,13 @@
   subframe->SendNavigateWithParams(&params);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
-  EXPECT_EQ(url1, observer.details().previous_url);
-  EXPECT_FALSE(observer.details().is_in_page);
-  EXPECT_FALSE(observer.details().is_main_frame);
+  EXPECT_EQ(url1, observer.previous_url());
+  EXPECT_FALSE(observer.is_in_page());
+  EXPECT_FALSE(observer.is_main_frame());
 
   // The new entry should be appended.
   NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
   EXPECT_EQ(2, controller.GetEntryCount());
-  EXPECT_EQ(entry, observer.details().entry);
 
   // New entry should refer to the new page, but the old URL (entries only
   // reflect the toplevel URL).
@@ -2631,7 +2648,11 @@
   self_params.should_update_history = false;
   self_params.gesture = NavigationGestureUser;
   self_params.method = "GET";
-  self_params.page_state = PageState::CreateFromURL(url1);
+  self_params.item_sequence_number = GenerateSequenceNumber();
+  self_params.document_sequence_number = GenerateSequenceNumber();
+  self_params.page_state = PageState::CreateForTestingWithSequenceNumbers(
+      url1, self_params.item_sequence_number,
+      self_params.document_sequence_number);
   self_params.was_within_same_page = true;
 
   LoadCommittedDetailsObserver observer(contents());
@@ -2641,8 +2662,8 @@
   NavigationEntry* entry1 = controller.GetLastCommittedEntry();
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
-  EXPECT_TRUE(observer.details().is_in_page);
-  EXPECT_TRUE(observer.details().did_replace_entry);
+  EXPECT_TRUE(observer.is_in_page());
+  EXPECT_TRUE(observer.did_replace_entry());
   EXPECT_EQ(1, controller.GetEntryCount());
 
   // Fragment navigation to a new page.
@@ -2655,31 +2676,30 @@
   params.should_update_history = false;
   params.gesture = NavigationGestureUser;
   params.method = "GET";
-  params.page_state = PageState::CreateFromURL(url2);
+  params.item_sequence_number = GenerateSequenceNumber();
+  params.document_sequence_number = self_params.document_sequence_number;
+  params.page_state = PageState::CreateForTestingWithSequenceNumbers(
+      url2, params.item_sequence_number, params.document_sequence_number);
   params.was_within_same_page = true;
 
   // This should generate a new entry.
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&params);
   NavigationEntry* entry2 = controller.GetLastCommittedEntry();
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
-  EXPECT_TRUE(observer.details().is_in_page);
-  EXPECT_FALSE(observer.details().did_replace_entry);
+  EXPECT_TRUE(observer.is_in_page());
+  EXPECT_FALSE(observer.did_replace_entry());
   EXPECT_EQ(2, controller.GetEntryCount());
 
   // Go back one.
-  FrameHostMsg_DidCommitProvisionalLoad_Params back_params(params);
+  FrameHostMsg_DidCommitProvisionalLoad_Params back_params(self_params);
   controller.GoBack();
-  back_params.url = url1;
   back_params.nav_entry_id = entry1->GetUniqueID();
   back_params.did_create_new_entry = false;
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&back_params);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
-  EXPECT_TRUE(observer.details().is_in_page);
+  EXPECT_TRUE(observer.is_in_page());
   EXPECT_EQ(2, controller.GetEntryCount());
   EXPECT_EQ(0, controller.GetCurrentEntryIndex());
   EXPECT_EQ(back_params.url, controller.GetVisibleEntry()->GetURL());
@@ -2687,14 +2707,12 @@
   // Go forward.
   FrameHostMsg_DidCommitProvisionalLoad_Params forward_params(params);
   controller.GoForward();
-  forward_params.url = url2;
   forward_params.nav_entry_id = entry2->GetUniqueID();
   forward_params.did_create_new_entry = false;
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&forward_params);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
-  EXPECT_TRUE(observer.details().is_in_page);
+  EXPECT_TRUE(observer.is_in_page());
   EXPECT_EQ(2, controller.GetEntryCount());
   EXPECT_EQ(1, controller.GetCurrentEntryIndex());
   EXPECT_EQ(forward_params.url,
@@ -2705,10 +2723,8 @@
   // one identified by an existing page ID. This would result in the second URL
   // losing the reference fragment when you navigate away from it and then back.
   controller.GoBack();
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&back_params);
   controller.GoForward();
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&forward_params);
   EXPECT_EQ(forward_params.url,
             controller.GetVisibleEntry()->GetURL());
@@ -2718,13 +2734,17 @@
   params.nav_entry_id = 0;
   params.did_create_new_entry = true;
   params.url = url3;
+  params.item_sequence_number = 0;
+  params.document_sequence_number = 0;
+  params.page_state = PageState::CreateFromURL(url3);
+  params.was_within_same_page = false;
   navigation_entry_committed_counter_ = 0;
   main_test_rfh()->SendRendererInitiatedNavigationRequest(url3, false);
   main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&params);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
-  EXPECT_FALSE(observer.details().is_in_page);
+  EXPECT_FALSE(observer.is_in_page());
   EXPECT_EQ(3, controller.GetEntryCount());
   EXPECT_EQ(2, controller.GetCurrentEntryIndex());
 }
@@ -2755,13 +2775,11 @@
 
   // This should NOT generate a new entry, nor prune the list.
   LoadCommittedDetailsObserver observer(contents());
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&params);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
-  EXPECT_TRUE(observer.details().is_in_page);
-  EXPECT_TRUE(observer.details().did_replace_entry);
+  EXPECT_TRUE(observer.is_in_page());
+  EXPECT_TRUE(observer.did_replace_entry());
   EXPECT_EQ(1, controller.GetEntryCount());
 }
 
@@ -2809,13 +2827,11 @@
 
     // This should NOT generate a new entry, nor prune the list.
     LoadCommittedDetailsObserver observer(contents());
-    main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
-    main_test_rfh()->PrepareForCommit();
     main_test_rfh()->SendNavigateWithParams(&params);
     EXPECT_EQ(1U, navigation_entry_committed_counter_);
     navigation_entry_committed_counter_ = 0;
-    EXPECT_TRUE(observer.details().is_in_page);
-    EXPECT_TRUE(observer.details().did_replace_entry);
+    EXPECT_TRUE(observer.is_in_page());
+    EXPECT_TRUE(observer.did_replace_entry());
     EXPECT_EQ(2, controller.GetEntryCount());
   }
 
@@ -2841,7 +2857,7 @@
     main_test_rfh()->SendNavigateWithParams(&params);
     EXPECT_EQ(1U, navigation_entry_committed_counter_);
     navigation_entry_committed_counter_ = 0;
-    EXPECT_FALSE(observer.details().is_in_page);
+    EXPECT_FALSE(observer.is_in_page());
     EXPECT_EQ(3, controller.GetEntryCount());
   }
 
@@ -3408,8 +3424,6 @@
   controller.SetTransientEntry(std::move(transient_entry));
   EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL());
 
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(url3_ref, false);
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigate(0, false, url3_ref);
   // Transient entry should be gone.
   EXPECT_FALSE(controller.GetTransientEntry());
@@ -4965,8 +4979,6 @@
   params.url = kUrl2;
   params.page_state = PageState::CreateFromURL(kUrl2);
   params.was_within_same_page = true;
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
-  main_test_rfh()->PrepareForCommit();
   main_test_rfh()->SendNavigateWithParams(&params);
 
   // The title should immediately be visible on the new NavigationEntry.
@@ -5062,8 +5074,6 @@
   params.was_within_same_page = true;
   params.method = "GET";
   params.post_id = -1;
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(replace_url, false);
-  main_test_rfh()->PrepareForCommit();
   contents()->GetMainFrame()->SendNavigateWithParams(&params);
 
   // Now reload. replaceState overrides the POST, so we should not show a
@@ -5096,7 +5106,7 @@
     main_test_rfh()->SendNavigateWithParams(&params);
     EXPECT_EQ(PAGE_TYPE_ERROR,
               controller_impl().GetLastCommittedEntry()->GetPageType());
-    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, observer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, observer.navigation_type());
   }
 
   // Navigate to existing page.
@@ -5108,7 +5118,7 @@
     main_test_rfh()->SendNavigateWithParams(&params);
     EXPECT_EQ(PAGE_TYPE_ERROR,
               controller_impl().GetLastCommittedEntry()->GetPageType());
-    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, observer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, observer.navigation_type());
   }
 
   // Navigate to same page.
@@ -5124,7 +5134,7 @@
     main_test_rfh()->SendNavigateWithParams(&params);
     EXPECT_EQ(PAGE_TYPE_ERROR,
               controller_impl().GetLastCommittedEntry()->GetPageType());
-    EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.details().type);
+    EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.navigation_type());
   }
 
   // Navigate in page.
@@ -5133,12 +5143,10 @@
   params.was_within_same_page = true;
   {
     LoadCommittedDetailsObserver observer(contents());
-    main_test_rfh()->SendRendererInitiatedNavigationRequest(params.url, false);
-    main_test_rfh()->PrepareForCommit();
     main_test_rfh()->SendNavigateWithParams(&params);
     EXPECT_EQ(PAGE_TYPE_ERROR,
               controller_impl().GetLastCommittedEntry()->GetPageType());
-    EXPECT_TRUE(observer.details().is_in_page);
+    EXPECT_TRUE(observer.is_in_page());
   }
 }
 
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc
index b528804..04c07a467 100644
--- a/content/browser/frame_host/navigation_entry_impl.cc
+++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -702,7 +702,6 @@
 
 RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams(
     const FrameNavigationEntry& frame_entry,
-    bool is_same_document_history_load,
     bool is_history_navigation_in_new_child,
     const std::map<std::string, bool>& subframe_unique_names,
     bool has_committed_real_load,
@@ -735,7 +734,7 @@
 #endif
   RequestNavigationParams request_params(
       GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(),
-      frame_entry.page_state(), GetUniqueID(), is_same_document_history_load,
+      frame_entry.page_state(), GetUniqueID(),
       is_history_navigation_in_new_child, subframe_unique_names,
       has_committed_real_load, intended_as_new_entry, pending_offset_to_send,
       current_offset_to_send, current_length_to_send, IsViewSourceMode(),
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h
index 24cf6f370..96f7ef8 100644
--- a/content/browser/frame_host/navigation_entry_impl.h
+++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -186,7 +186,6 @@
   StartNavigationParams ConstructStartNavigationParams() const;
   RequestNavigationParams ConstructRequestNavigationParams(
       const FrameNavigationEntry& frame_entry,
-      bool is_same_document_history_load,
       bool is_history_navigation_in_new_child,
       const std::map<std::string, bool>& subframe_unique_names,
       bool has_committed_real_load,
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index fda35af..74e0b20 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -108,6 +108,7 @@
       is_stream_(false),
       started_from_context_menu_(started_from_context_menu),
       reload_type_(ReloadType::NONE),
+      navigation_type_(NAVIGATION_TYPE_UNKNOWN),
       weak_factory_(this) {
   DCHECK(!navigation_start.is_null());
   if (redirect_chain_.empty())
@@ -431,7 +432,8 @@
   params.page_state = PageState::CreateFromURL(url);
   params.contents_mime_type = std::string("text/html");
 
-  DidCommitNavigation(params, false, GURL(), render_frame_host_);
+  DidCommitNavigation(params, false, GURL(), NAVIGATION_TYPE_NEW_PAGE,
+                      render_frame_host_);
 }
 
 bool NavigationHandleImpl::WasStartedFromContextMenu() const {
@@ -603,7 +605,7 @@
   render_frame_host_ = render_frame_host;
   state_ = READY_TO_COMMIT;
 
-  if (!IsRendererDebugURL(url_))
+  if (!IsRendererDebugURL(url_) && !IsSamePage())
     GetDelegate()->ReadyToCommitNavigation(this);
 }
 
@@ -611,6 +613,7 @@
     const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
     bool did_replace_entry,
     const GURL& previous_url,
+    NavigationType navigation_type,
     RenderFrameHostImpl* render_frame_host) {
   DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
   DCHECK_EQ(frame_tree_node_, render_frame_host->frame_tree_node());
@@ -625,6 +628,7 @@
   previous_url_ = previous_url;
   base_url_ = params.base_url;
   socket_address_ = params.socket_address;
+  navigation_type_ = navigation_type;
 
   // If an error page reloads, net_error_code might be 200 but we still want to
   // count it as an error page.
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h
index 74b629e..3a46059 100644
--- a/content/browser/frame_host/navigation_handle_impl.h
+++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -24,6 +24,7 @@
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/navigation_data.h"
 #include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/navigation_type.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/common/request_context_type.h"
 #include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
@@ -289,6 +290,7 @@
       const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
       bool did_replace_entry,
       const GURL& previous_url,
+      NavigationType navigation_type,
       RenderFrameHostImpl* render_frame_host);
 
   // Called during commit. Takes ownership of the embedder's NavigationData
@@ -314,6 +316,11 @@
     searchable_form_encoding_ = encoding;
   }
 
+  NavigationType navigation_type() {
+    DCHECK_GE(state_, DID_COMMIT);
+    return navigation_type_;
+  }
+
   void set_response_headers_for_testing(
       scoped_refptr<net::HttpResponseHeaders> response_headers) {
     response_headers_ = response_headers;
@@ -481,6 +488,7 @@
   GURL previous_url_;
   GURL base_url_;
   net::HostPortPair socket_address_;
+  NavigationType navigation_type_;
 
   base::WeakPtrFactory<NavigationHandleImpl> weak_factory_;
 
diff --git a/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
index 988fcc9b..bdda508 100644
--- a/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -40,7 +40,8 @@
         was_redirected_(false),
         frame_tree_node_id_(-1),
         page_transition_(ui::PAGE_TRANSITION_LINK),
-        expected_start_url_(expected_start_url) {}
+        expected_start_url_(expected_start_url),
+        net_error_code_(net::OK) {}
 
   void DidStartNavigation(NavigationHandle* navigation_handle) override {
     if (handle_ || navigation_handle->GetURL() != expected_start_url_)
@@ -71,6 +72,7 @@
     DCHECK_EQ(frame_tree_node_id_, navigation_handle->GetFrameTreeNodeId());
 
     was_redirected_ = navigation_handle->WasServerRedirect();
+    net_error_code_ = navigation_handle->GetNetErrorCode();
 
     if (navigation_handle->HasCommitted()) {
       has_committed_ = true;
@@ -101,6 +103,8 @@
 
   ui::PageTransition page_transition() { return page_transition_; }
 
+  net::Error net_error_code() { return net_error_code_; }
+
  private:
   // A reference to the NavigationHandle so this class will track only
   // one navigation at a time. It is set at DidStartNavigation and cleared
@@ -117,6 +121,7 @@
   ui::PageTransition page_transition_;
   GURL expected_start_url_;
   GURL last_committed_url_;
+  net::Error net_error_code_;
 };
 
 // A test NavigationThrottle that will return pre-determined checks and run
@@ -847,6 +852,71 @@
   EXPECT_FALSE(installer.navigation_throttle());
 }
 
+// Checks that the error code is properly set on the NavigationHandle when a
+// NavigationThrottle cancels.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
+                       ErrorCodeOnThrottleCancelNavigation) {
+  const GURL kUrl = embedded_test_server()->GetURL("/title1.html");
+  const GURL kRedirectingUrl =
+      embedded_test_server()->GetURL("/server-redirect?" + kUrl.spec());
+
+  {
+    // Set up a NavigationThrottle that will cancel the navigation in
+    // WillStartRequest.
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::CANCEL_AND_IGNORE,
+        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), kUrl);
+
+    // Try to navigate to the url. The navigation should be canceled and the
+    // NavigationHandle should have the right error code.
+    EXPECT_FALSE(NavigateToURL(shell(), kUrl));
+    EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
+  }
+
+  {
+    // Set up a NavigationThrottle that will cancel the navigation in
+    // WillRedirectRequest.
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::PROCEED,
+        NavigationThrottle::CANCEL_AND_IGNORE, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), kRedirectingUrl);
+
+    // Try to navigate to the url. The navigation should be canceled and the
+    // NavigationHandle should have the right error code.
+    EXPECT_FALSE(NavigateToURL(shell(), kRedirectingUrl));
+    EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
+  }
+
+  {
+    // Set up a NavigationThrottle that will cancel the navigation in
+    // WillProcessResponse.
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::PROCEED,
+        NavigationThrottle::PROCEED, NavigationThrottle::CANCEL_AND_IGNORE);
+    NavigationHandleObserver observer(shell()->web_contents(), kUrl);
+
+    // Try to navigate to the url. The navigation should be canceled and the
+    // NavigationHandle should have the right error code.
+    EXPECT_FALSE(NavigateToURL(shell(), kUrl));
+    EXPECT_EQ(net::ERR_ABORTED, observer.net_error_code());
+  }
+
+  {
+    // Set up a NavigationThrottle that will block the navigation in
+    // WillStartRequest.
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::BLOCK_REQUEST,
+        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), kUrl);
+
+    // Try to navigate to the url. The navigation should be canceled and the
+    // NavigationHandle should have the right error code.
+    EXPECT_FALSE(NavigateToURL(shell(), kUrl));
+    EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, observer.net_error_code());
+  }
+}
+
 // Specialized test that verifies the NavigationHandle gets the HTTPS upgraded
 // URL from the very beginning of the navigation.
 class NavigationHandleImplHttpsUpgradeBrowserTest
@@ -910,4 +980,73 @@
   CheckHttpsUpgradedIframeNavigation(start_url, cross_site_iframe_secure_url);
 }
 
+// Ensure that browser-initiated same-document navigations are detected and
+// don't issue network requests.  See crbug.com/663777.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
+                       SamePageBrowserInitiatedNoReload) {
+  GURL url(embedded_test_server()->GetURL("/title1.html"));
+  GURL url_fragment_1(embedded_test_server()->GetURL("/title1.html#id_1"));
+  GURL url_fragment_2(embedded_test_server()->GetURL("/title1.html#id_2"));
+
+  // 1) Perform a new-document navigation.
+  {
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::PROCEED,
+        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), url);
+    EXPECT_TRUE(NavigateToURL(shell(), url));
+    EXPECT_EQ(1, installer.will_start_called());
+    EXPECT_EQ(1, installer.will_process_called());
+    EXPECT_FALSE(observer.is_same_page());
+  }
+
+  // 2) Perform a same-document navigation by adding a fragment.
+  {
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::PROCEED,
+        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), url_fragment_1);
+    EXPECT_TRUE(NavigateToURL(shell(), url_fragment_1));
+    EXPECT_EQ(0, installer.will_start_called());
+    EXPECT_EQ(0, installer.will_process_called());
+    EXPECT_TRUE(observer.is_same_page());
+  }
+
+  // 3) Perform a same-document navigation by modifying the fragment.
+  {
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::PROCEED,
+        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), url_fragment_2);
+    EXPECT_TRUE(NavigateToURL(shell(), url_fragment_2));
+    EXPECT_EQ(0, installer.will_start_called());
+    EXPECT_EQ(0, installer.will_process_called());
+    EXPECT_TRUE(observer.is_same_page());
+  }
+
+  // 4) Redo the last navigation, but this time it should trigger a reload.
+  {
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::PROCEED,
+        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), url_fragment_2);
+    EXPECT_TRUE(NavigateToURL(shell(), url_fragment_2));
+    EXPECT_EQ(1, installer.will_start_called());
+    EXPECT_EQ(1, installer.will_process_called());
+    EXPECT_FALSE(observer.is_same_page());
+  }
+
+  // 5) Perform a new-document navigation by removing the fragment.
+  {
+    TestNavigationThrottleInstaller installer(
+        shell()->web_contents(), NavigationThrottle::PROCEED,
+        NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+    NavigationHandleObserver observer(shell()->web_contents(), url);
+    EXPECT_TRUE(NavigateToURL(shell(), url));
+    EXPECT_EQ(1, installer.will_start_called());
+    EXPECT_EQ(1, installer.will_process_called());
+    EXPECT_FALSE(observer.is_same_page());
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 4b1bd89..4a0c7cec 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -72,12 +72,13 @@
       *load_flags |=
           net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
       break;
-    case FrameMsg_Navigate_Type::NORMAL:
+    case FrameMsg_Navigate_Type::SAME_DOCUMENT:
+    case FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT:
+    case FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT:
+    case FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT:
       if (is_post)
         *load_flags |= net::LOAD_VALIDATE_CACHE;
       break;
-    default:
-      break;
   }
 }
 
@@ -231,8 +232,7 @@
                             blink::WebMixedContentContextType::Blockable,
                             initiator),
       entry.ConstructRequestNavigationParams(
-          frame_entry, is_same_document_history_load,
-          is_history_navigation_in_new_child,
+          frame_entry, is_history_navigation_in_new_child,
           entry.GetSubframeUniqueNames(frame_tree_node),
           frame_tree_node->has_committed_real_load(),
           controller->GetPendingEntryIndex() == -1,
@@ -252,34 +252,42 @@
     const BeginNavigationParams& begin_params,
     int current_history_list_offset,
     int current_history_list_length) {
-  // TODO(clamy): Check if some PageState should be provided here.
+  // Only normal navigations to a different document or reloads are expected.
+  // - Renderer-initiated fragment-navigations never take place in the browser,
+  //   even with PlzNavigate.
+  // - Restore-navigations are always browser-initiated.
+  // - History-navigations use the browser-initiated path, event the ones that
+  //   are initiated by a javascript script, please see the IPC message
+  //   ViewHostMsg_GoToEntryAtOffset.
+  DCHECK(FrameMsg_Navigate_Type::IsReload(common_params.navigation_type) ||
+         common_params.navigation_type ==
+             FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT);
+
   // TODO(clamy): See how we should handle override of the user agent when the
   // navigation may start in a renderer and commit in another one.
   // TODO(clamy): See if the navigation start time should be measured in the
   // renderer and sent to the browser instead of being measured here.
   // TODO(clamy): The pending history list offset should be properly set.
   RequestNavigationParams request_params(
-      false,                   // is_overriding_user_agent
-      std::vector<GURL>(),     // redirects
-      false,                   // can_load_local_resources
-      PageState(),             // page_state
-      0,                       // nav_entry_id
-      false,                   // is_same_document_history_load
-      false,                   // is_history_navigation_in_new_child
-      std::map<std::string, bool>(), // subframe_unique_names
+      false,                          // is_overriding_user_agent
+      std::vector<GURL>(),            // redirects
+      false,                          // can_load_local_resources
+      PageState(),                    // page_state
+      0,                              // nav_entry_id
+      false,                          // is_history_navigation_in_new_child
+      std::map<std::string, bool>(),  // subframe_unique_names
       frame_tree_node->has_committed_real_load(),
-      false,                   // intended_as_new_entry
-      -1,                      // pending_history_list_offset
+      false,  // intended_as_new_entry
+      -1,     // pending_history_list_offset
       current_history_list_offset, current_history_list_length,
-      false,                   // is_view_source
-      false,                   // should_clear_history_list
+      false,  // is_view_source
+      false,  // should_clear_history_list
       begin_params.has_user_gesture);
-  std::unique_ptr<NavigationRequest> navigation_request(
-      new NavigationRequest(frame_tree_node, common_params, begin_params,
-                            request_params,
-                            false, // browser_initiated
-                            false, // may_transfer
-                            nullptr, nullptr));
+  std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
+      frame_tree_node, common_params, begin_params, request_params,
+      false,  // browser_initiated
+      false,  // may_transfer
+      nullptr, nullptr));
   return navigation_request;
 }
 
@@ -346,7 +354,8 @@
   state_ = STARTED;
   RenderFrameDevToolsAgentHost::OnBeforeNavigation(navigation_handle_.get());
 
-  if (ShouldMakeNetworkRequestForURL(common_params_.url)) {
+  if (ShouldMakeNetworkRequestForURL(common_params_.url) &&
+      !navigation_handle_->IsSamePage()) {
     // It's safe to use base::Unretained because this NavigationRequest owns
     // the NavigationHandle where the callback will be stored.
     // TODO(clamy): pass the real value for |is_external_protocol| if needed.
@@ -382,8 +391,6 @@
 
 void NavigationRequest::CreateNavigationHandle(int pending_nav_entry_id) {
   DCHECK_EQ(frame_tree_node_->navigation_request(), this);
-  // TODO(nasko): Update the NavigationHandle creation to ensure that the
-  // proper values are specified for is_same_page.
   FrameTreeNode* frame_tree_node = frame_tree_node_;
 
   std::vector<GURL> redirect_chain;
@@ -393,11 +400,11 @@
 
   std::unique_ptr<NavigationHandleImpl> navigation_handle =
       NavigationHandleImpl::Create(
-        common_params_.url, redirect_chain, frame_tree_node_,
-        !browser_initiated_,
-        false,  // is_same_page
-        common_params_.navigation_start, pending_nav_entry_id,
-        false);  // started_in_context_menu
+          common_params_.url, redirect_chain, frame_tree_node_,
+          !browser_initiated_, FrameMsg_Navigate_Type::IsSameDocument(
+                                   common_params_.navigation_type),
+          common_params_.navigation_start, pending_nav_entry_id,
+          false);  // started_in_context_menu
 
   if (!frame_tree_node->navigation_request()) {
     // A callback could have cancelled this request synchronously in which case
@@ -582,12 +589,16 @@
   if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
       result == NavigationThrottle::CANCEL) {
     // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
-    frame_tree_node_->ResetNavigationRequest(false);
+    OnRequestFailed(false, net::ERR_ABORTED);
+
+    // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
+    // destroyed the NavigationRequest.
     return;
   }
 
   if (result == NavigationThrottle::BLOCK_REQUEST) {
     OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT);
+
     // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
     // destroyed the NavigationRequest.
     return;
@@ -675,7 +686,10 @@
   if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
       result == NavigationThrottle::CANCEL) {
     // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
-    frame_tree_node_->ResetNavigationRequest(false);
+    OnRequestFailed(false, net::ERR_ABORTED);
+
+    // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
+    // destroyed the NavigationRequest.
     return;
   }
 
@@ -692,9 +706,10 @@
   if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
       result == NavigationThrottle::CANCEL || !response_should_be_rendered_) {
     // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
-    frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
-        navigation_handle_.get());
-    frame_tree_node_->ResetNavigationRequest(false);
+    OnRequestFailed(false, net::ERR_ABORTED);
+
+    // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
+    // destroyed the NavigationRequest.
     return;
   }
 
@@ -715,7 +730,8 @@
 }
 
 void NavigationRequest::CommitNavigation() {
-  DCHECK(response_ || !ShouldMakeNetworkRequestForURL(common_params_.url));
+  DCHECK(response_ || !ShouldMakeNetworkRequestForURL(common_params_.url) ||
+         navigation_handle_->IsSamePage());
   DCHECK(!common_params_.url.SchemeIs(url::kJavaScriptScheme));
 
   // Retrieve the RenderFrameHost that needs to commit the navigation.
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 0c34b760..99780593 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -47,15 +47,20 @@
 #include "content/public/common/resource_response.h"
 #include "net/base/net_errors.h"
 #include "url/gurl.h"
+#include "url/url_util.h"
 
 namespace content {
 
 namespace {
 
 FrameMsg_Navigate_Type::Value GetNavigationType(
-    BrowserContext* browser_context,
+    const GURL& old_url,
+    const GURL& new_url,
+    ReloadType reload_type,
     const NavigationEntryImpl& entry,
-    ReloadType reload_type) {
+    const FrameNavigationEntry& frame_entry,
+    bool is_same_document_history_load) {
+  // Reload navigations
   switch (reload_type) {
     case ReloadType::NORMAL:
       return FrameMsg_Navigate_Type::RELOAD;
@@ -73,10 +78,36 @@
   if (entry.restore_type() == RestoreType::LAST_SESSION_EXITED_CLEANLY) {
     if (entry.GetHasPostData())
       return FrameMsg_Navigate_Type::RESTORE_WITH_POST;
-    return FrameMsg_Navigate_Type::RESTORE;
+    else
+      return FrameMsg_Navigate_Type::RESTORE;
   }
 
-  return FrameMsg_Navigate_Type::NORMAL;
+  // History navigations.
+  if (frame_entry.page_state().IsValid()) {
+    if (is_same_document_history_load)
+      return FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT;
+    else
+      return FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
+  }
+  DCHECK(!is_same_document_history_load);
+
+  // A same-document fragment-navigation happens when the only part of the url
+  // that is modified is after the '#' character.
+  //
+  // Be careful not to consider history navigations. For instance, if the
+  // history is: 'A#bar' -> 'B' -> 'A#foo'. Then an history navigation from
+  // 'A#foo' to 'A#bar' is not a same-document navigation, but a
+  // different-document one! The two FrameNavigationEntry doesn't share the same
+  // document_sequence_number.
+  //
+  // When modifying this condition, please take a look at:
+  // FrameLoader::shouldPerformFragmentNavigation.
+  if (new_url.has_ref() && old_url.EqualsIgnoringRef(new_url) &&
+      frame_entry.method() == "GET") {
+    return FrameMsg_Navigate_Type::SAME_DOCUMENT;
+  } else {
+    return FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
+  }
 }
 
 }  // namespace
@@ -417,15 +448,20 @@
           navigation_start, dest_url, entry.restore_type()));
       // Create the navigation parameters.
       FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(
-          controller_->GetBrowserContext(), entry, reload_type);
+          frame_tree_node->current_url(),  // old_url
+          dest_url,                        // new_url
+          reload_type,                     // reload_type
+          entry,                           // entry
+          frame_entry,                     // frame_entry
+          is_same_document_history_load);  // is_same_document_history_load
+
       dest_render_frame_host->Navigate(
           entry.ConstructCommonNavigationParams(
               frame_entry, post_body, dest_url, dest_referrer, navigation_type,
               previews_state, navigation_start),
           entry.ConstructStartNavigationParams(),
           entry.ConstructRequestNavigationParams(
-              frame_entry, is_same_document_history_load,
-              is_history_navigation_in_new_child,
+              frame_entry, is_history_navigation_in_new_child,
               entry.GetSubframeUniqueNames(frame_tree_node),
               frame_tree_node->has_committed_real_load(),
               controller_->GetPendingEntryIndex() == -1,
@@ -673,7 +709,7 @@
                                         params.url,
                                         transition_type);
     navigation_handle->DidCommitNavigation(params, details.did_replace_entry,
-                                           details.previous_url,
+                                           details.previous_url, details.type,
                                            render_frame_host);
     navigation_handle.reset();
   }
@@ -1133,8 +1169,13 @@
   bool should_dispatch_beforeunload =
       !is_same_document_history_load &&
       frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload();
-  FrameMsg_Navigate_Type::Value navigation_type =
-      GetNavigationType(controller_->GetBrowserContext(), entry, reload_type);
+  FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(
+      frame_tree_node->current_url(),  // old_url
+      dest_url,                        // new_url
+      reload_type,                     // reload_type
+      entry,                           // entry
+      frame_entry,                     // frame_entry
+      is_same_document_history_load);  // is_same_document_history_load
   std::unique_ptr<NavigationRequest> scoped_request =
       NavigationRequest::CreateBrowserInitiated(
           frame_tree_node, dest_url, dest_referrer, frame_entry, entry,
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index c241a26fa..d16dea8 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2533,9 +2533,9 @@
   DCHECK(data_url.SchemeIs(url::kDataScheme));
   CommonNavigationParams common_params(
       data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
-      FrameMsg_Navigate_Type::NORMAL, false, false, base::TimeTicks::Now(),
-      FrameMsg_UILoadMetricsReportType::NO_REPORT, GURL(), GURL(), PREVIEWS_OFF,
-      base::TimeTicks::Now(), "GET", nullptr);
+      FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false,
+      base::TimeTicks::Now(), FrameMsg_UILoadMetricsReportType::NO_REPORT,
+      GURL(), GURL(), PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr);
   if (IsBrowserSideNavigationEnabled()) {
     CommitNavigation(nullptr, nullptr, common_params, RequestNavigationParams(),
                      false);
@@ -2704,10 +2704,12 @@
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     bool is_view_source) {
-  DCHECK((response && body.get()) ||
-         common_params.url.SchemeIs(url::kDataScheme) ||
-         !ShouldMakeNetworkRequestForURL(common_params.url) ||
-         IsRendererDebugURL(common_params.url));
+  DCHECK(
+      (response && body.get()) ||
+      common_params.url.SchemeIs(url::kDataScheme) ||
+      !ShouldMakeNetworkRequestForURL(common_params.url) ||
+      FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type) ||
+      IsRendererDebugURL(common_params.url));
   UpdatePermissionsForNavigation(common_params, request_params);
 
   // Get back to a clean state, in case we start a new navigation without
@@ -2729,8 +2731,10 @@
                                      request_params));
 
   // If a network request was made, update the Previews state.
-  if (ShouldMakeNetworkRequestForURL(common_params.url))
+  if (ShouldMakeNetworkRequestForURL(common_params.url) &&
+      !FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)) {
     last_navigation_previews_state_ = common_params.previews_state;
+  }
 
   // TODO(clamy): Release the stream handle once the renderer has finished
   // reading it.
@@ -3405,15 +3409,27 @@
 std::unique_ptr<NavigationHandleImpl>
 RenderFrameHostImpl::TakeNavigationHandleForCommit(
     const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
-  // If this is a same-page navigation, there isn't an existing NavigationHandle
-  // to use for the navigation. Create one, but don't reset any NavigationHandle
-  // tracking an ongoing navigation, since this may lead to the cancellation of
-  // the navigation.
-  if (params.was_within_same_page) {
-    // We don't ever expect navigation_handle_ to match, because handles are not
-    // created for same-page navigations.
-    DCHECK(!navigation_handle_ || !navigation_handle_->IsSamePage());
+  bool is_browser_initiated = (params.nav_entry_id != 0);
 
+  if (params.was_within_same_page) {
+    if (IsBrowserSideNavigationEnabled()) {
+      // When browser-side navigation is enabled, a NavigationHandle is created
+      // for browser-initiated same-page navigation. Try to take it if it's
+      // still available and matches the current navigation.
+      if (is_browser_initiated && navigation_handle_ &&
+          navigation_handle_->IsSamePage() &&
+          navigation_handle_->GetURL() == params.url) {
+        return std::move(navigation_handle_);
+      }
+    } else {
+      // When browser-side navigation is disabled, there is never any existing
+      // NavigationHandle to use for the navigation. We don't ever expect
+      // navigation_handle_ to match.
+      DCHECK(!navigation_handle_ || !navigation_handle_->IsSamePage());
+    }
+    // No existing NavigationHandle has been found. Create a new one, but don't
+    // reset any NavigationHandle tracking an ongoing navigation, since this may
+    // lead to the cancellation of the navigation.
     // First, determine if the navigation corresponds to the pending navigation
     // entry. This is the case for a browser-initiated same-page navigation,
     // which does not cause a NavigationHandle to be created because it does not
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
index 9391ad1..ea642f7 100644
--- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -431,7 +431,7 @@
                                                      ->GetController());
       FrameMsg_Navigate_Type::Value navigate_type =
           entry.restore_type() == RestoreType::NONE
-              ? FrameMsg_Navigate_Type::NORMAL
+              ? FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT
               : FrameMsg_Navigate_Type::RESTORE;
       std::unique_ptr<NavigationRequest> navigation_request =
           NavigationRequest::CreateBrowserInitiated(
@@ -2837,8 +2837,8 @@
       NavigationRequest::CreateBrowserInitiated(
           contents()->GetFrameTree()->root(), frame_entry->url(),
           frame_entry->referrer(), *frame_entry, entry,
-          FrameMsg_Navigate_Type::NORMAL, PREVIEWS_UNSPECIFIED, false, false,
-          base::TimeTicks::Now(),
+          FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED,
+          false, false, base::TimeTicks::Now(),
           static_cast<NavigationControllerImpl*>(&controller()));
   manager->DidCreateNavigationRequest(navigation_request.get());
 
@@ -2898,8 +2898,8 @@
       NavigationRequest::CreateBrowserInitiated(
           contents()->GetFrameTree()->root(), frame_entry->url(),
           frame_entry->referrer(), *frame_entry, entry,
-          FrameMsg_Navigate_Type::NORMAL, PREVIEWS_UNSPECIFIED, false, false,
-          base::TimeTicks::Now(),
+          FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED,
+          false, false, base::TimeTicks::Now(),
           static_cast<NavigationControllerImpl*>(&controller()));
   manager->DidCreateNavigationRequest(navigation_request.get());
 
@@ -2956,8 +2956,8 @@
       NavigationRequest::CreateBrowserInitiated(
           contents()->GetFrameTree()->root(), frame_entry->url(),
           frame_entry->referrer(), *frame_entry, entry,
-          FrameMsg_Navigate_Type::NORMAL, PREVIEWS_UNSPECIFIED, false, false,
-          base::TimeTicks::Now(),
+          FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, PREVIEWS_UNSPECIFIED,
+          false, false, base::TimeTicks::Now(),
           static_cast<NavigationControllerImpl*>(&controller()));
   manager->DidCreateNavigationRequest(navigation_request.get());
 
diff --git a/content/browser/media/audio_stream_monitor.cc b/content/browser/media/audio_stream_monitor.cc
index ba86d56a..f2782a6b 100644
--- a/content/browser/media/audio_stream_monitor.cc
+++ b/content/browser/media/audio_stream_monitor.cc
@@ -15,13 +15,30 @@
 
 namespace {
 
-AudioStreamMonitor* AudioStreamMonitorFromRenderFrame(int render_process_id,
-                                                      int render_frame_id) {
+enum class ActionType { STARTING, STOPPING };
+AudioStreamMonitor* StartStopMonitoringHelper(ActionType action_type,
+                                              int render_process_id,
+                                              int render_frame_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  // It's important that this code uses only the process id for lookup as there
+  // may not be a RenderFrameHost or WebContents attached to the RenderProcess
+  // at time of call; e.g., in the event of a crash.
+  RenderProcessHost* const render_process_host =
+      RenderProcessHost::FromID(render_process_id);
+  if (!render_process_host)
+    return nullptr;
+
+  // TODO(dalecurtis, maxmorin): We should really only be sending these when the
+  // streams are audible or we don't have power level monitoring.
+  if (action_type == ActionType::STARTING)
+    render_process_host->OnAudioStreamAdded();
+  else
+    render_process_host->OnAudioStreamRemoved();
+
   WebContentsImpl* const web_contents =
       static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(
           RenderFrameHost::FromID(render_process_id, render_frame_id)));
-
   return web_contents ? web_contents->audio_stream_monitor() : nullptr;
 }
 
@@ -82,18 +99,15 @@
     int stream_id,
     const ReadPowerAndClipCallback& read_power_callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  AudioStreamMonitor* const monitor =
-      AudioStreamMonitorFromRenderFrame(render_process_id, render_frame_id);
-  if (!monitor)
-    return;
-
-  monitor->OnStreamAdded();
-
-  if (!power_level_monitoring_available())
-    return;
-
-  monitor->StartMonitoringStreamOnUIThread(render_process_id, stream_id,
-                                           read_power_callback);
+  if (AudioStreamMonitor* monitor = StartStopMonitoringHelper(
+          ActionType::STARTING, render_process_id, render_frame_id)) {
+    if (!power_level_monitoring_available()) {
+      monitor->OnStreamAdded();
+    } else {
+      monitor->StartMonitoringStreamOnUIThread(render_process_id, stream_id,
+                                               read_power_callback);
+    }
+  }
 }
 
 // static
@@ -101,17 +115,13 @@
                                               int render_frame_id,
                                               int stream_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  AudioStreamMonitor* const monitor =
-      AudioStreamMonitorFromRenderFrame(render_process_id, render_frame_id);
-  if (!monitor)
-    return;
-
-  monitor->OnStreamRemoved();
-
-  if (!power_level_monitoring_available())
-    return;
-
-  monitor->StopMonitoringStreamOnUIThread(render_process_id, stream_id);
+  if (AudioStreamMonitor* monitor = StartStopMonitoringHelper(
+          ActionType::STOPPING, render_process_id, render_frame_id)) {
+    if (!power_level_monitoring_available())
+      monitor->OnStreamRemoved();
+    else
+      monitor->StopMonitoringStreamOnUIThread(render_process_id, stream_id);
+  }
 }
 
 void AudioStreamMonitor::StartMonitoringStreamOnUIThread(
@@ -120,12 +130,15 @@
     const ReadPowerAndClipCallback& read_power_callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!read_power_callback.is_null());
-  poll_callbacks_[StreamID(render_process_id, stream_id)] = read_power_callback;
+
+  const StreamID qualified_id(render_process_id, stream_id);
+  DCHECK(poll_callbacks_.find(qualified_id) == poll_callbacks_.end());
+  poll_callbacks_[qualified_id] = read_power_callback;
+
   if (!poll_timer_.IsRunning()) {
     poll_timer_.Start(
-        FROM_HERE,
-        base::TimeDelta::FromSeconds(1) /
-            static_cast<int>(kPowerMeasurementsPerSecond),
+        FROM_HERE, base::TimeDelta::FromSeconds(1) /
+                       static_cast<int>(kPowerMeasurementsPerSecond),
         base::Bind(&AudioStreamMonitor::Poll, base::Unretained(this)));
   }
 }
@@ -133,7 +146,11 @@
 void AudioStreamMonitor::StopMonitoringStreamOnUIThread(int render_process_id,
                                                         int stream_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  poll_callbacks_.erase(StreamID(render_process_id, stream_id));
+
+  const StreamID qualified_id(render_process_id, stream_id);
+  DCHECK(poll_callbacks_.find(qualified_id) != poll_callbacks_.end());
+  poll_callbacks_.erase(qualified_id);
+
   if (poll_callbacks_.empty())
     poll_timer_.Stop();
 }
@@ -187,12 +204,8 @@
 
 void AudioStreamMonitor::OnStreamAdded() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  ++active_streams_;
-
-  if (power_level_monitoring_available())
-    return;
-
-  if (active_streams_ == 1) {
+  DCHECK(!power_level_monitoring_available());
+  if (++active_streams_ == 1u) {
     is_audible_ = true;
     web_contents_->OnAudioStateChanged(true);
     MaybeToggle();
@@ -201,12 +214,9 @@
 
 void AudioStreamMonitor::OnStreamRemoved() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  --active_streams_;
-
-  if (power_level_monitoring_available())
-    return;
-
-  if (active_streams_ == 0) {
+  DCHECK(!power_level_monitoring_available());
+  DCHECK_GT(active_streams_, 0u);
+  if (--active_streams_ == 0u) {
     is_audible_ = false;
     web_contents_->OnAudioStateChanged(false);
     MaybeToggle();
diff --git a/content/browser/notifications/PRESUBMIT.py b/content/browser/notifications/PRESUBMIT.py
deleted file mode 100644
index 4fbc9a7..0000000
--- a/content/browser/notifications/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for notifications.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/browser/push_messaging/PRESUBMIT.py b/content/browser/push_messaging/PRESUBMIT.py
deleted file mode 100644
index aa4ae97d..0000000
--- a/content/browser/push_messaging/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for Push Messaging.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/browser/renderer_host/media/audio_output_delegate.h b/content/browser/renderer_host/media/audio_output_delegate.h
index 4afe6c6..1bab027 100644
--- a/content/browser/renderer_host/media/audio_output_delegate.h
+++ b/content/browser/renderer_host/media/audio_output_delegate.h
@@ -31,9 +31,6 @@
 
     // All these methods are called on the IO thread.
 
-    // Called when the state changes between playing and not playing.
-    virtual void OnStreamStateChanged(bool playing) = 0;
-
     // Called when construction is finished and the stream is ready for
     // playout.
     virtual void OnStreamCreated(int stream_id,
diff --git a/content/browser/renderer_host/media/audio_output_delegate_impl.cc b/content/browser/renderer_host/media/audio_output_delegate_impl.cc
index b51b253..84aecef 100644
--- a/content/browser/renderer_host/media/audio_output_delegate_impl.cc
+++ b/content/browser/renderer_host/media/audio_output_delegate_impl.cc
@@ -180,7 +180,6 @@
     return;
 
   playing_ = playing;
-  subscriber_->OnStreamStateChanged(playing);
   if (playing) {
     // Note that this takes a reference to |controller_|, and
     // (Start|Stop)MonitoringStream calls are async, so we don't have a
diff --git a/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc b/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
index 0d93a7d..255c5aa 100644
--- a/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
+++ b/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
@@ -78,7 +78,6 @@
 
 class MockEventHandler : public AudioOutputDelegate::EventHandler {
  public:
-  MOCK_METHOD1(OnStreamStateChanged, void(bool playing));
   MOCK_METHOD3(OnStreamCreated,
                void(int stream_id,
                     base::SharedMemory* shared_memory,
@@ -153,11 +152,6 @@
                 OnStreamCreated(kStreamId, NotNull(), NotNull()));
     EXPECT_CALL(mirroring_manager_,
                 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()));
-    {
-      InSequence s;
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(true));
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(false));
-    }
 
     {
       AudioOutputDelegateImpl delegate(
@@ -212,13 +206,6 @@
                 OnStreamCreated(kStreamId, NotNull(), NotNull()));
     EXPECT_CALL(mirroring_manager_,
                 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()));
-    {
-      InSequence s;
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(true));
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(false));
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(true));
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(false));
-    }
 
     {
       AudioOutputDelegateImpl delegate(
@@ -248,11 +235,6 @@
                 OnStreamCreated(kStreamId, NotNull(), NotNull()));
     EXPECT_CALL(mirroring_manager_,
                 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()));
-    {
-      InSequence s;
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(true));
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(false));
-    }
 
     {
       AudioOutputDelegateImpl delegate(
@@ -340,11 +322,6 @@
                 OnStreamCreated(kStreamId, NotNull(), NotNull()));
     EXPECT_CALL(mirroring_manager_,
                 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()));
-    {
-      InSequence s;
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(true));
-      EXPECT_CALL(event_handler_, OnStreamStateChanged(false));
-    }
 
     DummyAudioOutputStream stream;
     {
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 9d1c9645..6a99670 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -25,7 +25,6 @@
 #include "content/public/browser/media_observer.h"
 #include "content/public/browser/render_frame_host.h"
 #include "media/audio/audio_device_description.h"
-#include "media/audio/audio_streams_tracker.h"
 #include "media/base/audio_bus.h"
 #include "media/base/limits.h"
 
@@ -36,21 +35,6 @@
 
 namespace {
 
-// Tracks the maximum number of simultaneous output streams browser-wide.
-// Accessed on IO thread.
-base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker =
-    LAZY_INSTANCE_INITIALIZER;
-
-void NotifyRenderProcessHostThatAudioStateChanged(int render_process_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  RenderProcessHost* render_process_host =
-      RenderProcessHost::FromID(render_process_id);
-
-  if (render_process_host)
-    render_process_host->AudioStateChanged();
-}
-
 void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) {
   UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime",
                              base::TimeTicks::Now() - auth_start_time,
@@ -85,10 +69,8 @@
       audio_manager_(audio_manager),
       mirroring_manager_(mirroring_manager),
       media_stream_manager_(media_stream_manager),
-      num_playing_streams_(0),
       salt_(salt),
       validate_render_frame_id_function_(&ValidateRenderFrameId),
-      max_simultaneous_streams_(0),
       authorization_handler_(audio_manager_,
                              media_stream_manager,
                              render_process_id_,
@@ -99,19 +81,6 @@
 AudioRendererHost::~AudioRendererHost() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(delegates_.empty());
-
-  // If we had any streams, report UMA stats for the maximum number of
-  // simultaneous streams for this render process and for the whole browser
-  // process since last reported.
-  if (max_simultaneous_streams_ > 0) {
-    UMA_HISTOGRAM_CUSTOM_COUNTS("Media.AudioRendererIpcStreams",
-                                max_simultaneous_streams_, 1, 50, 51);
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Media.AudioRendererIpcStreamsTotal",
-        g_audio_streams_tracker.Get().max_stream_count(),
-        1, 100, 101);
-    g_audio_streams_tracker.Get().ResetMaxStreamCount();
-  }
 }
 
 void AudioRendererHost::GetOutputControllers(
@@ -124,10 +93,6 @@
 
 void AudioRendererHost::OnChannelClosing() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  // Since the IPC sender is gone, close all requested audio streams.
-  // The audio streams tracker isn't automatically decremented since the
-  // removal isn't done through OnCloseStream.
-  g_audio_streams_tracker.Get().DecreaseStreamCount(delegates_.size());
   delegates_.clear();
 
   // Remove any authorizations for streams that were not yet created
@@ -349,11 +314,6 @@
           this, audio_manager_, std::move(audio_log), mirroring_manager_,
           media_observer, stream_id, render_frame_id, render_process_id_,
           params, device_unique_id)));
-
-  g_audio_streams_tracker.Get().IncreaseStreamCount();
-
-  if (delegates_.size() > max_simultaneous_streams_)
-    max_simultaneous_streams_ = delegates_.size();
 }
 
 void AudioRendererHost::OnPlayStream(int stream_id) {
@@ -412,8 +372,6 @@
 
   std::swap(*i, delegates_.back());
   delegates_.pop_back();
-
-  g_audio_streams_tracker.Get().DecreaseStreamCount();
 }
 
 AudioRendererHost::AudioOutputDelegateVector::iterator
@@ -434,40 +392,11 @@
   return i != delegates_.end() ? i->get() : nullptr;
 }
 
-void AudioRendererHost::OnStreamStateChanged(bool is_playing) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (is_playing) {
-    base::AtomicRefCountInc(&num_playing_streams_);
-
-    // Inform the RenderProcessHost when audio starts playing for the first
-    // time. The nonatomic increment-and-read is ok since this is the only
-    // thread that |num_plaing_streams_| may be updated on.
-    if (base::AtomicRefCountIsOne(&num_playing_streams_)) {
-      BrowserThread::PostTask(
-          BrowserThread::UI, FROM_HERE,
-          base::Bind(&NotifyRenderProcessHostThatAudioStateChanged,
-                     render_process_id_));
-    }
-  } else {
-    // Inform the RenderProcessHost when there is no more audio playing.
-    if (!base::AtomicRefCountDec(&num_playing_streams_)) {
-      BrowserThread::PostTask(
-          BrowserThread::UI, FROM_HERE,
-          base::Bind(&NotifyRenderProcessHostThatAudioStateChanged,
-                     render_process_id_));
-    }
-  }
-}
-
 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   return authorizations_.find(stream_id) != authorizations_.end();
 }
 
-bool AudioRendererHost::HasActiveAudio() {
-  return !base::AtomicRefCountIsZero(&num_playing_streams_);
-}
-
 void AudioRendererHost::OverrideDevicePermissionsForTesting(bool has_access) {
   authorization_handler_.OverridePermissionsForTesting(has_access);
 }
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h
index 6170e93..0d0ca36 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -93,11 +93,6 @@
                        base::SharedMemory* shared_memory,
                        base::CancelableSyncSocket* foreign_socket) override;
   void OnStreamError(int stream_id) override;
-  void OnStreamStateChanged(bool is_playing) override;
-
-  // Returns true if any streams managed by this host are actively playing.  Can
-  // be called from any thread.
-  bool HasActiveAudio();
 
   void OverrideDevicePermissionsForTesting(bool has_access);
 
@@ -216,10 +211,6 @@
   // A list of the current open streams.
   AudioOutputDelegateVector delegates_;
 
-  // The number of streams in the playing state. Atomic read safe from any
-  // thread, but should only be updated from the IO thread.
-  base::AtomicRefCount num_playing_streams_;
-
   // Salt required to translate renderer device IDs to raw device unique IDs
   std::string salt_;
 
@@ -234,10 +225,6 @@
   // constructor, but this can be overridden by unit tests.
   ValidateRenderFrameIdFunction validate_render_frame_id_function_;
 
-  // The maximum number of simultaneous streams during the lifetime of this
-  // host. Reported as UMA stat at shutdown.
-  size_t max_simultaneous_streams_;
-
   AudioOutputAuthorizationHandler authorization_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioRendererHost);
diff --git a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
index c729f6d..c4a16f2f 100644
--- a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
+++ b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
@@ -22,8 +22,7 @@
                provider->GetSurfaceManager(),
                frame_sink_id,
                nullptr,
-               true /* handles_frame_sink_id_invalidation */,
-               true /* needs_sync_points */),
+               nullptr),
       client_(std::move(client)),
       binding_(this, std::move(request)) {
   binding_.set_connection_error_handler(
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index 52ab8563..e8f6b3a 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -18,6 +18,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_service.mojom.h"
 #include "content/shell/browser/shell.h"
+#include "media/base/test_data_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/public/cpp/interface_registry.h"
@@ -46,6 +47,11 @@
  public:
   RenderProcessHostTest() : process_exits_(0), host_destructions_(0) {}
 
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(
+        switches::kDisableGestureRequirementForMediaPlayback);
+  }
+
  protected:
   void set_process_exit_callback(const base::Closure& callback) {
     process_exit_callback_ = callback;
@@ -239,5 +245,84 @@
     rph->RemoveObserver(this);
 }
 
+class MediaStopObserver : public WebContentsObserver {
+ public:
+  MediaStopObserver(WebContents* web_contents, base::Closure quit_closure)
+      : WebContentsObserver(web_contents),
+        quit_closure_(std::move(quit_closure)) {}
+  ~MediaStopObserver() override {}
+
+  void MediaStoppedPlaying(
+      const WebContentsObserver::MediaPlayerInfo& media_info,
+      const WebContentsObserver::MediaPlayerId& id) override {
+    quit_closure_.Run();
+  }
+
+ private:
+  base::Closure quit_closure_;
+};
+
+// Tests that audio stream counts (used for process priority calculations) are
+// properly set and cleared during media playback and renderer terminations.
+//
+// Note: This test can't run when the Mojo Renderer is used since it does not
+// create audio streams through the normal audio pathways; at present this is
+// only used by Chromecast.
+#if defined(ENABLE_MOJO_RENDERER)
+#define KillProcessZerosAudioStreams DISABLED_KillProcessZerosAudioStreams
+#endif
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
+  embedded_test_server()->ServeFilesFromSourceDirectory(
+      media::GetTestDataPath());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  NavigateToURL(shell(), embedded_test_server()->GetURL("/sfx_s16le.wav"));
+  RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
+      shell()->web_contents()->GetMainFrame()->GetProcess());
+
+  {
+    // Wait for media playback to complete. We use the stop signal instead of
+    // the start signal here since the start signal does not mean the audio
+    // has actually started playing yet. Whereas the stop signal is sent before
+    // the audio device is actually torn down.
+    base::RunLoop run_loop;
+    MediaStopObserver stop_observer(shell()->web_contents(),
+                                    run_loop.QuitClosure());
+    run_loop.Run();
+
+    // No point in running the rest of the test if this is wrong.
+    ASSERT_EQ(1, rph->get_audio_stream_count_for_testing());
+  }
+
+  host_destructions_ = 0;
+  process_exits_ = 0;
+  rph->AddObserver(this);
+
+  mojom::TestServicePtr service;
+  rph->GetRemoteInterfaces()->GetInterface(&service);
+
+  {
+    // Force a bad message event to occur which will terminate the renderer.
+    base::RunLoop run_loop;
+    set_process_exit_callback(run_loop.QuitClosure());
+    service->DoSomething(base::Bind(&base::DoNothing));
+    run_loop.Run();
+  }
+
+  {
+    // Cycle UI loop once to ensure audio stream notifications are sent.
+    base::RunLoop run_loop;
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                            run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  // Verify shutdown went as expected.
+  EXPECT_EQ(0, rph->get_audio_stream_count_for_testing());
+  EXPECT_EQ(1, process_exits_);
+  EXPECT_EQ(0, host_destructions_);
+  if (!host_destructions_)
+    rph->RemoveObserver(this);
+}
+
 }  // namespace
 }  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 79eeee2..a2f19a9f 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -680,8 +680,6 @@
       shared_worker_ref_count_(0),
       is_worker_ref_count_disabled_(false),
       route_provider_binding_(this),
-      associated_interface_provider_bindings_(
-          mojo::BindingSetDispatchMode::WITH_CONTEXT),
       visible_widgets_(0),
       is_process_backgrounded_(false),
       id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
@@ -1356,15 +1354,14 @@
     mojom::AssociatedInterfaceProviderAssociatedRequest request) {
   DCHECK(request.is_pending());
   associated_interface_provider_bindings_.AddBinding(
-      this, std::move(request),
-      reinterpret_cast<void*>(static_cast<uintptr_t>(routing_id)));
+      this, std::move(request), routing_id);
 }
 
 void RenderProcessHostImpl::GetAssociatedInterface(
     const std::string& name,
     mojom::AssociatedInterfaceAssociatedRequest request) {
-  int32_t routing_id = static_cast<int32_t>(reinterpret_cast<uintptr_t>(
-      associated_interface_provider_bindings_.dispatch_context()));
+  int32_t routing_id =
+      associated_interface_provider_bindings_.dispatch_context();
   IPC::Listener* listener = listeners_.Lookup(routing_id);
   if (listener)
     listener->OnAssociatedInterfaceRequest(name, request.PassHandle());
@@ -1572,7 +1569,14 @@
   return visible_widgets_;
 }
 
-void RenderProcessHostImpl::AudioStateChanged() {
+void RenderProcessHostImpl::OnAudioStreamAdded() {
+  ++audio_stream_count_;
+  UpdateProcessPriority();
+}
+
+void RenderProcessHostImpl::OnAudioStreamRemoved() {
+  DCHECK_GT(audio_stream_count_, 0);
+  --audio_stream_count_;
   UpdateProcessPriority();
 }
 
@@ -2831,7 +2835,7 @@
   // visible widgets -- the callers must call this function whenever we
   // transition in/out of those states.
   const bool should_background =
-      visible_widgets_ == 0 && !audio_renderer_host_->HasActiveAudio() &&
+      visible_widgets_ == 0 && audio_stream_count_ == 0 &&
       !base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableRendererBackgrounding);
 
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index dc269f2..a7c2fa32 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -123,7 +123,6 @@
   void WidgetRestored() override;
   void WidgetHidden() override;
   int VisibleWidgetCount() const override;
-  void AudioStateChanged() override;
   bool IsForGuestsOnly() const override;
   StoragePartition* GetStoragePartition() const override;
   bool Shutdown(int exit_code, bool wait) override;
@@ -287,6 +286,12 @@
 
   void RecomputeAndUpdateWebKitPreferences();
 
+  // Called when an audio stream is added or removed and used to determine if
+  // the process should be backgrounded or not.
+  void OnAudioStreamAdded() override;
+  void OnAudioStreamRemoved() override;
+  int get_audio_stream_count_for_testing() const { return audio_stream_count_; }
+
  protected:
   // A proxy for our IPC::Channel that lives on the IO thread.
   std::unique_ptr<IPC::ChannelProxy> channel_;
@@ -451,7 +456,7 @@
   IDMap<IPC::Listener*> listeners_;
 
   mojo::AssociatedBinding<mojom::RouteProvider> route_provider_binding_;
-  mojo::AssociatedBindingSet<mojom::AssociatedInterfaceProvider>
+  mojo::AssociatedBindingSet<mojom::AssociatedInterfaceProvider, int32_t>
       associated_interface_provider_bindings_;
 
   // The count of currently visible widgets.  Since the host can be a container
@@ -599,6 +604,10 @@
   mojom::RouteProviderAssociatedPtr remote_route_provider_;
   mojom::RendererAssociatedPtr renderer_interface_;
 
+  // Tracks active audio streams within the render process; used to determine if
+  // if a process should be backgrounded.
+  int audio_stream_count_ = 0;
+
   // A WeakPtrFactory which is reset every time Cleanup() runs. Used to vend
   // WeakPtrs which are invalidated any time the RPHI is recycled.
   std::unique_ptr<base::WeakPtrFactory<RenderProcessHostImpl>>
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 02d54e8..9f1db28 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -400,6 +400,10 @@
       display_compositor::GLHelper::SCALER_QUALITY_GOOD);
 }
 
+bool FloatEquals(float a, float b) {
+  return std::abs(a - b) < FLT_EPSILON;
+}
+
 }  // namespace
 
 void RenderWidgetHostViewAndroid::OnContextLost() {
@@ -435,6 +439,8 @@
       synchronous_compositor_client_(nullptr),
       frame_evictor_(new DelegatedFrameEvictor(this)),
       observing_root_window_(false),
+      prev_top_shown_pix_(0.f),
+      prev_bottom_shown_pix_(0.f),
       weak_ptr_factory_(this) {
   // Set the layer which will hold the content layer for this view. The content
   // layer is managed by the DelegatedFrameHost.
@@ -790,8 +796,7 @@
   if (delegated_frame_host_)
     delegated_frame_host_->UpdateBackgroundColor(color);
 
-  if (content_view_core_)
-    content_view_core_->OnBackgroundColorChanged(color);
+  view_.OnBackgroundColorChanged(color);
 }
 
 void RenderWidgetHostViewAndroid::SetNeedsBeginFrames(bool needs_begin_frames) {
@@ -805,8 +810,7 @@
 
 void RenderWidgetHostViewAndroid::OnStartContentIntent(
     const GURL& content_url, bool is_main_frame) {
-  if (content_view_core_)
-    content_view_core_->StartContentIntent(content_url, is_main_frame);
+  view_.StartContentIntent(content_url, is_main_frame);
 }
 
 bool RenderWidgetHostViewAndroid::OnTouchEvent(
@@ -1274,6 +1278,28 @@
       frame_metadata.top_controls_height *
           frame_metadata.top_controls_shown_ratio));
 
+  float dip_scale = ui::GetScaleFactorForNativeView(GetNativeView());
+  float top_controls_pix = frame_metadata.top_controls_height * dip_scale;
+  float top_shown_pix = top_controls_pix
+      * frame_metadata.top_controls_shown_ratio;
+  bool top_changed = !FloatEquals(top_shown_pix, prev_top_shown_pix_);
+
+  float bottom_controls_pix = frame_metadata.bottom_controls_height * dip_scale;
+  float bottom_shown_pix = bottom_controls_pix
+      * frame_metadata.bottom_controls_shown_ratio;
+  bool bottom_changed = !FloatEquals(bottom_shown_pix, prev_bottom_shown_pix_);
+
+  if (top_changed) {
+    float translate = top_shown_pix - top_controls_pix;
+    view_.OnTopControlsChanged(translate, top_shown_pix);
+    prev_top_shown_pix_ = top_shown_pix;
+  }
+  if (bottom_changed) {
+    float translate = bottom_controls_pix - bottom_shown_pix;
+    view_.OnBottomControlsChanged(translate, bottom_shown_pix);
+    prev_bottom_shown_pix_ = bottom_shown_pix;
+  }
+
   // All offsets and sizes are in CSS pixels.
   content_view_core_->UpdateFrameInfo(
       frame_metadata.root_scroll_offset,
@@ -1284,8 +1310,6 @@
       frame_metadata.scrollable_viewport_size,
       frame_metadata.top_controls_height,
       frame_metadata.top_controls_shown_ratio,
-      frame_metadata.bottom_controls_height,
-      frame_metadata.bottom_controls_shown_ratio,
       is_mobile_optimized,
       frame_metadata.selection.start);
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index a52a7a1..05064919 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -376,6 +376,9 @@
   // The last scroll offset of the view.
   gfx::Vector2dF last_scroll_offset_;
 
+  float prev_top_shown_pix_;
+  float prev_bottom_shown_pix_;
+
   base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 6317139..74e7ed4 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2369,7 +2369,8 @@
   base::string16 selected_text;
   if (GetTextInputManager()
           ->GetTextSelection(focused_view)
-          ->GetSelectedText(&selected_text)) {
+          ->GetSelectedText(&selected_text) &&
+      selected_text.length()) {
     // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
     ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
     clipboard_writer.WriteText(selected_text);
diff --git a/content/browser/renderer_host/text_input_manager.cc b/content/browser/renderer_host/text_input_manager.cc
index dc7e1b6b..39bbe599 100644
--- a/content/browser/renderer_host/text_input_manager.cc
+++ b/content/browser/renderer_host/text_input_manager.cc
@@ -328,8 +328,10 @@
 
 bool TextInputManager::TextSelection::GetSelectedText(
     base::string16* selected_text) const {
-  if (text.empty() || range.is_empty())
+  if (text.empty() || range.is_empty()) {
+    selected_text->clear();
     return true;
+  }
 
   size_t pos = range.GetMin() - offset;
   size_t n = range.length();
diff --git a/content/browser/resources/media/manager.js b/content/browser/resources/media/manager.js
index 27f6b99..983cca5 100644
--- a/content/browser/resources/media/manager.js
+++ b/content/browser/resources/media/manager.js
@@ -16,6 +16,11 @@
     this.players_ = {};
     this.audioComponents_ = [];
     this.clientRenderer_ = clientRenderer;
+
+    this.hidePlayersButton = document.getElementById('hide-players-button');
+    // In tests we may not have this button.
+    if (this.hidePlayersButton)
+      this.hidePlayersButton.onclick = this.hidePlayers_.bind(this);
   }
 
   Manager.prototype = {
@@ -78,6 +83,12 @@
       this.clientRenderer_.playerRemoved(this.players_, playerRemoved);
     },
 
+    hidePlayers_: function() {
+      util.object.forEach(this.players_, function(playerInfo, id) {
+        this.removePlayer(id);
+      }, this);
+    },
+
     updatePlayerInfoNoRecord: function(id, timestamp, key, value) {
       if (!this.players_[id]) {
         console.error('[updatePlayerInfo] Id ' + id + ' does not exist');
diff --git a/content/browser/resources/media/media_internals.html b/content/browser/resources/media/media_internals.html
index 8782a4c..eb72b60 100644
--- a/content/browser/resources/media/media_internals.html
+++ b/content/browser/resources/media/media_internals.html
@@ -27,7 +27,8 @@
     </tabs>
     <tabpanels>
       <tabpanel id="players">
-        <button id="save-log-button" style="display:none">Save log</button>
+        <button id="save-log-button" title="Save all player logs into a file." style="display:none">Save log</button>
+        <button id="hide-players-button" title="Hide all players in the current view." stype="display:inline-block">Hide players</button>
         <div id="list-wrapper">
           <div id="player-list-wrapper">
             <h2>Recent Players</h2>
diff --git a/content/browser/service_worker/PRESUBMIT.py b/content/browser/service_worker/PRESUBMIT.py
deleted file mode 100644
index 928d9fe0..0000000
--- a/content/browser/service_worker/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for service_worker.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/browser/shared_worker/PRESUBMIT.py b/content/browser/shared_worker/PRESUBMIT.py
deleted file mode 100644
index 2cff9b0..0000000
--- a/content/browser/shared_worker/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +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.
-
-"""Presubmit script for service_worker.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/browser/shared_worker/shared_worker_host.cc b/content/browser/shared_worker/shared_worker_host.cc
index a41e5b6..21e22369 100644
--- a/content/browser/shared_worker/shared_worker_host.cc
+++ b/content/browser/shared_worker/shared_worker_host.cc
@@ -130,6 +130,15 @@
   }
 }
 
+void SharedWorkerHost::CountFeature(uint32_t feature) {
+  if (!used_features_.insert(feature).second)
+    return;
+  for (const auto& filter_info : filters_) {
+    filter_info.filter()->Send(new ViewMsg_CountFeatureOnSharedWorker(
+        filter_info.route_id(), feature));
+  }
+}
+
 void SharedWorkerHost::WorkerContextClosed() {
   // Set the closed flag - this will stop any further messages from
   // being sent to the worker (messages can still be sent from the worker,
@@ -139,6 +148,13 @@
     NotifyWorkerDestroyed(worker_process_id_, worker_route_id_);
 }
 
+void SharedWorkerHost::WorkerContextDestroyed() {
+  for (const auto& filter_info : filters_) {
+    filter_info.filter()->Send(
+        new ViewMsg_WorkerDestroyed(filter_info.route_id()));
+  }
+}
+
 void SharedWorkerHost::WorkerReadyForInspection() {
   NotifyWorkerReadyForInspection(worker_process_id_, worker_route_id_);
 }
@@ -159,7 +175,8 @@
   for (const FilterInfo& info : filters_) {
     if (info.message_port_id() != message_port_id)
       continue;
-    info.filter()->Send(new ViewMsg_WorkerConnected(info.route_id()));
+    info.filter()->Send(
+        new ViewMsg_WorkerConnected(info.route_id(), used_features_));
     return;
   }
 }
diff --git a/content/browser/shared_worker/shared_worker_host.h b/content/browser/shared_worker/shared_worker_host.h
index 49c65f0..5e8a4b8e 100644
--- a/content/browser/shared_worker/shared_worker_host.h
+++ b/content/browser/shared_worker/shared_worker_host.h
@@ -7,6 +7,7 @@
 
 #include <list>
 #include <memory>
+#include <set>
 #include <utility>
 #include <vector>
 
@@ -62,12 +63,13 @@
   // referenced by active documents.
   void RenderFrameDetached(int render_process_id, int render_frame_id);
 
+  void CountFeature(uint32_t feature);
   void WorkerContextClosed();
+  void WorkerContextDestroyed();
   void WorkerReadyForInspection();
   void WorkerScriptLoaded();
   void WorkerScriptLoadFailed();
   void WorkerConnected(int message_port_id);
-  void WorkerContextDestroyed();
   void AllowFileSystem(const GURL& url,
                        std::unique_ptr<IPC::Message> reply_msg);
   void AllowIndexedDB(const GURL& url,
@@ -141,6 +143,10 @@
   bool closed_ = false;
   const base::TimeTicks creation_time_;
 
+  // This is the set of features that this worker has used. The values must be
+  // from blink::UseCounter::Feature enum.
+  std::set<uint32_t> used_features_;
+
   base::WeakPtrFactory<SharedWorkerHost> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SharedWorkerHost);
diff --git a/content/browser/shared_worker/shared_worker_message_filter.cc b/content/browser/shared_worker/shared_worker_message_filter.cc
index 375cf1a..9b5440f 100644
--- a/content/browser/shared_worker/shared_worker_message_filter.cc
+++ b/content/browser/shared_worker/shared_worker_message_filter.cc
@@ -58,6 +58,9 @@
                         SharedWorkerServiceImpl::GetInstance(),
                         SharedWorkerServiceImpl::DocumentDetached)
     // Only sent from SharedWorker in renderer.
+    IPC_MESSAGE_FORWARD(WorkerHostMsg_CountFeature,
+                        SharedWorkerServiceImpl::GetInstance(),
+                        SharedWorkerServiceImpl::CountFeature)
     IPC_MESSAGE_FORWARD(WorkerHostMsg_WorkerContextClosed,
                         SharedWorkerServiceImpl::GetInstance(),
                         SharedWorkerServiceImpl::WorkerContextClosed)
diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc
index e700500..4524fd5 100644
--- a/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -347,6 +347,15 @@
   }
 }
 
+void SharedWorkerServiceImpl::CountFeature(SharedWorkerMessageFilter* filter,
+                                           int worker_route_id,
+                                           uint32_t feature) {
+  if (SharedWorkerHost* host =
+          FindSharedWorkerHost(filter->render_process_id(), worker_route_id)) {
+    host->CountFeature(feature);
+  }
+}
+
 void SharedWorkerServiceImpl::WorkerContextClosed(
     SharedWorkerMessageFilter* filter,
     int worker_route_id) {
@@ -360,6 +369,10 @@
     SharedWorkerMessageFilter* filter,
     int worker_route_id) {
   ScopedWorkerDependencyChecker checker(this);
+  if (SharedWorkerHost* host =
+          FindSharedWorkerHost(filter->render_process_id(), worker_route_id)) {
+    host->WorkerContextDestroyed();
+  }
   ProcessRouteIdPair key(filter->render_process_id(), worker_route_id);
   worker_hosts_.erase(key);
 }
diff --git a/content/browser/shared_worker/shared_worker_service_impl.h b/content/browser/shared_worker/shared_worker_service_impl.h
index 952b428..ca351d1 100644
--- a/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/content/browser/shared_worker/shared_worker_service_impl.h
@@ -61,6 +61,9 @@
                        int sent_message_port_id);
   void DocumentDetached(SharedWorkerMessageFilter* filter,
                         unsigned long long document_id);
+  void CountFeature(SharedWorkerMessageFilter* filter,
+                    int worker_route_id,
+                    uint32_t feature);
   void WorkerContextClosed(SharedWorkerMessageFilter* filter,
                            int worker_route_id);
   void WorkerContextDestroyed(SharedWorkerMessageFilter* filter,
diff --git a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index b1b809a5..fec5578f 100644
--- a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -351,6 +351,18 @@
   EXPECT_EQ(connector->route_id(), msg->routing_id());
 }
 
+void CheckViewMsgCountFeature(MockRendererProcessHost* renderer_host,
+                              MockSharedWorkerConnector* connector,
+                              uint32_t expected_feature) {
+  std::unique_ptr<IPC::Message> msg(renderer_host->PopMessage());
+  EXPECT_EQ(ViewMsg_CountFeatureOnSharedWorker::ID, msg->type());
+  EXPECT_EQ(connector->route_id(), msg->routing_id());
+  ViewMsg_CountFeatureOnSharedWorker::Param params;
+  EXPECT_TRUE(ViewMsg_CountFeatureOnSharedWorker::Read(msg.get(), &params));
+  uint32_t feature = std::get<0>(params);
+  EXPECT_EQ(expected_feature, feature);
+}
+
 void CheckMessagePortMsgMessagesQueued(MockRendererProcessHost* renderer_host,
                                        MockSharedWorkerConnector* connector) {
   std::unique_ptr<IPC::Message> msg(renderer_host->PopMessage());
@@ -385,10 +397,15 @@
 }
 
 void CheckViewMsgWorkerConnected(MockRendererProcessHost* renderer_host,
-                                 MockSharedWorkerConnector* connector) {
+                                 MockSharedWorkerConnector* connector,
+                                 std::set<uint32_t> expected_used_features) {
   std::unique_ptr<IPC::Message> msg(renderer_host->PopMessage());
   EXPECT_EQ(ViewMsg_WorkerConnected::ID, msg->type());
   EXPECT_EQ(connector->route_id(), msg->routing_id());
+  ViewMsg_WorkerConnected::Param params;
+  EXPECT_TRUE(ViewMsg_WorkerConnected::Read(msg.get(), &params));
+  std::set<uint32_t> used_features = std::get<0>(params);
+  EXPECT_EQ(expected_used_features, used_features);
 }
 
 }  // namespace
@@ -465,7 +482,8 @@
           connector->remote_port_id(), worker_route_id)));
   EXPECT_EQ(1U, renderer_host->QueuedMessageCount());
   // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side.
-  CheckViewMsgWorkerConnected(renderer_host.get(), connector.get());
+  CheckViewMsgWorkerConnected(renderer_host.get(), connector.get(),
+                              std::set<uint32_t>());
 
   // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage,
   // SharedWorker side shuold receive MessagePortMsg_Message.
@@ -485,6 +503,28 @@
   CheckMessagePortMsgMessage(
       renderer_host.get(), connector->local_port_route_id(), "test2");
 
+  // SharedWorker sends WorkerHostMsg_CountFeature in
+  // EmbeddedSharedWorkerStub::CountFeature().
+  uint32_t feature1 = 124;
+  EXPECT_TRUE(renderer_host->OnMessageReceived(
+      new WorkerHostMsg_CountFeature(worker_route_id, feature1)));
+  EXPECT_EQ(1U, renderer_host->QueuedMessageCount());
+  // ViewMsg_CountFeature should be sent to SharedWorkerConnector side.
+  CheckViewMsgCountFeature(renderer_host.get(), connector.get(), feature1);
+  // A message should be sent only one time per feature.
+  EXPECT_TRUE(renderer_host->OnMessageReceived(
+      new WorkerHostMsg_CountFeature(worker_route_id, feature1)));
+  EXPECT_EQ(0U, renderer_host->QueuedMessageCount());
+
+  // SharedWorker sends WorkerHostMsg_CountFeature in
+  // EmbeddedSharedWorkerStub::CountFeature() for another feature use.
+  uint32_t feature2 = 901;
+  EXPECT_TRUE(renderer_host->OnMessageReceived(
+      new WorkerHostMsg_CountFeature(worker_route_id, feature2)));
+  EXPECT_EQ(1U, renderer_host->QueuedMessageCount());
+  // ViewMsg_CountFeature should be sent to SharedWorkerConnector side.
+  CheckViewMsgCountFeature(renderer_host.get(), connector.get(), feature2);
+
   // UpdateWorkerDependency should not be called.
   EXPECT_EQ(0, s_update_worker_dependency_call_count_);
 }
@@ -562,7 +602,8 @@
           connector0->remote_port_id(), worker_route_id)));
   EXPECT_EQ(1U, renderer_host0->QueuedMessageCount());
   // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side.
-  CheckViewMsgWorkerConnected(renderer_host0.get(), connector0.get());
+  CheckViewMsgWorkerConnected(renderer_host0.get(), connector0.get(),
+                              std::set<uint32_t>());
 
   // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage,
   // SharedWorker side shuold receive MessagePortMsg_Message.
@@ -582,6 +623,21 @@
   CheckMessagePortMsgMessage(
       renderer_host0.get(), connector0->local_port_route_id(), "test2");
 
+  // SharedWorker sends WorkerHostMsg_CountFeature in
+  // EmbeddedSharedWorkerStub::CountFeature().
+  uint32_t feature1 = 124;
+  EXPECT_TRUE(renderer_host0->OnMessageReceived(
+      new WorkerHostMsg_CountFeature(worker_route_id, feature1)));
+  EXPECT_EQ(1U, renderer_host0->QueuedMessageCount());
+  // ViewMsg_CountFeature should be sent to SharedWorkerConnector side.
+  CheckViewMsgCountFeature(renderer_host0.get(), connector0.get(), feature1);
+  uint32_t feature2 = 901;
+  EXPECT_TRUE(renderer_host0->OnMessageReceived(
+      new WorkerHostMsg_CountFeature(worker_route_id, feature2)));
+  EXPECT_EQ(1U, renderer_host0->QueuedMessageCount());
+  // ViewMsg_CountFeature should be sent to SharedWorkerConnector side.
+  CheckViewMsgCountFeature(renderer_host0.get(), connector0.get(), feature2);
+
   // The second renderer host.
   std::unique_ptr<MockRendererProcessHost> renderer_host1(
       new MockRendererProcessHost(kProcessIDs[1],
@@ -642,7 +698,8 @@
           connector1->remote_port_id(), worker_route_id)));
   EXPECT_EQ(1U, renderer_host1->QueuedMessageCount());
   // ViewMsg_WorkerConnected should be sent to SharedWorkerConnector side.
-  CheckViewMsgWorkerConnected(renderer_host1.get(), connector1.get());
+  CheckViewMsgWorkerConnected(renderer_host1.get(), connector1.get(),
+                              {feature1, feature2});
 
   // When SharedWorkerConnector side sends MessagePortHostMsg_PostMessage,
   // SharedWorker side shuold receive MessagePortMsg_Message.
@@ -661,6 +718,27 @@
   CheckMessagePortMsgMessage(
       renderer_host1.get(), connector1->local_port_route_id(), "test4");
 
+  // SharedWorker sends WorkerHostMsg_CountFeature in
+  // EmbeddedSharedWorkerStub::CountFeature(). These used_features are already
+  // counted in the browser-side, so messages should not be sent to
+  // SharedWorkerConnectors.
+  EXPECT_TRUE(renderer_host0->OnMessageReceived(
+      new WorkerHostMsg_CountFeature(worker_route_id, feature1)));
+  EXPECT_EQ(0U, renderer_host0->QueuedMessageCount());
+  EXPECT_EQ(0U, renderer_host1->QueuedMessageCount());
+
+  // SharedWorker sends WorkerHostMsg_CountFeature in
+  // EmbeddedSharedWorkerStub::CountFeature() for another feature use.
+  uint32_t feature3 = 1019;
+  EXPECT_TRUE(renderer_host0->OnMessageReceived(
+      new WorkerHostMsg_CountFeature(worker_route_id, feature3)));
+  // ViewMsg_CountFeature should be sent to all SharedWorkerConnectors
+  // connecting to this worker.
+  EXPECT_EQ(1U, renderer_host0->QueuedMessageCount());
+  CheckViewMsgCountFeature(renderer_host0.get(), connector0.get(), feature3);
+  EXPECT_EQ(1U, renderer_host1->QueuedMessageCount());
+  CheckViewMsgCountFeature(renderer_host1.get(), connector1.get(), feature3);
+
   EXPECT_EQ(1, s_update_worker_dependency_call_count_);
   renderer_host1.reset();
   // UpdateWorkerDependency should be called.
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 53a86d7..238c19b1 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -521,8 +521,9 @@
       url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
   int entry_id = controller().GetPendingEntry()->GetUniqueID();
   orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  contents()->TestDidNavigateWithSequenceNumber(
+      orig_rfh, entry_id, true, url, Referrer(), ui::PAGE_TRANSITION_TYPED,
+      false, 0, 0);
 
   // Keep the number of active frames in orig_rfh's SiteInstance non-zero so
   // that orig_rfh doesn't get deleted when it gets swapped out.
@@ -557,8 +558,9 @@
   }
 
   // DidNavigate from the pending page
-  contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  contents()->TestDidNavigateWithSequenceNumber(
+      pending_rfh, entry_id, true, url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
+      false, 1, 1);
   SiteInstance* instance2 = contents()->GetSiteInstance();
 
   // Keep the number of active frames in pending_rfh's SiteInstance
@@ -595,8 +597,9 @@
   }
 
   // DidNavigate from the back action
-  contents()->TestDidNavigate(goback_rfh, entry_id, false, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  contents()->TestDidNavigateWithSequenceNumber(
+      goback_rfh, entry_id, false, url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
+      false, 2, 0);
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(goback_rfh, main_test_rfh());
   EXPECT_EQ(instance1, contents()->GetSiteInstance());
@@ -1141,8 +1144,9 @@
   int entry_id = controller().GetPendingEntry()->GetUniqueID();
   TestRenderFrameHost* webui_rfh = main_test_rfh();
   webui_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(webui_rfh, entry_id, true, url1,
-                              ui::PAGE_TRANSITION_TYPED);
+  contents()->TestDidNavigateWithSequenceNumber(
+      webui_rfh, entry_id, true, url1, Referrer(), ui::PAGE_TRANSITION_TYPED,
+      false, 0, 0);
   NavigationEntry* entry1 = controller().GetLastCommittedEntry();
   SiteInstance* instance1 = contents()->GetSiteInstance();
 
@@ -1166,8 +1170,9 @@
   webui_rfh->PrepareForCommit();
 
   // DidNavigate from the pending page.
-  contents()->TestDidNavigate(google_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  contents()->TestDidNavigateWithSequenceNumber(
+      google_rfh, entry_id, true, url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
+      false, 1, 1);
   NavigationEntry* entry2 = controller().GetLastCommittedEntry();
   SiteInstance* instance2 = contents()->GetSiteInstance();
 
@@ -1187,8 +1192,9 @@
   entry_id = controller().GetPendingEntry()->GetUniqueID();
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(google_rfh, entry_id, true, url3,
-                              ui::PAGE_TRANSITION_TYPED);
+  contents()->TestDidNavigateWithSequenceNumber(
+      google_rfh, entry_id, true, url3, Referrer(), ui::PAGE_TRANSITION_TYPED,
+      false, 2, 2);
   NavigationEntry* entry3 = controller().GetLastCommittedEntry();
   SiteInstance* instance3 = contents()->GetSiteInstance();
 
@@ -1220,8 +1226,9 @@
       FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
 
   // DidNavigate from the first back. This aborts the second back's pending RFH.
-  contents()->TestDidNavigate(google_rfh, goback_entry->GetUniqueID(), false,
-                              url2, ui::PAGE_TRANSITION_TYPED);
+  contents()->TestDidNavigateWithSequenceNumber(
+      google_rfh, goback_entry->GetUniqueID(), false, url2, Referrer(),
+      ui::PAGE_TRANSITION_TYPED, false, 1, 1);
 
   // We should commit this page and forget about the second back.
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 6440176..3dfb828 100644
--- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -414,6 +414,8 @@
   GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
 
   // Test with invalid mandatory audio sourceID.
+  // TODO(guidou): Update error string when spec-compliant constraint resolution
+  // for audio is implemented. See http://crbug.com/657733.
   NavigateToURL(shell(), url);
   EXPECT_EQ("DevicesNotFoundError", ExecuteJavascriptAndReturnResult(
       GenerateGetUserMediaWithMandatorySourceID(
@@ -422,13 +424,15 @@
           video_ids[0])));
 
   // Test with invalid mandatory video sourceID.
-  EXPECT_EQ("DevicesNotFoundError", ExecuteJavascriptAndReturnResult(
-      GenerateGetUserMediaWithMandatorySourceID(
-          kGetUserMediaAndExpectFailure,
-          audio_ids[0],
-          "something invalid")));
+  EXPECT_EQ("ConstraintNotSatisfiedError",
+            ExecuteJavascriptAndReturnResult(
+                GenerateGetUserMediaWithMandatorySourceID(
+                    kGetUserMediaAndExpectFailure, audio_ids[0],
+                    "something invalid")));
 
   // Test with empty mandatory audio sourceID.
+  // TODO(guidou): Update error string when spec-compliant constraint resolution
+  // for audio is implemented. See http://crbug.com/657733.
   EXPECT_EQ("DevicesNotFoundError", ExecuteJavascriptAndReturnResult(
       GenerateGetUserMediaWithMandatorySourceID(
           kGetUserMediaAndExpectFailure,
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index f360e88c..d72cd20 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -231,7 +231,6 @@
     "//content/common",
     "//content/public/common:common_sources",
     "//crypto:platform",
-    "//device/power_monitor/public/cpp",
     "//gpu/command_buffer/client",
     "//ipc",
     "//ipc:mojom",
@@ -239,7 +238,8 @@
     "//mojo/common",
     "//mojo/edk/system",
     "//net",
-    "//services/device/public/interfaces",
+    "//services/device/public/cpp/power_monitor",
+    "//services/device/public/interfaces:constants",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/interfaces",
     "//services/service_manager/runner/common",
diff --git a/content/child/DEPS b/content/child/DEPS
index 54654a30..3f315c9 100644
--- a/content/child/DEPS
+++ b/content/child/DEPS
@@ -9,7 +9,7 @@
 
   "+content/app/strings/grit",  # For generated headers
   "+content/public/child",
-  "+device/power_monitor/public",
+  "+services/device/public/cpp/power_monitor",
   "+services/device/public/interfaces",
   "+services/service_manager",
   "+services/service_manager",
diff --git a/content/child/background_sync/PRESUBMIT.py b/content/child/background_sync/PRESUBMIT.py
deleted file mode 100644
index 0d969d3..0000000
--- a/content/child/background_sync/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for src/content/child/background_sync/
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index dd7af71..977d87a 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -54,7 +54,6 @@
 #include "content/public/common/mojo_channel_switches.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
-#include "device/power_monitor/public/cpp/power_monitor_broadcast_source.h"
 #include "ipc/ipc_channel_mojo.h"
 #include "ipc/ipc_logging.h"
 #include "ipc/ipc_platform_file.h"
@@ -66,6 +65,7 @@
 #include "mojo/edk/embedder/scoped_ipc_support.h"
 #include "mojo/public/cpp/system/buffer.h"
 #include "mojo/public/cpp/system/platform_handle.h"
+#include "services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h"
 #include "services/device/public/interfaces/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_factory.h"
@@ -357,8 +357,6 @@
 
 ChildThreadImpl::ChildThreadImpl()
     : route_provider_binding_(this),
-      associated_interface_provider_bindings_(
-          mojo::BindingSetDispatchMode::WITH_CONTEXT),
       router_(this),
       channel_connected_factory_(
           new base::WeakPtrFactory<ChildThreadImpl>(this)),
@@ -368,8 +366,6 @@
 
 ChildThreadImpl::ChildThreadImpl(const Options& options)
     : route_provider_binding_(this),
-      associated_interface_provider_bindings_(
-          mojo::BindingSetDispatchMode::WITH_CONTEXT),
       router_(this),
       browser_process_io_runner_(options.browser_process_io_runner),
       channel_connected_factory_(
@@ -856,15 +852,14 @@
     int32_t routing_id,
     mojom::AssociatedInterfaceProviderAssociatedRequest request) {
   associated_interface_provider_bindings_.AddBinding(
-      this, std::move(request),
-      reinterpret_cast<void*>(static_cast<uintptr_t>(routing_id)));
+      this, std::move(request), routing_id);
 }
 
 void ChildThreadImpl::GetAssociatedInterface(
     const std::string& name,
     mojom::AssociatedInterfaceAssociatedRequest request) {
-  int32_t routing_id = static_cast<int32_t>(reinterpret_cast<uintptr_t>(
-      associated_interface_provider_bindings_.dispatch_context()));
+  int32_t routing_id =
+      associated_interface_provider_bindings_.dispatch_context();
   Listener* route = router_.GetRoute(routing_id);
   if (route)
     route->OnAssociatedInterfaceRequest(name, request.PassHandle());
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index 012cb43..29a3f7dd 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -265,7 +265,7 @@
   service_manager::ServiceInfo browser_info_;
 
   mojo::AssociatedBinding<mojom::RouteProvider> route_provider_binding_;
-  mojo::AssociatedBindingSet<mojom::AssociatedInterfaceProvider>
+  mojo::AssociatedBindingSet<mojom::AssociatedInterfaceProvider, int32_t>
       associated_interface_provider_bindings_;
   mojom::RouteProviderAssociatedPtr remote_route_provider_;
 
diff --git a/content/child/memory/child_memory_coordinator_impl.cc b/content/child/memory/child_memory_coordinator_impl.cc
index 7724519a..8477942 100644
--- a/content/child/memory/child_memory_coordinator_impl.cc
+++ b/content/child/memory/child_memory_coordinator_impl.cc
@@ -59,11 +59,11 @@
 }
 
 void ChildMemoryCoordinatorImpl::PurgeMemory() {
-  base::MemoryCoordinatorClientRegistry::GetInstance()->PurgeMemory();
-  // TODO(bashi): Remove following notification when all clients implement
+  // TODO(bashi): Remove Notify() call when all clients implement
   // OnPurgeMemory();
   base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(
       base::MemoryState::SUSPENDED);
+  base::MemoryCoordinatorClientRegistry::GetInstance()->PurgeMemory();
 }
 
 void ChildMemoryCoordinatorImpl::OnStateChange(mojom::MemoryState state) {
diff --git a/content/child/notifications/PRESUBMIT.py b/content/child/notifications/PRESUBMIT.py
deleted file mode 100644
index 4fbc9a7..0000000
--- a/content/child/notifications/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for notifications.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/child/push_messaging/PRESUBMIT.py b/content/child/push_messaging/PRESUBMIT.py
deleted file mode 100644
index aa4ae97d..0000000
--- a/content/child/push_messaging/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for Push Messaging.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/child/service_worker/PRESUBMIT.py b/content/child/service_worker/PRESUBMIT.py
deleted file mode 100644
index 928d9fe0..0000000
--- a/content/child/service_worker/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for service_worker.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/child/v8_value_converter_impl.cc b/content/child/v8_value_converter_impl.cc
index 5dcf636..dd36788 100644
--- a/content/child/v8_value_converter_impl.cc
+++ b/content/child/v8_value_converter_impl.cc
@@ -17,9 +17,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/values.h"
-#include "third_party/WebKit/public/web/WebArrayBuffer.h"
-#include "third_party/WebKit/public/web/WebArrayBufferConverter.h"
-#include "third_party/WebKit/public/web/WebArrayBufferView.h"
 #include "v8/include/v8.h"
 
 namespace content {
@@ -339,11 +336,11 @@
     v8::Isolate* isolate,
     v8::Local<v8::Object> creation_context,
     const base::BinaryValue* value) const {
-  blink::WebArrayBuffer buffer =
-      blink::WebArrayBuffer::create(value->GetSize(), 1);
-  memcpy(buffer.data(), value->GetBuffer(), value->GetSize());
-  return blink::WebArrayBufferConverter::toV8Value(
-      &buffer, creation_context, isolate);
+  DCHECK(creation_context->CreationContext() == isolate->GetCurrentContext());
+  v8::Local<v8::ArrayBuffer> buffer =
+      v8::ArrayBuffer::New(isolate, value->GetSize());
+  memcpy(buffer->GetContents().Data(), value->GetBuffer(), value->GetSize());
+  return buffer;
 }
 
 std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8ValueImpl(
@@ -497,27 +494,20 @@
       return out;
   }
 
-  char* data = NULL;
-  size_t length = 0;
-
-  std::unique_ptr<blink::WebArrayBuffer> array_buffer(
-      blink::WebArrayBufferConverter::createFromV8Value(val, isolate));
-  std::unique_ptr<blink::WebArrayBufferView> view;
-  if (array_buffer) {
-    data = reinterpret_cast<char*>(array_buffer->data());
-    length = array_buffer->byteLength();
+  if (val->IsArrayBuffer()) {
+    auto contents = val.As<v8::ArrayBuffer>()->GetContents();
+    return base::BinaryValue::CreateWithCopiedBuffer(
+        static_cast<const char*>(contents.Data()), contents.ByteLength());
+  } else if (val->IsArrayBufferView()) {
+    v8::Local<v8::ArrayBufferView> view = val.As<v8::ArrayBufferView>();
+    size_t byte_length = view->ByteLength();
+    auto buffer = base::MakeUnique<char[]>(byte_length);
+    view->CopyContents(buffer.get(), byte_length);
+    return base::MakeUnique<base::BinaryValue>(std::move(buffer), byte_length);
   } else {
-    view.reset(blink::WebArrayBufferView::createFromV8Value(val));
-    if (view) {
-      data = reinterpret_cast<char*>(view->baseAddress()) + view->byteOffset();
-      length = view->byteLength();
-    }
-  }
-
-  if (data)
-    return base::BinaryValue::CreateWithCopiedBuffer(data, length);
-  else
+    NOTREACHED() << "Only ArrayBuffer and ArrayBufferView should get here.";
     return nullptr;
+  }
 }
 
 std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Object(
diff --git a/content/child/v8_value_converter_impl_unittest.cc b/content/child/v8_value_converter_impl_unittest.cc
index a403751b..84d03fc 100644
--- a/content/child/v8_value_converter_impl_unittest.cc
+++ b/content/child/v8_value_converter_impl_unittest.cc
@@ -1108,8 +1108,29 @@
   EXPECT_TRUE(
       base::Value::Equals(reference_array_value.get(), array_value.get()));
 
-  // Not testing ArrayBuffers as V8ValueConverter uses blink helpers and
-  // this requires having blink to be initialized.
+  const char kExampleData[] = {1, 2, 3, 4, 5};
+  v8::Local<v8::ArrayBuffer> array_buffer(
+      v8::ArrayBuffer::New(isolate_, sizeof(kExampleData)));
+  memcpy(array_buffer->GetContents().Data(), kExampleData,
+         sizeof(kExampleData));
+  std::unique_ptr<base::Value> binary_value(
+      converter.FromV8Value(array_buffer, context));
+  ASSERT_TRUE(binary_value);
+  std::unique_ptr<base::Value> reference_binary_value(
+      base::BinaryValue::CreateWithCopiedBuffer(kExampleData,
+                                                sizeof(kExampleData)));
+  EXPECT_TRUE(
+      base::Value::Equals(reference_binary_value.get(), binary_value.get()));
+
+  v8::Local<v8::ArrayBufferView> array_buffer_view(
+      v8::Uint8Array::New(array_buffer, 1, 3));
+  std::unique_ptr<base::Value> binary_view_value(
+      converter.FromV8Value(array_buffer_view, context));
+  ASSERT_TRUE(binary_view_value);
+  std::unique_ptr<base::Value> reference_binary_view_value(
+      base::BinaryValue::CreateWithCopiedBuffer(&kExampleData[1], 3));
+  EXPECT_TRUE(base::Value::Equals(reference_binary_view_value.get(),
+                                  binary_view_value.get()));
 
   v8::Local<v8::Number> number(v8::Number::New(isolate_, 0.0));
   std::unique_ptr<base::Value> number_value(
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 87e95ee..2e169434 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -601,7 +601,6 @@
   public_deps = [
     "//components/leveldb/public/interfaces",
     "//content/public/common:interfaces",
-    "//device/power_monitor/public/interfaces",
 
     # TODO(mcasas): remove the following dep after https://crbug.com/653994
     "//gpu/ipc/common:interfaces",
diff --git a/content/common/bluetooth/PRESUBMIT.py b/content/common/bluetooth/PRESUBMIT.py
deleted file mode 100644
index 5af5a08..0000000
--- a/content/common/bluetooth/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +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.
-
-"""Presubmit script.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/common/frame_message_enums.h b/content/common/frame_message_enums.h
index 3d9f84a..ef1d22d 100644
--- a/content/common/frame_message_enums.h
+++ b/content/common/frame_message_enums.h
@@ -29,12 +29,36 @@
     // Like RESTORE, except that the navigation contains POST data.
     RESTORE_WITH_POST,
 
-    // Navigation type not categorized by the other types.
-    NORMAL,
+    // History navigation inside the same document.
+    HISTORY_SAME_DOCUMENT,
+
+    // History navigation to a different document.
+    HISTORY_DIFFERENT_DOCUMENT,
+
+    // Navigation inside the same document. It occurs when the part of the url
+    // that is modified is after the '#' part.
+    SAME_DOCUMENT,
+
+    // Navigation to another document.
+    DIFFERENT_DOCUMENT,
 
     // Last guard value, so we can use it for validity checks.
-    NAVIGATE_TYPE_LAST = NORMAL,
+    NAVIGATE_TYPE_LAST = DIFFERENT_DOCUMENT,
   };
+
+  static bool IsReload(Value value) {
+    return value == RELOAD || value == RELOAD_BYPASSING_CACHE ||
+           value == RELOAD_ORIGINAL_REQUEST_URL;
+  }
+
+  static bool IsSameDocument(Value value) {
+    return value == SAME_DOCUMENT || value == HISTORY_SAME_DOCUMENT;
+  }
+
+  static bool IsHistory(Value value) {
+    return value == HISTORY_SAME_DOCUMENT ||
+           value == HISTORY_DIFFERENT_DOCUMENT;
+  }
 };
 
 struct FrameMsg_UILoadMetricsReportType {
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 2eea1d1..eec10530 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -376,7 +376,6 @@
   IPC_STRUCT_TRAITS_MEMBER(can_load_local_resources)
   IPC_STRUCT_TRAITS_MEMBER(page_state)
   IPC_STRUCT_TRAITS_MEMBER(nav_entry_id)
-  IPC_STRUCT_TRAITS_MEMBER(is_same_document_history_load)
   IPC_STRUCT_TRAITS_MEMBER(is_history_navigation_in_new_child)
   IPC_STRUCT_TRAITS_MEMBER(subframe_unique_names)
   IPC_STRUCT_TRAITS_MEMBER(has_committed_real_load)
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc
index 0bd0621b..0d64f3b 100644
--- a/content/common/navigation_params.cc
+++ b/content/common/navigation_params.cc
@@ -22,8 +22,6 @@
 
   // Javascript URLs, about:blank, srcdoc should not send a request
   // to the network stack.
-  // TODO(clamy): same document navigations should not send requests to the
-  // network stack. Neither should pushState/popState.
   return !url::IsAboutBlank(url) && !url.SchemeIs(url::kJavaScriptScheme) &&
          !url.is_empty() && !url.SchemeIs(url::kContentIDScheme) &&
          url != content::kAboutSrcDocURL;
@@ -31,7 +29,7 @@
 
 CommonNavigationParams::CommonNavigationParams()
     : transition(ui::PAGE_TRANSITION_LINK),
-      navigation_type(FrameMsg_Navigate_Type::NORMAL),
+      navigation_type(FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT),
       allow_download(true),
       should_replace_current_entry(false),
       report_type(FrameMsg_UILoadMetricsReportType::NO_REPORT),
@@ -134,7 +132,6 @@
     : is_overriding_user_agent(false),
       can_load_local_resources(false),
       nav_entry_id(0),
-      is_same_document_history_load(false),
       is_history_navigation_in_new_child(false),
       has_committed_real_load(false),
       intended_as_new_entry(false),
@@ -155,7 +152,6 @@
     bool can_load_local_resources,
     const PageState& page_state,
     int nav_entry_id,
-    bool is_same_document_history_load,
     bool is_history_navigation_in_new_child,
     std::map<std::string, bool> subframe_unique_names,
     bool has_committed_real_load,
@@ -171,7 +167,6 @@
       can_load_local_resources(can_load_local_resources),
       page_state(page_state),
       nav_entry_id(nav_entry_id),
-      is_same_document_history_load(is_same_document_history_load),
       is_history_navigation_in_new_child(is_history_navigation_in_new_child),
       subframe_unique_names(subframe_unique_names),
       has_committed_real_load(has_committed_real_load),
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h
index 0cdafb5..c47da6b8 100644
--- a/content/common/navigation_params.h
+++ b/content/common/navigation_params.h
@@ -231,7 +231,6 @@
                           bool can_load_local_resources,
                           const PageState& page_state,
                           int nav_entry_id,
-                          bool is_same_document_history_load,
                           bool is_history_navigation_in_new_child,
                           std::map<std::string, bool> subframe_unique_names,
                           bool has_committed_real_load,
@@ -268,10 +267,6 @@
   // the resulting FrameHostMsg_DidCommitProvisionalLoad message.
   int nav_entry_id;
 
-  // For history navigations, this indicates whether the load will stay within
-  // the same document.  Defaults to false.
-  bool is_same_document_history_load;
-
   // Whether this is a history navigation in a newly created child frame, in
   // which case the browser process is instructing the renderer process to load
   // a URL from a session history item.  Defaults to false.
diff --git a/content/common/sandbox_mac.h b/content/common/sandbox_mac.h
index 39f2301..a15440e 100644
--- a/content/common/sandbox_mac.h
+++ b/content/common/sandbox_mac.h
@@ -20,38 +20,6 @@
 
 namespace content {
 
-// This class wraps the C-style sandbox APIs in a class to ensure proper
-// initialization and cleanup.
-class CONTENT_EXPORT SandboxCompiler {
- public:
-  explicit SandboxCompiler(const std::string& profile_str);
-
-  ~SandboxCompiler();
-
-  // Inserts a boolean into the parameters key/value map. A duplicate key is not
-  // allowed, and will cause the function to return false. The value is not
-  // inserted in this case.
-  bool InsertBooleanParam(const std::string& key, bool value);
-
-  // Inserts a string into the parameters key/value map. A duplicate key is not
-  // allowed, and will cause the function to return false. The value is not
-  // inserted in this case.
-  bool InsertStringParam(const std::string& key, const std::string& value);
-
-  // Compiles and applies the profile; returns true on success.
-  bool CompileAndApplyProfile(std::string* error);
-
- private:
-  // Storage of the key/value pairs of strings that are used in the sandbox
-  // profile.
-  std::map<std::string, std::string> params_map_;
-
-  // The sandbox profile source code.
-  const std::string profile_str_;
-
-  DISALLOW_COPY_AND_ASSIGN(SandboxCompiler);
-};
-
 class CONTENT_EXPORT Sandbox {
  public:
 
diff --git a/content/common/sandbox_mac.mm b/content/common/sandbox_mac.mm
index ccfe867..2c21995 100644
--- a/content/common/sandbox_mac.mm
+++ b/content/common/sandbox_mac.mm
@@ -36,7 +36,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "media/gpu/vt_video_decode_accelerator_mac.h"
-#include "sandbox/mac/seatbelt.h"
+#include "sandbox/mac/sandbox_compiler.h"
 #include "third_party/icu/source/common/unicode/uchar.h"
 #include "ui/base/layout.h"
 #include "ui/gl/init/gl_factory.h"
@@ -118,43 +118,6 @@
 
 }  // namespace
 
-SandboxCompiler::SandboxCompiler(const std::string& profile_str)
-    : params_map_(), profile_str_(profile_str) {
-}
-
-SandboxCompiler::~SandboxCompiler() {
-}
-
-bool SandboxCompiler::InsertBooleanParam(const std::string& key, bool value) {
-  return params_map_.insert(std::make_pair(key, value ? "TRUE" : "FALSE"))
-      .second;
-}
-
-bool SandboxCompiler::InsertStringParam(const std::string& key,
-                                        const std::string& value) {
-  return params_map_.insert(std::make_pair(key, value)).second;
-}
-
-bool SandboxCompiler::CompileAndApplyProfile(std::string* error) {
-  char* error_internal = nullptr;
-  std::vector<const char*> params;
-
-  for (const auto& kv : params_map_) {
-    params.push_back(kv.first.c_str());
-    params.push_back(kv.second.c_str());
-  }
-  // The parameters array must be null terminated.
-  params.push_back(static_cast<const char*>(0));
-
-  if (sandbox::Seatbelt::InitWithParams(profile_str_.c_str(), 0, params.data(),
-                                        &error_internal)) {
-    error->assign(error_internal);
-    sandbox::Seatbelt::FreeError(error_internal);
-    return false;
-  }
-  return true;
-}
-
 // static
 bool Sandbox::QuotePlainString(const std::string& src_utf8, std::string* dst) {
   dst->clear();
@@ -425,7 +388,7 @@
     return false;
   }
 
-  SandboxCompiler compiler(sandbox_data);
+  sandbox::SandboxCompiler compiler(sandbox_data);
 
   if (!allowed_dir.empty()) {
     // Add the sandbox parameters necessary to access the given directory.
diff --git a/content/common/sandbox_mac_diraccess_unittest.mm b/content/common/sandbox_mac_diraccess_unittest.mm
index 322b231d..828395f 100644
--- a/content/common/sandbox_mac_diraccess_unittest.mm
+++ b/content/common/sandbox_mac_diraccess_unittest.mm
@@ -20,6 +20,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/multiprocess_test.h"
 #include "content/common/sandbox_mac.h"
+#include "sandbox/mac/sandbox_compiler.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/multiprocess_func_list.h"
 
@@ -205,7 +206,7 @@
       "perm_dir)))))";
 
   // Setup the parameters to pass to the sandbox.
-  SandboxCompiler compiler(sandbox_profile);
+  sandbox::SandboxCompiler compiler(sandbox_profile);
   CHECK(compiler.InsertStringParam("PERMITTED_DIR", final_allowed_dir));
 
   // Enable Sandbox.
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 3b7b3c4..b443ce9 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -538,7 +538,19 @@
 
 // Sent when the worker has connected.
 // This message is sent only if the worker successfully loaded the script.
-IPC_MESSAGE_ROUTED0(ViewMsg_WorkerConnected)
+// |used_features| is the set of features that the worker has used. The values
+// must be from blink::UseCounter::Feature enum.
+IPC_MESSAGE_ROUTED1(ViewMsg_WorkerConnected,
+                    std::set<uint32_t> /* used_features */)
+
+// Sent when the worker is destroyed.
+IPC_MESSAGE_ROUTED0(ViewMsg_WorkerDestroyed)
+
+// Sent when the worker calls API that should be recored in UseCounter.
+// |feature| must be one of the values from blink::UseCounter::Feature
+// enum.
+IPC_MESSAGE_ROUTED1(ViewMsg_CountFeatureOnSharedWorker,
+                    uint32_t /* feature */)
 
 // Sent by the browser to synchronize with the next compositor frame. Used only
 // for tests.
diff --git a/content/common/worker_messages.h b/content/common/worker_messages.h
index e49ce80..e0405087 100644
--- a/content/common/worker_messages.h
+++ b/content/common/worker_messages.h
@@ -89,6 +89,14 @@
 // WorkerHost messages
 // These are messages sent from the worker (renderer process) to the worker
 // host (browser process).
+
+// Sent when the worker calls API that should be recored in UseCounter.
+// |feature| must be one of the values from blink::UseCounter::Feature
+// enum.
+IPC_MESSAGE_CONTROL2(WorkerHostMsg_CountFeature,
+                     int /* worker_route_id */,
+                     uint32_t /* feature */)
+
 IPC_MESSAGE_CONTROL1(WorkerHostMsg_WorkerContextClosed,
                      int /* worker_route_id */)
 
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn
index 63852e1..50ebf15 100644
--- a/content/gpu/BUILD.gn
+++ b/content/gpu/BUILD.gn
@@ -102,10 +102,6 @@
 
   if (use_ozone) {
     deps += [ "//ui/ozone" ]
-
-    if (ozone_platform_x11) {
-      defines = [ "OZONE_X11" ]
-    }
   }
 
   if (enable_vulkan) {
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 54791f6..923b1fd 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -81,6 +81,10 @@
 #include "content/common/sandbox_mac.h"
 #endif
 
+#if defined(USE_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
+#endif
+
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
 #include "media/gpu/vaapi_wrapper.h"
 #endif
@@ -218,13 +222,11 @@
     // and https://crbug.com/326995.
     main_message_loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
     event_source = ui::PlatformEventSource::CreateDefault();
-#elif defined(USE_OZONE) && defined(OZONE_X11)
-    // If we might be running Ozone X11 we need a UI loop to grab Expose events.
-    // See GLSurfaceGLX and https://crbug.com/326995.
-    main_message_loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
 #elif defined(USE_OZONE)
-    main_message_loop.reset(
-        new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
+    // The MessageLoop type required depends on the Ozone platform selected at
+    // runtime.
+    main_message_loop.reset(new base::MessageLoop(
+        ui::OzonePlatform::EnsureInstance()->GetMessageLoopTypeForGpu()));
 #elif defined(OS_LINUX)
 #error "Unsupported Linux platform."
 #elif defined(OS_MACOSX)
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
index be561324..6ef25210 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
@@ -4,14 +4,8 @@
 
 package org.chromium.content.browser;
 
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
 import android.view.KeyEvent;
 
-import org.chromium.base.Log;
-import org.chromium.base.metrics.RecordUserAction;
-
 /**
  *  Main callback class used by ContentView.
  *
@@ -20,103 +14,21 @@
  *  The memory and reference ownership of this class is unusual - see the .cc file and ContentView
  *  for more details.
  *
- *  TODO(mkosiba): Rid this class of default implementations. This class is used by both WebView and
- *  the browser and we don't want a the browser-specific default implementation to accidentally leak
- *  over to WebView.
- *
  *  WARNING: ConteViewClient is going away. Do not add new stuff in this class.
  */
 public class ContentViewClient {
-    // Tag used for logging.
-    private static final String TAG = "cr_ContentViewClient";
-
-    private static final String GEO_SCHEME = "geo";
-    private static final String TEL_SCHEME = "tel";
-    private static final String MAILTO_SCHEME = "mailto";
-
-    /**
-     * Called whenever the background color of the page changes as notified by WebKit.
-     * @param color The new ARGB color of the page background.
-     */
-    public void onBackgroundColorChanged(int color) {
-    }
-
-    /**
-     * Notifies the client of the position of the top controls.
-     * @param topControlsOffsetY The Y offset of the top controls in physical pixels.
-     * @param topContentOffsetY The Y offset of the content in physical pixels.
-     */
-    public void onTopControlsChanged(float browserControlsOffsetY, float topContentOffsetY) {}
-
-    /**
-     * Notifies the client of the position of the bottom controls.
-     * @param bottomControlsOffsetY The Y offset of the bottom controls in physical pixels.
-     * @param bottomContentOffsetY The Y offset of the content in physical pixels.
-     */
-    public void onBottomControlsChanged(float bottomControlsOffsetY, float bottomContentOffsetY) { }
-
-    public boolean shouldOverrideKeyEvent(KeyEvent event) {
-        int keyCode = event.getKeyCode();
-
-        if (!shouldPropagateKey(keyCode)) return true;
-
-        return false;
-    }
-
     /**
      * Called when an ImeEvent is sent to the page. Can be used to know when some text is entered
      * in a page.
      */
-    public void onImeEvent() {
-    }
+    public void onImeEvent() {}
 
     /**
      * Notified when the editability of the focused node changes.
      *
      * @param editable Whether the focused node is editable.
      */
-    public void onFocusedNodeEditabilityChanged(boolean editable) {
-    }
-
-    /**
-     * Check whether the given scheme is one of the acceptable schemes for onStartContentIntent.
-     *
-     * @param scheme The scheme to check.
-     * @return true if the scheme is okay, false if it should be blocked.
-     */
-    protected boolean isAcceptableContentIntentScheme(String scheme) {
-        return GEO_SCHEME.equals(scheme) || TEL_SCHEME.equals(scheme)
-                || MAILTO_SCHEME.equals(scheme);
-    }
-
-    /**
-     * Called when a new content intent is requested to be started.
-     */
-    public void onStartContentIntent(Context context, String intentUrl, boolean isMainFrame) {
-        Intent intent;
-        // Perform generic parsing of the URI to turn it into an Intent.
-        try {
-            intent = Intent.parseUri(intentUrl, Intent.URI_INTENT_SCHEME);
-
-            String scheme = intent.getScheme();
-            if (!isAcceptableContentIntentScheme(scheme)) {
-                Log.w(TAG, "Invalid scheme for URI %s", intentUrl);
-                return;
-            }
-
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        } catch (Exception ex) {
-            Log.w(TAG, "Bad URI %s", intentUrl, ex);
-            return;
-        }
-
-        try {
-            RecordUserAction.record("Android.ContentDetectorActivated");
-            context.startActivity(intent);
-        } catch (ActivityNotFoundException ex) {
-            Log.w(TAG, "No application can handle %s", intentUrl);
-        }
-    }
+    public void onFocusedNodeEditabilityChanged(boolean editable) {}
 
     /**
      * Check whether a key should be propagated to the embedder or not.
@@ -147,33 +59,10 @@
     }
 
     /**
-     * Returns the left system window inset in pixels. The system window inset represents the area
-     * of a full-screen window that is partially or fully obscured by the status bar, navigation
-     * bar, IME or other system windows.
-     * @return The left system window inset.
+     * @see {@link #shouldPropagateKey(int)
      */
-    public int getSystemWindowInsetLeft() {
-        return 0;
-    }
-
-    /**
-     * Returns the top system window inset in pixels. The system window inset represents the area of
-     * a full-screen window that is partially or fully obscured by the status bar, navigation bar,
-     * IME or other system windows.
-     * @return The top system window inset.
-     */
-    public int getSystemWindowInsetTop() {
-        return 0;
-    }
-
-    /**
-     * Returns the right system window inset in pixels. The system window inset represents the area
-     * of a full-screen window that is partially or fully obscured by the status bar, navigation
-     * bar, IME or other system windows.
-     * @return The right system window inset.
-     */
-    public int getSystemWindowInsetRight() {
-        return 0;
+    public boolean shouldOverrideKeyEvent(KeyEvent event) {
+        return !shouldPropagateKey(event.getKeyCode());
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 78232fa..6d48071 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -828,11 +828,6 @@
         return mContentViewClient;
     }
 
-    @CalledByNative
-    private void onBackgroundColorChanged(int color) {
-        getContentViewClient().onBackgroundColorChanged(color);
-    }
-
     /**
      * @return Viewport width in physical pixels as set from onSizeChanged.
      */
@@ -1804,7 +1799,6 @@
             float minPageScaleFactor, float maxPageScaleFactor, float contentWidth,
             float contentHeight, float viewportWidth, float viewportHeight,
             float browserControlsHeightDp, float browserControlsShownRatio,
-            float bottomControlsHeightDp, float bottomControlsShownRatio,
             boolean isMobileOptimizedHint, boolean hasInsertionMarker,
             boolean isInsertionMarkerVisible, float insertionMarkerHorizontal,
             float insertionMarkerTop, float insertionMarkerBottom) {
@@ -1819,8 +1813,6 @@
                 mViewportHeightPix / (deviceScale * pageScaleFactor));
         final float topBarShownPix =
                 browserControlsHeightDp * deviceScale * browserControlsShownRatio;
-        final float bottomBarShownPix = bottomControlsHeightDp * deviceScale
-                * bottomControlsShownRatio;
 
         final boolean contentSizeChanged =
                 contentWidth != mRenderCoordinates.getContentWidthCss()
@@ -1836,8 +1828,6 @@
                 || scrollOffsetY != mRenderCoordinates.getScrollY();
         final boolean topBarChanged = Float.compare(topBarShownPix,
                 mRenderCoordinates.getContentOffsetYPix()) != 0;
-        final boolean bottomBarChanged = Float.compare(bottomBarShownPix, mRenderCoordinates
-                .getContentOffsetYPixBottom()) != 0;
 
         final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged;
 
@@ -1856,7 +1846,7 @@
                 contentWidth, contentHeight,
                 viewportWidth, viewportHeight,
                 pageScaleFactor, minPageScaleFactor, maxPageScaleFactor,
-                topBarShownPix, bottomBarShownPix);
+                topBarShownPix);
 
         if (scrollChanged || topBarChanged) {
             for (mGestureStateListenersIterator.rewind();
@@ -1875,15 +1865,6 @@
             }
         }
 
-        if (topBarChanged) {
-            float topBarTranslate = topBarShownPix - browserControlsHeightDp * deviceScale;
-            getContentViewClient().onTopControlsChanged(topBarTranslate, topBarShownPix);
-        }
-        if (bottomBarChanged) {
-            float bottomBarTranslate = bottomControlsHeightDp * deviceScale - bottomBarShownPix;
-            getContentViewClient().onBottomControlsChanged(bottomBarTranslate, bottomBarShownPix);
-        }
-
         if (mBrowserAccessibilityManager != null) {
             mBrowserAccessibilityManager.notifyFrameInfoInitialized();
         }
@@ -2303,11 +2284,6 @@
         return mRenderCoordinates.getPageScaleFactor();
     }
 
-    @CalledByNative
-    private void startContentIntent(String contentUrl, boolean isMainFrame) {
-        getContentViewClient().onStartContentIntent(getContext(), contentUrl, isMainFrame);
-    }
-
     @Override
     public void onAccessibilityStateChanged(boolean enabled) {
         setAccessibilityState(enabled);
diff --git a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
index bdc90185..c7d1eff 100644
--- a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
@@ -22,6 +22,9 @@
 
 @JNINamespace("content")
 class InterfaceRegistrarImpl {
+
+    private static boolean sHasRegisteredRegistrars;
+
     @CalledByNative
     static void createInterfaceRegistryForContext(int nativeHandle, Context applicationContext) {
         ensureContentRegistrarsAreRegistered();
@@ -48,25 +51,25 @@
                 new ContentWebContentsInterfaceRegistrar());
     }
 
-    private static boolean sHasRegisteredRegistrars;
-}
-
-class ContentContextInterfaceRegistrar implements InterfaceRegistrar<Context> {
-    @Override
-    public void registerInterfaces(InterfaceRegistry registry, final Context applicationContext) {
-        registry.addInterface(
-                VibrationManager.MANAGER, new VibrationManagerImpl.Factory(applicationContext));
-        registry.addInterface(
-                BatteryMonitor.MANAGER, new BatteryMonitorFactory(applicationContext));
-        registry.addInterface(FaceDetectionProvider.MANAGER,
-                new FaceDetectionProviderImpl.Factory(applicationContext));
-        // TODO(avayvod): Register the PresentationService implementation here.
+    private static class ContentContextInterfaceRegistrar implements InterfaceRegistrar<Context> {
+        @Override
+        public void registerInterfaces(
+                InterfaceRegistry registry, final Context applicationContext) {
+            registry.addInterface(
+                    VibrationManager.MANAGER, new VibrationManagerImpl.Factory(applicationContext));
+            registry.addInterface(
+                    BatteryMonitor.MANAGER, new BatteryMonitorFactory(applicationContext));
+            registry.addInterface(FaceDetectionProvider.MANAGER,
+                    new FaceDetectionProviderImpl.Factory(applicationContext));
+            // TODO(avayvod): Register the PresentationService implementation here.
+        }
     }
-}
 
-class ContentWebContentsInterfaceRegistrar implements InterfaceRegistrar<WebContents> {
-    @Override
-    public void registerInterfaces(InterfaceRegistry registry, final WebContents webContents) {
-        registry.addInterface(Nfc.MANAGER, new NfcFactory(webContents));
+    private static class ContentWebContentsInterfaceRegistrar
+            implements InterfaceRegistrar<WebContents> {
+        @Override
+        public void registerInterfaces(InterfaceRegistry registry, final WebContents webContents) {
+            registry.addInterface(Nfc.MANAGER, new NfcFactory(webContents));
+        }
     }
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java b/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java
index fcce242..d4bd795 100644
--- a/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java
+++ b/content/public/android/java/src/org/chromium/content/browser/RenderCoordinates.java
@@ -46,7 +46,6 @@
     private float mWheelScrollFactor;
 
     private float mTopContentOffsetYPix;
-    private float mBottomContentOffsetYPix;
 
     private boolean mHasFrameInfo;
 
@@ -87,14 +86,13 @@
             float contentWidthCss, float contentHeightCss,
             float viewportWidthCss, float viewportHeightCss,
             float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor,
-            float contentOffsetYPix, float contentOffsetYPixBottom) {
+            float contentOffsetYPix) {
         mScrollXCss = scrollXCss;
         mScrollYCss = scrollYCss;
         mPageScaleFactor = pageScaleFactor;
         mMinPageScaleFactor = minPageScaleFactor;
         mMaxPageScaleFactor = maxPageScaleFactor;
         mTopContentOffsetYPix = contentOffsetYPix;
-        mBottomContentOffsetYPix = contentOffsetYPixBottom;
 
         updateContentSizeCss(contentWidthCss, contentHeightCss);
         mLastFrameViewportWidthCss = viewportWidthCss;
@@ -333,13 +331,6 @@
     }
 
     /**
-     * @return The Physical on-screen Y offset amount below the bottom controls.
-     */
-    public float getContentOffsetYPixBottom() {
-        return mBottomContentOffsetYPix;
-    }
-
-    /**
      * @return Current page scale factor (maps CSS pixels to DIP pixels).
      */
     public float getPageScaleFactor() {
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java
index 3ecf1a2..9144b56 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java
@@ -6,13 +6,15 @@
 
 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
 
+import android.app.Activity;
 import android.net.Uri;
 
+import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
-import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnStartContentIntentHelper;
+import org.chromium.content_shell.ShellViewAndroidDelegate.ContentIntentHandler;
 import org.chromium.content_shell_apk.ContentShellTestBase;
 
 import java.util.concurrent.TimeUnit;
@@ -25,6 +27,41 @@
     private static final long WAIT_TIMEOUT_SECONDS = scaleTimeout(10);
 
     private TestCallbackHelperContainer mCallbackHelper;
+    private TestContentIntentHandler mContentIntentHandler;
+
+    /**
+     * CallbackHelper for OnStartContentIntent.
+     */
+    private static class OnStartContentIntentHelper extends CallbackHelper {
+        private String mIntentUrl;
+        public void notifyCalled(String intentUrl) {
+            mIntentUrl = intentUrl;
+            notifyCalled();
+        }
+        public String getIntentUrl() {
+            assert getCallCount() > 0;
+            return mIntentUrl;
+        }
+    }
+
+    /**
+     * ContentIntentHandler impl to test content detection.
+     */
+    private static class TestContentIntentHandler implements ContentIntentHandler {
+        private OnStartContentIntentHelper mOnStartContentIntentHelper;
+
+        public OnStartContentIntentHelper getOnStartContentIntentHelper() {
+            if (mOnStartContentIntentHelper == null) {
+                mOnStartContentIntentHelper = new OnStartContentIntentHelper();
+            }
+            return mOnStartContentIntentHelper;
+        }
+
+        @Override
+        public void onIntentUrlReceived(String intentUrl) {
+            mOnStartContentIntentHelper.notifyCalled(intentUrl);
+        }
+    }
 
     /**
      * Returns the TestCallbackHelperContainer associated with this ContentView,
@@ -37,12 +74,25 @@
         return mCallbackHelper;
     }
 
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContentIntentHandler = new TestContentIntentHandler();
+    }
+
+    @Override
+    protected void setActivity(Activity activity) {
+        super.setActivity(activity);
+        getActivity().getShellManager().getActiveShell().getViewAndroidDelegate()
+                .setContentIntentHandler(mContentIntentHandler);
+    }
+
     /**
      * Encodes the provided content string into an escaped url as intents do.
      * @param content Content to escape into a url.
      * @return Escaped url.
      */
-    protected String urlForContent(String content) {
+    protected static String urlForContent(String content) {
         return Uri.encode(content).replaceAll("%20", "+");
     }
 
@@ -62,9 +112,8 @@
      * @return The content url of the received intent or null if none.
      */
     protected String scrollAndTapExpectingIntent(String id) throws Throwable {
-        TestCallbackHelperContainer callbackHelperContainer = getTestCallbackHelperContainer();
         OnStartContentIntentHelper onStartContentIntentHelper =
-                callbackHelperContainer.getOnStartContentIntentHelper();
+                mContentIntentHandler.getOnStartContentIntentHelper();
         int currentCallCount = onStartContentIntentHelper.getCallCount();
 
         DOMUtils.clickNode(this, getContentViewCore(), id);
@@ -93,4 +142,4 @@
                 TimeUnit.SECONDS);
         getInstrumentation().waitForIdleSync();
     }
-}
+}
\ No newline at end of file
diff --git a/content/public/browser/download_save_info.cc b/content/public/browser/download_save_info.cc
index eabc761e..8e686f3 100644
--- a/content/public/browser/download_save_info.cc
+++ b/content/public/browser/download_save_info.cc
@@ -6,9 +6,11 @@
 
 namespace content {
 
+// static
+const int64_t DownloadSaveInfo::kLengthFullContent = 0;
+
 DownloadSaveInfo::DownloadSaveInfo()
-    : offset(0), prompt_for_save_location(false) {
-}
+    : offset(0), length(kLengthFullContent), prompt_for_save_location(false) {}
 
 DownloadSaveInfo::~DownloadSaveInfo() {
 }
@@ -18,6 +20,7 @@
       suggested_name(std::move(that.suggested_name)),
       file(std::move(that.file)),
       offset(that.offset),
+      length(that.length),
       hash_state(std::move(that.hash_state)),
       hash_of_partial_file(std::move(that.hash_of_partial_file)),
       prompt_for_save_location(that.prompt_for_save_location) {}
diff --git a/content/public/browser/download_save_info.h b/content/public/browser/download_save_info.h
index 69893f4b..c1c97bf5 100644
--- a/content/public/browser/download_save_info.h
+++ b/content/public/browser/download_save_info.h
@@ -22,6 +22,10 @@
 // name, |offset| is set to the point where we left off, and |hash_state| will
 // hold the state of the hash algorithm where we left off.
 struct CONTENT_EXPORT DownloadSaveInfo {
+  // The default value for |length|. Used when request the rest of the file
+  // starts from |offset|.
+  static const int64_t kLengthFullContent;
+
   DownloadSaveInfo();
   ~DownloadSaveInfo();
   DownloadSaveInfo(DownloadSaveInfo&& that);
@@ -41,6 +45,13 @@
   // The file offset at which to start the download.  May be 0.
   int64_t offset;
 
+  // The number of the bytes to download from |offset|. Set to
+  // |kLengthFullContent| by default.
+  // Ask to retrieve segment of the download file when length is greater than 0.
+  // Request the rest of the file starting from |offset|, when length is
+  // |kLengthFullContent|.
+  int64_t length;
+
   // The state of the hash. If specified, this hash state must indicate the
   // state of the partial file for the first |offset| bytes.
   std::unique_ptr<crypto::SecureHash> hash_state;
diff --git a/content/public/browser/download_url_parameters.h b/content/public/browser/download_url_parameters.h
index 41b0ed6..88121d8 100644
--- a/content/public/browser/download_url_parameters.h
+++ b/content/public/browser/download_url_parameters.h
@@ -168,9 +168,16 @@
   }
 
   // If |offset| is non-zero, then a byte range request will be issued to fetch
-  // the range of bytes starting at |offset| through to the end of thedownload.
+  // the range of bytes starting at |offset|.
+  // Use |set_length| to specify the last byte position, or the range
+  // request will be "Range:bytes={offset}-" to retrieve the rest of the file.
   void set_offset(int64_t offset) { save_info_.offset = offset; }
 
+  // When |length| > 0, the range of bytes will be from
+  // |save_info_.offset| to |save_info_.offset| + |length| - 1.
+  // See |DownloadSaveInfo.length|.
+  void set_length(int64_t length) { save_info_.length = length; }
+
   // If |offset| is non-zero, then |hash_of_partial_file| contains the raw
   // SHA-256 hash of the first |offset| bytes of the target file. Only
   // meaningful if a partial file exists and is identified by either the
@@ -239,6 +246,7 @@
     return save_info_.suggested_name;
   }
   int64_t offset() const { return save_info_.offset; }
+  int64_t length() const { return save_info_.length; }
   const std::string& hash_of_partial_file() const {
     return save_info_.hash_of_partial_file;
   }
diff --git a/content/public/browser/navigation_handle.h b/content/public/browser/navigation_handle.h
index e3e8df8e..0f3892c 100644
--- a/content/public/browser/navigation_handle.h
+++ b/content/public/browser/navigation_handle.h
@@ -156,6 +156,7 @@
   // navigations are:
   // * reference fragment navigations
   // * pushState/replaceState
+  // * same page history navigation
   virtual bool IsSamePage() = 0;
 
   // Whether the navigation has encountered a server redirect or not.
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index 67c5321..c7b5451 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -120,8 +120,10 @@
   virtual void WidgetHidden() = 0;
   virtual int VisibleWidgetCount() const = 0;
 
-  // Called when the audio state changes for this render process host.
-  virtual void AudioStateChanged() = 0;
+  // Called when an audio stream is added or removed and used to determine if
+  // the process should be backgrounded or not.
+  virtual void OnAudioStreamAdded() = 0;
+  virtual void OnAudioStreamRemoved() = 0;
 
   // Indicates whether the current RenderProcessHost is exclusively hosting
   // guest RenderFrames. Not all guest RenderFrames are created equal.  A guest,
diff --git a/content/public/browser/web_contents_binding_set.h b/content/public/browser/web_contents_binding_set.h
index 029c68b..1d3290f 100644
--- a/content/public/browser/web_contents_binding_set.h
+++ b/content/public/browser/web_contents_binding_set.h
@@ -119,8 +119,7 @@
   class FrameInterfaceBinder : public Binder {
    public:
     FrameInterfaceBinder(WebContentsFrameBindingSet* binding_set,
-                         Interface* impl)
-        : impl_(impl), bindings_(mojo::BindingSetDispatchMode::WITH_CONTEXT) {
+                         Interface* impl) : impl_(impl) {
       bindings_.set_pre_dispatch_handler(
           base::Bind(&WebContentsFrameBindingSet::WillDispatchForContext,
                      base::Unretained(binding_set)));
@@ -138,13 +137,13 @@
     }
 
     Interface* const impl_;
-    mojo::AssociatedBindingSet<Interface> bindings_;
+    mojo::AssociatedBindingSet<Interface, RenderFrameHost*> bindings_;
 
     DISALLOW_COPY_AND_ASSIGN(FrameInterfaceBinder);
   };
 
-  void WillDispatchForContext(void* context) {
-    current_target_frame_ = static_cast<RenderFrameHost*>(context);
+  void WillDispatchForContext(RenderFrameHost* const& frame_host) {
+    current_target_frame_ = frame_host;
   }
 
   RenderFrameHost* current_target_frame_ = nullptr;
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index 6098aaa..ab84e813 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -130,6 +130,7 @@
   IPC_STRUCT_TRAITS_MEMBER(loads_images_automatically)
   IPC_STRUCT_TRAITS_MEMBER(images_enabled)
   IPC_STRUCT_TRAITS_MEMBER(plugins_enabled)
+  IPC_STRUCT_TRAITS_MEMBER(encrypted_media_enabled)
   IPC_STRUCT_TRAITS_MEMBER(dom_paste_enabled)
   IPC_STRUCT_TRAITS_MEMBER(shrinks_standalone_images_to_fit)
   IPC_STRUCT_TRAITS_MEMBER(text_areas_are_resizable)
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 6d1f4a3..2eb0de9 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -56,9 +56,9 @@
 const char kAndroidFontsPath[]          = "android-fonts-path";
 
 // Set blink settings. Format is <name>[=<value],<name>[=<value>],...
-// The names are declared in Settings.in. For boolean type, use "true", "false",
-// or omit '=<value>' part to set to true. For enum type, use the int value of
-// the enum value. Applied after other command line flags and prefs.
+// The names are declared in Settings.json5. For boolean type, use "true",
+// "false", or omit '=<value>' part to set to true. For enum type, use the int
+// value of the enum value. Applied after other command line flags and prefs.
 const char kBlinkSettings[]                 = "blink-settings";
 
 // Causes the browser process to crash on startup.
@@ -109,7 +109,7 @@
     "disable-background-timer-throttling";
 
 // Disable one or more Blink runtime-enabled features.
-// Use names from RuntimeEnabledFeatures.in, separated by commas.
+// Use names from RuntimeEnabledFeatures.json5, separated by commas.
 // Applied after kEnableBlinkFeatures, and after other flags that change these
 // features.
 const char kDisableBlinkFeatures[]          = "disable-blink-features";
@@ -352,7 +352,7 @@
     "enable-prefer-compositing-to-lcd-text";
 
 // Enable one or more Blink runtime-enabled features.
-// Use names from RuntimeEnabledFeatures.in, separated by commas.
+// Use names from RuntimeEnabledFeatures.json5, separated by commas.
 // Applied before kDisableBlinkFeatures, and after other flags that change these
 // features.
 const char kEnableBlinkFeatures[]           = "enable-blink-features";
diff --git a/content/public/common/web_preferences.cc b/content/public/common/web_preferences.cc
index ec26b95..2034641d 100644
--- a/content/public/common/web_preferences.cc
+++ b/content/public/common/web_preferences.cc
@@ -80,6 +80,7 @@
       loads_images_automatically(true),
       images_enabled(true),
       plugins_enabled(true),
+      encrypted_media_enabled(true),
       dom_paste_enabled(false),  // enables execCommand("paste")
       shrinks_standalone_images_to_fit(true),
       text_areas_are_resizable(true),
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h
index 08b75f2..b5f363f 100644
--- a/content/public/common/web_preferences.h
+++ b/content/public/common/web_preferences.h
@@ -97,6 +97,7 @@
   bool loads_images_automatically;
   bool images_enabled;
   bool plugins_enabled;
+  bool encrypted_media_enabled;
   bool dom_paste_enabled;
   bool shrinks_standalone_images_to_fit;
   bool text_areas_are_resizable;
diff --git a/content/public/test/android/BUILD.gn b/content/public/test/android/BUILD.gn
index a2bd7c8..2d1af8a 100644
--- a/content/public/test/android/BUILD.gn
+++ b/content/public/test/android/BUILD.gn
@@ -38,7 +38,6 @@
     "javatests/src/org/chromium/content/browser/test/util/KeyUtils.java",
     "javatests/src/org/chromium/content/browser/test/util/RenderProcessLimit.java",
     "javatests/src/org/chromium/content/browser/test/util/TestCallbackHelperContainer.java",
-    "javatests/src/org/chromium/content/browser/test/util/TestContentViewClient.java",
     "javatests/src/org/chromium/content/browser/test/util/TestInputMethodManagerWrapper.java",
     "javatests/src/org/chromium/content/browser/test/util/TestTouchUtils.java",
     "javatests/src/org/chromium/content/browser/test/util/TestWebContentsObserver.java",
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestCallbackHelperContainer.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestCallbackHelperContainer.java
index c06fa6c..701106e 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestCallbackHelperContainer.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestCallbackHelperContainer.java
@@ -17,12 +17,9 @@
  * This class is used to provide callback hooks for tests and related classes.
  */
 public class TestCallbackHelperContainer {
-    private final TestContentViewClient mTestContentViewClient;
     private TestWebContentsObserver mTestWebContentsObserver;
 
     public TestCallbackHelperContainer(final ContentViewCore contentViewCore) {
-        mTestContentViewClient = new TestContentViewClient();
-        contentViewCore.setContentViewClient(mTestContentViewClient);
         // TODO(yfriedman): Change callers to be executed on the UI thread. Unfortunately this is
         // super convenient as the caller is nearly always on the test thread which is fine to block
         // and it's cumbersome to keep bouncing to the UI thread.
@@ -35,12 +32,6 @@
         });
     }
 
-    protected TestCallbackHelperContainer(
-            TestContentViewClient viewClient, TestWebContentsObserver contentsObserver) {
-        mTestContentViewClient = viewClient;
-        mTestWebContentsObserver = contentsObserver;
-    }
-
     /**
      * CallbackHelper for OnPageCommitVisible.
      */
@@ -181,21 +172,6 @@
         }
     }
 
-    /**
-     * CallbackHelper for OnStartContentIntent.
-     */
-    public static class OnStartContentIntentHelper extends CallbackHelper {
-        private String mIntentUrl;
-        public void notifyCalled(String intentUrl) {
-            mIntentUrl = intentUrl;
-            notifyCalled();
-        }
-        public String getIntentUrl() {
-            assert getCallCount() > 0;
-            return mIntentUrl;
-        }
-    }
-
     public OnPageStartedHelper getOnPageStartedHelper() {
         return mTestWebContentsObserver.getOnPageStartedHelper();
     }
@@ -207,8 +183,4 @@
     public OnReceivedErrorHelper getOnReceivedErrorHelper() {
         return mTestWebContentsObserver.getOnReceivedErrorHelper();
     }
-
-    public OnStartContentIntentHelper getOnStartContentIntentHelper() {
-        return mTestContentViewClient.getOnStartContentIntentHelper();
-    }
 }
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewClient.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewClient.java
deleted file mode 100644
index 7fda5207b..0000000
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewClient.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 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.
-
-package org.chromium.content.browser.test.util;
-
-import android.content.Context;
-
-import org.chromium.content.browser.ContentViewClient;
-import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnStartContentIntentHelper;
-
-/**
- * The default ContentViewClient used by ContentView tests.
- * <p>
- * Tests that need to supply their own ContentViewClient should do that
- * by extending this one.
- */
-public class TestContentViewClient extends ContentViewClient {
-
-    private final OnStartContentIntentHelper mOnStartContentIntentHelper;
-
-    public TestContentViewClient() {
-        mOnStartContentIntentHelper = new OnStartContentIntentHelper();
-    }
-
-    public OnStartContentIntentHelper getOnStartContentIntentHelper() {
-        return mOnStartContentIntentHelper;
-    }
-
-    /**
-     * ATTENTION!: When overriding the following method, be sure to call
-     * the corresponding method in the super class. Otherwise
-     * {@link CallbackHelper#waitForCallback()} methods will
-     * stop working!
-     */
-
-    @Override
-    public void onStartContentIntent(Context context, String contentUrl, boolean isMainFrame) {
-        mOnStartContentIntentHelper.notifyCalled(contentUrl);
-    }
-}
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index d0af148f..7ea1a745 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -143,12 +143,14 @@
   return 1;
 }
 
-void MockRenderProcessHost::AudioStateChanged() {}
-
 bool MockRenderProcessHost::IsForGuestsOnly() const {
   return is_for_guests_only_;
 }
 
+void MockRenderProcessHost::OnAudioStreamAdded() {}
+
+void MockRenderProcessHost::OnAudioStreamRemoved() {}
+
 StoragePartition* MockRenderProcessHost::GetStoragePartition() const {
   return BrowserContext::GetDefaultStoragePartition(browser_context_);
 }
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 358a2672..10ef44d0 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -57,8 +57,9 @@
   void WidgetRestored() override;
   void WidgetHidden() override;
   int VisibleWidgetCount() const override;
-  void AudioStateChanged() override;
   bool IsForGuestsOnly() const override;
+  void OnAudioStreamAdded() override;
+  void OnAudioStreamRemoved() override;
   StoragePartition* GetStoragePartition() const override;
   virtual void AddWord(const base::string16& word);
   bool Shutdown(int exit_code, bool wait) override;
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index bc99abf7..f3857d4 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -652,9 +652,9 @@
 
   CommonNavigationParams common_params(
       url, Referrer(), ui::PAGE_TRANSITION_FORWARD_BACK,
-      FrameMsg_Navigate_Type::NORMAL, true, false, base::TimeTicks(),
-      FrameMsg_UILoadMetricsReportType::NO_REPORT, GURL(), GURL(),
-      PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), "GET", nullptr);
+      FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT, true, false,
+      base::TimeTicks(), FrameMsg_UILoadMetricsReportType::NO_REPORT, GURL(),
+      GURL(), PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), "GET", nullptr);
   RequestNavigationParams request_params;
   request_params.page_state = state;
   request_params.nav_entry_id = pending_offset + 1;
diff --git a/content/renderer/dom_storage/local_storage_cached_area.cc b/content/renderer/dom_storage/local_storage_cached_area.cc
index a7ba25ed..a662cb7 100644
--- a/content/renderer/dom_storage/local_storage_cached_area.cc
+++ b/content/renderer/dom_storage/local_storage_cached_area.cc
@@ -151,7 +151,6 @@
 void LocalStorageCachedArea::Clear(const GURL& page_url,
                                    const std::string& storage_area_id) {
   // No need to prime the cache in this case.
-
   Reset();
   map_ = new DOMStorageMap(kPerStorageAreaQuota);
   ignore_all_mutations_ = true;
diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc
index 36a5b19fe..077c27cd 100644
--- a/content/renderer/media/media_stream_dispatcher.cc
+++ b/content/renderer/media/media_stream_dispatcher.cc
@@ -11,7 +11,6 @@
 #include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
 #include "content/renderer/render_thread_impl.h"
 #include "media/base/audio_parameters.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
 #include "url/origin.h"
 
 namespace content {
@@ -74,14 +73,15 @@
     int request_id,
     const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
     const StreamControls& controls,
-    const url::Origin& security_origin) {
+    const url::Origin& security_origin,
+    bool is_processing_user_gesture) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DVLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")";
 
   requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
-  Send(new MediaStreamHostMsg_GenerateStream(
-      routing_id(), next_ipc_id_++, controls, security_origin,
-      blink::WebUserGestureIndicator::isProcessingUserGesture()));
+  Send(new MediaStreamHostMsg_GenerateStream(routing_id(), next_ipc_id_++,
+                                             controls, security_origin,
+                                             is_processing_user_gesture));
 }
 
 void MediaStreamDispatcher::CancelGenerateStream(
diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h
index 3cc993a..b5fc1d82 100644
--- a/content/renderer/media/media_stream_dispatcher.h
+++ b/content/renderer/media/media_stream_dispatcher.h
@@ -45,7 +45,8 @@
       int request_id,
       const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
       const StreamControls& controls,
-      const url::Origin& security_origin);
+      const url::Origin& security_origin,
+      bool is_processing_user_gesture);
 
   // Cancel the request for a new media stream to be created.
   virtual void CancelGenerateStream(
diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc
index 4a608f4..82f6097 100644
--- a/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -117,7 +117,7 @@
   int GenerateStream(const StreamControls& controls, int request_id) {
     int next_ipc_id = dispatcher_->GetNextIpcIdForTest();
     dispatcher_->GenerateStream(request_id, handler_.get()->AsWeakPtr(),
-                                controls, security_origin_);
+                                controls, security_origin_, true);
     return next_ipc_id;
   }
 
@@ -282,7 +282,7 @@
   // Test failure when creating a stream.
   int ipc_request_id1 = dispatcher->next_ipc_id_;
   dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
-                             components, security_origin);
+                             components, security_origin, true);
   dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerationFailed(
       kRouteId, ipc_request_id1, MEDIA_DEVICE_PERMISSION_DENIED));
 
@@ -293,7 +293,7 @@
   // Create a new stream.
   ipc_request_id1 = dispatcher->next_ipc_id_;
   dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
-                             components, security_origin);
+                             components, security_origin, true);
 
   StreamDeviceInfoArray audio_device_array(1);
   StreamDeviceInfo audio_device_info;
@@ -328,9 +328,9 @@
   int ipc_request_id1 = dispatcher->next_ipc_id_;
 
   dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
-                             components, url::Origin());
+                             components, url::Origin(), true);
   dispatcher->GenerateStream(kRequestId2, handler.get()->AsWeakPtr(),
-                             components, url::Origin());
+                             components, url::Origin(), true);
 
   EXPECT_EQ(2u, dispatcher->requests_.size());
   dispatcher->CancelGenerateStream(kRequestId2, handler.get()->AsWeakPtr());
diff --git a/content/renderer/media/mock_media_stream_dispatcher.cc b/content/renderer/media/mock_media_stream_dispatcher.cc
index e2f054ac..a4b3fe5 100644
--- a/content/renderer/media/mock_media_stream_dispatcher.cc
+++ b/content/renderer/media/mock_media_stream_dispatcher.cc
@@ -30,7 +30,8 @@
     int request_id,
     const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
     const StreamControls& controls,
-    const url::Origin& url) {
+    const url::Origin& security_origin,
+    bool is_processing_user_gesture) {
   // Audio and video share the same request so we use |audio_input_request_id_|
   // only.
   audio_input_request_id_ = request_id;
diff --git a/content/renderer/media/mock_media_stream_dispatcher.h b/content/renderer/media/mock_media_stream_dispatcher.h
index 6550031..f84df36 100644
--- a/content/renderer/media/mock_media_stream_dispatcher.h
+++ b/content/renderer/media/mock_media_stream_dispatcher.h
@@ -23,7 +23,8 @@
       int request_id,
       const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
       const StreamControls& controls,
-      const url::Origin& url) override;
+      const url::Origin& security_origin,
+      bool is_procesing_user_gesture) override;
   void CancelGenerateStream(
       int request_id,
       const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler)
diff --git a/content/renderer/media/render_media_log.cc b/content/renderer/media/render_media_log.cc
index 059e68b..1169f685 100644
--- a/content/renderer/media/render_media_log.cc
+++ b/content/renderer/media/render_media_log.cc
@@ -42,11 +42,9 @@
 
 namespace content {
 
-RenderMediaLog::RenderMediaLog(
-    const GURL& security_origin,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+RenderMediaLog::RenderMediaLog(const GURL& security_origin)
     : security_origin_(security_origin),
-      task_runner_(task_runner),
+      task_runner_(base::ThreadTaskRunnerHandle::Get()),
       tick_clock_(new base::DefaultTickClock()),
       last_ipc_send_time_(tick_clock_->NowTicks()),
       ipc_send_pending_(false) {
diff --git a/content/renderer/media/render_media_log.h b/content/renderer/media/render_media_log.h
index 568e283..ed9ce62 100644
--- a/content/renderer/media/render_media_log.h
+++ b/content/renderer/media/render_media_log.h
@@ -33,9 +33,7 @@
 // It must be constructed on the render thread.
 class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
  public:
-  explicit RenderMediaLog(
-      const GURL& security_origin,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+  explicit RenderMediaLog(const GURL& security_origin);
 
   // MediaLog implementation.
   void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override;
diff --git a/content/renderer/media/render_media_log_unittest.cc b/content/renderer/media/render_media_log_unittest.cc
index a4633c2..905bec5 100644
--- a/content/renderer/media/render_media_log_unittest.cc
+++ b/content/renderer/media/render_media_log_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "content/common/view_messages.h"
 #include "content/public/test/mock_render_thread.h"
 #include "content/renderer/media/render_media_log.h"
@@ -19,8 +18,7 @@
 class RenderMediaLogTest : public testing::Test {
  public:
   RenderMediaLogTest()
-      : log_(new RenderMediaLog(GURL("http://foo.com"),
-                                base::ThreadTaskRunnerHandle::Get())),
+      : log_(new RenderMediaLog(GURL("http://foo.com"))),
         tick_clock_(new base::SimpleTestTickClock()),
         task_runner_(new base::TestMockTimeTaskRunner()) {
     log_->SetTickClockForTesting(std::unique_ptr<base::TickClock>(tick_clock_));
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc
index c490a1c3..1ff102e6 100644
--- a/content/renderer/media/user_media_client_impl.cc
+++ b/content/renderer/media/user_media_client_impl.cc
@@ -18,12 +18,15 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_runner.h"
+#include "base/task_runner_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/renderer/media/local_media_stream_audio_source.h"
 #include "content/renderer/media/media_stream.h"
 #include "content/renderer/media/media_stream_constraints_util.h"
+#include "content/renderer/media/media_stream_constraints_util_video_source.h"
 #include "content/renderer/media/media_stream_dispatcher.h"
 #include "content/renderer/media/media_stream_video_capturer_source.h"
 #include "content/renderer/media/media_stream_video_track.h"
@@ -33,6 +36,7 @@
 #include "content/renderer/media/webrtc_logging.h"
 #include "content/renderer/media/webrtc_uma_histograms.h"
 #include "content/renderer/render_thread_impl.h"
+#include "media/capture/video_capture_types.h"
 #include "third_party/WebKit/public/platform/URLConversion.h"
 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
 #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
@@ -40,6 +44,7 @@
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
 
 namespace content {
 namespace {
@@ -214,13 +219,27 @@
 
 }  // namespace
 
+struct UserMediaClientImpl::RequestSettings {
+  RequestSettings(bool is_processing_user_gesture, url::Origin security_origin)
+      : enable_automatic_audio_output_device_selection(false),
+        is_processing_user_gesture(is_processing_user_gesture),
+        security_origin(security_origin) {}
+  ~RequestSettings() = default;
+
+  bool enable_automatic_audio_output_device_selection;
+  bool is_processing_user_gesture;
+  url::Origin security_origin;
+};
+
 UserMediaClientImpl::UserMediaClientImpl(
     RenderFrame* render_frame,
     PeerConnectionDependencyFactory* dependency_factory,
-    std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher)
+    std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher,
+    const scoped_refptr<base::TaskRunner>& worker_task_runner)
     : RenderFrameObserver(render_frame),
       dependency_factory_(dependency_factory),
       media_stream_dispatcher_(std::move(media_stream_dispatcher)),
+      worker_task_runner_(worker_task_runner),
       weak_factory_(this) {
   DCHECK(dependency_factory_);
   DCHECK(media_stream_dispatcher_.get());
@@ -256,9 +275,16 @@
   int request_id = g_next_request_id++;
   std::unique_ptr<StreamControls> controls = base::MakeUnique<StreamControls>();
 
-  bool enable_automatic_output_device_selection = false;
-  bool request_audio_input_devices = false;
+  // The value returned by isProcessingUserGesture() is used by the browser to
+  // make decisions about the permissions UI. Its value can be lost while
+  // switching threads, so saving its value here.
+  RequestSettings request_settings(
+      blink::WebUserGestureIndicator::isProcessingUserGesture(),
+      static_cast<url::Origin>(user_media_request.getSecurityOrigin()));
   if (user_media_request.audio()) {
+    bool request_audio_input_devices = false;
+    // TODO(guidou): Implement spec-compliant device selection for audio. See
+    // http://crbug.com/623104.
     CopyConstraintsToTrackControls(user_media_request.audioConstraints(),
                                    &controls->audio,
                                    &request_audio_input_devices);
@@ -269,73 +295,122 @@
     GetConstraintValueAsBoolean(
         user_media_request.audioConstraints(),
         &blink::WebMediaTrackConstraintSet::renderToAssociatedSink,
-        &enable_automatic_output_device_selection);
-  }
-  bool request_video_input_devices = false;
-  if (user_media_request.video()) {
-    CopyConstraintsToTrackControls(user_media_request.videoConstraints(),
-                                   &controls->video,
-                                   &request_video_input_devices);
+        &request_settings.enable_automatic_audio_output_device_selection);
+
+    if (request_audio_input_devices) {
+      GetMediaDevicesDispatcher()->EnumerateDevices(
+          true /* audio_input */, false /* video_input */,
+          false /* audio_output */, request_settings.security_origin,
+          base::Bind(&UserMediaClientImpl::SelectAudioInputDevice,
+                     weak_factory_.GetWeakPtr(), request_id, user_media_request,
+                     base::Passed(&controls), request_settings));
+      return;
+    }
   }
 
-  url::Origin security_origin = user_media_request.getSecurityOrigin();
-  if (request_audio_input_devices || request_video_input_devices) {
-    GetMediaDevicesDispatcher()->EnumerateDevices(
-        request_audio_input_devices, request_video_input_devices,
-        false /* request_audio_output_devices */, security_origin,
-        base::Bind(&UserMediaClientImpl::SelectUserMediaDevice,
-                   weak_factory_.GetWeakPtr(), request_id, user_media_request,
-                   base::Passed(&controls),
-                   enable_automatic_output_device_selection, security_origin));
-  } else {
-    FinalizeRequestUserMedia(
-        request_id, user_media_request, std::move(controls),
-        enable_automatic_output_device_selection, security_origin);
-  }
+  SetupVideoInput(request_id, user_media_request, std::move(controls),
+                  request_settings);
 }
 
-void UserMediaClientImpl::SelectUserMediaDevice(
+void UserMediaClientImpl::SelectAudioInputDevice(
     int request_id,
     const blink::WebUserMediaRequest& user_media_request,
     std::unique_ptr<StreamControls> controls,
-    bool enable_automatic_output_device_selection,
-    const url::Origin& security_origin,
+    const RequestSettings& request_settings,
     const EnumerationResult& device_enumeration) {
   DCHECK(CalledOnValidThread());
+  DCHECK(controls->audio.requested);
+  DCHECK(IsDeviceSource(controls->audio.stream_source));
 
-  if (controls->audio.requested &&
-      IsDeviceSource(controls->audio.stream_source)) {
-    if (!PickDeviceId(user_media_request.audioConstraints(),
-                      device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT],
-                      &controls->audio.device_id)) {
-      GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE,
-                                "");
+  if (!PickDeviceId(user_media_request.audioConstraints(),
+                    device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT],
+                    &controls->audio.device_id)) {
+    GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, "");
+    return;
+  }
+
+  SetupVideoInput(request_id, user_media_request, std::move(controls),
+                  request_settings);
+}
+
+void UserMediaClientImpl::SetupVideoInput(
+    int request_id,
+    const blink::WebUserMediaRequest& user_media_request,
+    std::unique_ptr<StreamControls> controls,
+    const RequestSettings& request_settings) {
+  if (user_media_request.video()) {
+    bool ignore;
+    CopyConstraintsToTrackControls(user_media_request.videoConstraints(),
+                                   &controls->video, &ignore);
+    if (IsDeviceSource(controls->video.stream_source)) {
+      GetMediaDevicesDispatcher()->GetVideoInputCapabilities(
+          request_settings.security_origin,
+          base::Bind(&UserMediaClientImpl::SelectVideoDeviceSourceSettings,
+                     weak_factory_.GetWeakPtr(), request_id, user_media_request,
+                     base::Passed(&controls), request_settings));
       return;
     }
   }
-
-  if (controls->video.requested &&
-      IsDeviceSource(controls->video.stream_source)) {
-    if (!PickDeviceId(user_media_request.videoConstraints(),
-                      device_enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT],
-                      &controls->video.device_id)) {
-      GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE,
-                                "");
-      return;
-    }
-  }
-
   FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls),
-                           enable_automatic_output_device_selection,
-                           security_origin);
+                           request_settings);
+}
+
+void UserMediaClientImpl::SelectVideoDeviceSourceSettings(
+    int request_id,
+    const blink::WebUserMediaRequest& user_media_request,
+    std::unique_ptr<StreamControls> controls,
+    const RequestSettings& request_settings,
+    std::vector<::mojom::VideoInputDeviceCapabilitiesPtr>
+        video_input_capabilities) {
+  DCHECK(CalledOnValidThread());
+  DCHECK(controls->video.requested);
+  DCHECK(IsDeviceSource(controls->video.stream_source));
+
+  VideoCaptureCapabilities capabilities;
+  capabilities.device_capabilities = std::move(video_input_capabilities);
+  capabilities.power_line_capabilities = {
+      media::PowerLineFrequency::FREQUENCY_DEFAULT,
+      media::PowerLineFrequency::FREQUENCY_50HZ,
+      media::PowerLineFrequency::FREQUENCY_60HZ};
+
+  base::PostTaskAndReplyWithResult(
+      worker_task_runner_.get(), FROM_HERE,
+      base::Bind(&SelectVideoCaptureSourceSettings, std::move(capabilities),
+                 user_media_request.videoConstraints()),
+      base::Bind(&UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings,
+                 weak_factory_.GetWeakPtr(), request_id, user_media_request,
+                 base::Passed(&controls), request_settings));
+}
+
+void UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings(
+    int request_id,
+    const blink::WebUserMediaRequest& user_media_request,
+    std::unique_ptr<StreamControls> controls,
+    const RequestSettings& request_settings,
+    const VideoCaptureSourceSelectionResult& selection_result) {
+  DCHECK(CalledOnValidThread());
+  // Select video device.
+  if (!selection_result.has_value()) {
+    blink::WebString failed_constraint_name =
+        blink::WebString::fromASCII(selection_result.failed_constraint_name);
+    MediaStreamRequestResult result =
+        failed_constraint_name.isEmpty()
+            ? MEDIA_DEVICE_NO_HARDWARE
+            : MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
+    GetUserMediaRequestFailed(user_media_request, result,
+                              failed_constraint_name);
+    return;
+  }
+  controls->video.device_id = selection_result.settings.device_id();
+  FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls),
+                           request_settings);
 }
 
 void UserMediaClientImpl::FinalizeRequestUserMedia(
     int request_id,
     const blink::WebUserMediaRequest& user_media_request,
     std::unique_ptr<StreamControls> controls,
-    bool enable_automatic_output_device_selection,
-    const url::Origin& security_origin) {
+    const RequestSettings& request_settings) {
   DCHECK(CalledOnValidThread());
 
   WebRtcLogMessage(
@@ -345,12 +420,14 @@
                          request_id, controls->audio.device_id.c_str(),
                          controls->video.device_id.c_str()));
 
-  user_media_requests_.push_back(std::unique_ptr<UserMediaRequestInfo>(
-      new UserMediaRequestInfo(request_id, user_media_request,
-                               enable_automatic_output_device_selection)));
+  user_media_requests_.push_back(base::MakeUnique<UserMediaRequestInfo>(
+      request_id, user_media_request,
+      request_settings.enable_automatic_audio_output_device_selection));
 
   media_stream_dispatcher_->GenerateStream(
-      request_id, weak_factory_.GetWeakPtr(), *controls, security_origin);
+      request_id, weak_factory_.GetWeakPtr(), *controls,
+      request_settings.security_origin,
+      request_settings.is_processing_user_gesture);
 }
 
 void UserMediaClientImpl::cancelUserMediaRequest(
diff --git a/content/renderer/media/user_media_client_impl.h b/content/renderer/media/user_media_client_impl.h
index d6ee61e..db866f2 100644
--- a/content/renderer/media/user_media_client_impl.h
+++ b/content/renderer/media/user_media_client_impl.h
@@ -30,11 +30,16 @@
 #include "third_party/WebKit/public/web/WebUserMediaClient.h"
 #include "third_party/WebKit/public/web/WebUserMediaRequest.h"
 
+namespace base {
+class TaskRunner;
+}
+
 namespace content {
 class PeerConnectionDependencyFactory;
 class MediaStreamAudioSource;
 class MediaStreamDispatcher;
 class MediaStreamVideoSource;
+struct VideoCaptureSourceSelectionResult;
 
 // UserMediaClientImpl is a delegate for the Media Stream GetUserMedia API.
 // It ties together WebKit and MediaStreamManager
@@ -51,7 +56,8 @@
   UserMediaClientImpl(
       RenderFrame* render_frame,
       PeerConnectionDependencyFactory* dependency_factory,
-      std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher);
+      std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher,
+      const scoped_refptr<base::TaskRunner>& worker_task_runner);
   ~UserMediaClientImpl() override;
 
   MediaStreamDispatcher* media_stream_dispatcher() const {
@@ -282,19 +288,40 @@
 
   const ::mojom::MediaDevicesDispatcherHostPtr& GetMediaDevicesDispatcher();
 
-  void SelectUserMediaDevice(
+  struct RequestSettings;
+
+  void SelectAudioInputDevice(
       int request_id,
       const blink::WebUserMediaRequest& user_media_request,
       std::unique_ptr<StreamControls> controls,
-      bool enable_automatic_output_device_selection,
-      const url::Origin& security_origin,
+      const RequestSettings& request_settings,
       const EnumerationResult& device_enumeration);
+
+  void SetupVideoInput(int request_id,
+                       const blink::WebUserMediaRequest& user_media_request,
+                       std::unique_ptr<StreamControls> controls,
+                       const RequestSettings& request_settings);
+
+  void SelectVideoDeviceSourceSettings(
+      int request_id,
+      const blink::WebUserMediaRequest& user_media_request,
+      std::unique_ptr<StreamControls> controls,
+      const RequestSettings& request_settings,
+      std::vector<::mojom::VideoInputDeviceCapabilitiesPtr>
+          video_input_capabilities);
+
+  void FinalizeSelectVideoDeviceSourceSettings(
+      int request_id,
+      const blink::WebUserMediaRequest& user_media_request,
+      std::unique_ptr<StreamControls> controls,
+      const RequestSettings& request_settings,
+      const VideoCaptureSourceSelectionResult& selection_result);
+
   void FinalizeRequestUserMedia(
       int request_id,
       const blink::WebUserMediaRequest& user_media_request,
       std::unique_ptr<StreamControls> controls,
-      bool enable_automatic_output_device_selection,
-      const url::Origin& security_origin);
+      const RequestSettings& request_settings);
 
   // Callback invoked by MediaDevicesEventDispatcher when a device-change
   // notification arrives.
@@ -322,6 +349,8 @@
 
   blink::WebMediaDeviceChangeObserver media_device_change_observer_;
 
+  const scoped_refptr<base::TaskRunner> worker_task_runner_;
+
   // Note: This member must be the last to ensure all outstanding weak pointers
   // are invalidated first.
   base::WeakPtrFactory<UserMediaClientImpl> weak_factory_;
diff --git a/content/renderer/media/user_media_client_impl_unittest.cc b/content/renderer/media/user_media_client_impl_unittest.cc
index 43a957f..2cd033b 100644
--- a/content/renderer/media/user_media_client_impl_unittest.cc
+++ b/content/renderer/media/user_media_client_impl_unittest.cc
@@ -45,8 +45,7 @@
 blink::WebMediaConstraints CreateDeviceConstraints(
     const char* basic_exact_value,
     const char* basic_ideal_value = nullptr,
-    const char* advanced_exact_value = nullptr,
-    const char* advanced_ideal_value = nullptr) {
+    const char* advanced_exact_value = nullptr) {
   MockConstraintFactory factory;
   blink::WebMediaTrackConstraintSet basic;
   if (basic_exact_value) {
@@ -64,9 +63,29 @@
     blink::WebString value = blink::WebString::fromUTF8(advanced_exact_value);
     advanced.deviceId.setExact(value);
   }
-  if (advanced_ideal_value) {
-    blink::WebString value = blink::WebString::fromUTF8(advanced_ideal_value);
-    advanced.deviceId.setIdeal(blink::WebVector<blink::WebString>(&value, 1));
+
+  return factory.CreateWebMediaConstraints();
+}
+
+blink::WebMediaConstraints CreateFacingModeConstraints(
+    const char* basic_exact_value,
+    const char* basic_ideal_value = nullptr,
+    const char* advanced_exact_value = nullptr) {
+  MockConstraintFactory factory;
+  if (basic_exact_value) {
+    factory.basic().facingMode.setExact(
+        blink::WebString::fromUTF8(basic_exact_value));
+  }
+  if (basic_ideal_value) {
+    blink::WebString value = blink::WebString::fromUTF8(basic_ideal_value);
+    factory.basic().deviceId.setIdeal(
+        blink::WebVector<blink::WebString>(&value, 1));
+  }
+
+  auto& advanced = factory.AddAdvanced();
+  if (advanced_exact_value) {
+    blink::WebString value = blink::WebString::fromUTF8(advanced_exact_value);
+    advanced.deviceId.setExact(value);
   }
 
   return factory.CreateWebMediaConstraints();
@@ -120,15 +139,34 @@
     callback.Run(result);
   }
 
+  void GetVideoInputCapabilities(
+      const url::Origin& security_origin,
+      const GetVideoInputCapabilitiesCallback& client_callback) override {
+    ::mojom::VideoInputDeviceCapabilitiesPtr device =
+        ::mojom::VideoInputDeviceCapabilities::New();
+    device->device_id = kFakeVideoInputDeviceId1;
+    device->facing_mode = ::mojom::FacingMode::USER;
+    device->formats.push_back(media::VideoCaptureFormat(
+        gfx::Size(640, 480), 30.0f, media::PIXEL_FORMAT_I420));
+    std::vector<::mojom::VideoInputDeviceCapabilitiesPtr> result;
+    result.push_back(std::move(device));
+
+    device = ::mojom::VideoInputDeviceCapabilities::New();
+    device->device_id = kFakeVideoInputDeviceId2;
+    device->facing_mode = ::mojom::FacingMode::ENVIRONMENT;
+    device->formats.push_back(media::VideoCaptureFormat(
+        gfx::Size(640, 480), 30.0f, media::PIXEL_FORMAT_I420));
+    result.push_back(std::move(device));
+
+    client_callback.Run(std::move(result));
+  }
+
   MOCK_METHOD3(SubscribeDeviceChangeNotifications,
                void(MediaDeviceType type,
                     uint32_t subscription_id,
                     const url::Origin& security_origin));
   MOCK_METHOD2(UnsubscribeDeviceChangeNotifications,
                void(MediaDeviceType type, uint32_t subscription_id));
-  MOCK_METHOD2(GetVideoInputCapabilities,
-               void(const url::Origin& security_origin,
-                    const GetVideoInputCapabilitiesCallback& client_callback));
 };
 
 class UserMediaClientImplUnderTest : public UserMediaClientImpl {
@@ -143,15 +181,16 @@
   UserMediaClientImplUnderTest(
       PeerConnectionDependencyFactory* dependency_factory,
       std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher)
-      : UserMediaClientImpl(NULL,
+      : UserMediaClientImpl(nullptr,
                             dependency_factory,
-                            std::move(media_stream_dispatcher)),
+                            std::move(media_stream_dispatcher),
+                            base::ThreadTaskRunnerHandle::Get()),
         state_(REQUEST_NOT_STARTED),
         result_(NUM_MEDIA_REQUEST_RESULTS),
         result_name_(""),
         factory_(dependency_factory),
         create_source_that_fails_(false),
-        video_source_(NULL) {}
+        video_source_(nullptr) {}
 
   void RequestUserMediaForTest(
       const blink::WebUserMediaRequest& user_media_request) {
@@ -390,7 +429,7 @@
     return result;
   }
 
-  void TestValidRequestWithDeviceConstraints(
+  void TestValidRequestWithConstraints(
       const blink::WebMediaConstraints& audio_constraints,
       const blink::WebMediaConstraints& video_constraints,
       const std::string& expected_audio_device_id,
@@ -838,9 +877,9 @@
       CreateDeviceConstraints(kFakeAudioInputDeviceId1);
   blink::WebMediaConstraints video_constraints =
       CreateDeviceConstraints(kFakeVideoInputDeviceId1);
-  TestValidRequestWithDeviceConstraints(audio_constraints, video_constraints,
-                                        kFakeAudioInputDeviceId1,
-                                        kFakeVideoInputDeviceId1);
+  TestValidRequestWithConstraints(audio_constraints, video_constraints,
+                                  kFakeAudioInputDeviceId1,
+                                  kFakeVideoInputDeviceId1);
 }
 
 TEST_F(UserMediaClientImplTest, CreateWithBasicIdealValidDeviceId) {
@@ -848,9 +887,9 @@
       CreateDeviceConstraints(nullptr, kFakeAudioInputDeviceId1);
   blink::WebMediaConstraints video_constraints =
       CreateDeviceConstraints(nullptr, kFakeVideoInputDeviceId1);
-  TestValidRequestWithDeviceConstraints(audio_constraints, video_constraints,
-                                        kFakeAudioInputDeviceId1,
-                                        kFakeVideoInputDeviceId1);
+  TestValidRequestWithConstraints(audio_constraints, video_constraints,
+                                  kFakeAudioInputDeviceId1,
+                                  kFakeVideoInputDeviceId1);
 }
 
 TEST_F(UserMediaClientImplTest, CreateWithAdvancedExactValidDeviceId) {
@@ -858,40 +897,43 @@
       CreateDeviceConstraints(nullptr, nullptr, kFakeAudioInputDeviceId1);
   blink::WebMediaConstraints video_constraints = CreateDeviceConstraints(
       nullptr, nullptr, kFakeVideoInputDeviceId1);
-  TestValidRequestWithDeviceConstraints(audio_constraints, video_constraints,
-                                        kFakeAudioInputDeviceId1,
-                                        kFakeVideoInputDeviceId1);
-}
-
-TEST_F(UserMediaClientImplTest, CreateWithAdvancedIdealValidDeviceId) {
-  blink::WebMediaConstraints audio_constraints = CreateDeviceConstraints(
-      nullptr, nullptr, nullptr, kFakeAudioInputDeviceId1);
-  blink::WebMediaConstraints video_constraints = CreateDeviceConstraints(
-      nullptr, nullptr, nullptr, kFakeVideoInputDeviceId1);
-  TestValidRequestWithDeviceConstraints(audio_constraints, video_constraints,
-                                        kFakeAudioInputDeviceId1,
-                                        kFakeVideoInputDeviceId1);
+  TestValidRequestWithConstraints(audio_constraints, video_constraints,
+                                  kFakeAudioInputDeviceId1,
+                                  kFakeVideoInputDeviceId1);
 }
 
 TEST_F(UserMediaClientImplTest, CreateWithAllOptionalInvalidDeviceId) {
-  blink::WebMediaConstraints audio_constraints = CreateDeviceConstraints(
-      nullptr, kInvalidDeviceId, kInvalidDeviceId, kInvalidDeviceId);
-  blink::WebMediaConstraints video_constraints = CreateDeviceConstraints(
-      nullptr, kInvalidDeviceId, kInvalidDeviceId, kInvalidDeviceId);
-  // MockMediaStreamDispatcher uses empty string as default device ID.
-  TestValidRequestWithDeviceConstraints(audio_constraints, video_constraints,
-                                        std::string(), std::string());
+  blink::WebMediaConstraints audio_constraints =
+      CreateDeviceConstraints(nullptr, kInvalidDeviceId, kInvalidDeviceId);
+  blink::WebMediaConstraints video_constraints =
+      CreateDeviceConstraints(nullptr, kInvalidDeviceId, kInvalidDeviceId);
+  // MockMediaStreamDispatcher uses empty string as default audio device ID.
+  // MockMediaDevicesDispatcher uses the first device in the enumeration as
+  // default video device ID.
+  TestValidRequestWithConstraints(audio_constraints, video_constraints,
+                                  std::string(), kFakeVideoInputDeviceId1);
 }
 
-TEST_F(UserMediaClientImplTest,
-       CreateWithAdvancedIdealValidOtherOptionalInvalidDeviceId) {
-  blink::WebMediaConstraints audio_constraints = CreateDeviceConstraints(
-      nullptr, kInvalidDeviceId, kInvalidDeviceId, kFakeAudioInputDeviceId1);
-  blink::WebMediaConstraints video_constraints = CreateDeviceConstraints(
-      nullptr, kInvalidDeviceId, kInvalidDeviceId, kFakeVideoInputDeviceId1);
-  TestValidRequestWithDeviceConstraints(audio_constraints, video_constraints,
-                                        kFakeAudioInputDeviceId1,
-                                        kFakeVideoInputDeviceId1);
+TEST_F(UserMediaClientImplTest, CreateWithFacingModeUser) {
+  blink::WebMediaConstraints audio_constraints =
+      CreateDeviceConstraints(kFakeAudioInputDeviceId1);
+  blink::WebMediaConstraints video_constraints =
+      CreateFacingModeConstraints("user");
+  // kFakeVideoInputDeviceId1 has user facing mode.
+  TestValidRequestWithConstraints(audio_constraints, video_constraints,
+                                  kFakeAudioInputDeviceId1,
+                                  kFakeVideoInputDeviceId1);
+}
+
+TEST_F(UserMediaClientImplTest, CreateWithFacingModeEnvironment) {
+  blink::WebMediaConstraints audio_constraints =
+      CreateDeviceConstraints(kFakeAudioInputDeviceId1);
+  blink::WebMediaConstraints video_constraints =
+      CreateFacingModeConstraints("environment");
+  // kFakeVideoInputDeviceId2 has environment facing mode.
+  TestValidRequestWithConstraints(audio_constraints, video_constraints,
+                                  kFakeAudioInputDeviceId1,
+                                  kFakeVideoInputDeviceId2);
 }
 
 }  // namespace content
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 520892b..558531af 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -483,7 +483,6 @@
       document_url_(container ? GURL(container->document().url()) : GURL()),
       is_flash_plugin_(module->name() == kFlashPluginName),
       has_been_clicked_(false),
-      javascript_used_(false),
       full_frame_(false),
       viewport_to_dip_scale_(1.0f),
       sent_initial_did_change_view_(false),
@@ -1251,7 +1250,6 @@
   scoped_refptr<PepperPluginInstanceImpl> ref(this);
 
   DCHECK_EQ(isolate, isolate_);
-  RecordFlashJavaScriptUse();
 
   // If the plugin supports the private instance interface, try to retrieve its
   // instance object.
@@ -1708,8 +1706,6 @@
   // During the first view update, initialize the throttler.
   if (!sent_initial_did_change_view_) {
     if (is_flash_plugin_ && RenderThread::Get()) {
-      RenderThread::Get()->RecordAction(
-          base::UserMetricsAction("Flash.PluginInstanceCreated"));
       RecordFlashSizeMetric(unobscured_rect_.width(),
                             unobscured_rect_.height());
     }
@@ -2414,7 +2410,6 @@
 PP_Var PepperPluginInstanceImpl::GetWindowObject(PP_Instance instance) {
   if (!container_)
     return PP_MakeUndefined();
-  RecordFlashJavaScriptUse();
   V8VarConverter converter(pp_instance_, V8VarConverter::kAllowObjectVars);
   PepperTryCatchVar try_catch(this, &converter, NULL);
   WebLocalFrame* frame = container_->document().frame();
@@ -2432,7 +2427,6 @@
 PP_Var PepperPluginInstanceImpl::GetOwnerElementObject(PP_Instance instance) {
   if (!container_)
     return PP_MakeUndefined();
-  RecordFlashJavaScriptUse();
   V8VarConverter converter(pp_instance_, V8VarConverter::kAllowObjectVars);
   PepperTryCatchVar try_catch(this, &converter, NULL);
   ScopedPPVar result = try_catch.FromV8(container_->v8ObjectForElement());
@@ -2447,7 +2441,6 @@
     return PP_MakeUndefined();
   if (is_deleted_ && blink::WebPluginScriptForbiddenScope::isForbidden())
     return PP_MakeUndefined();
-  RecordFlashJavaScriptUse();
 
   // Executing the script may remove the plugin from the DOM, so we need to keep
   // a reference to ourselves so that we can still process the result after
@@ -3407,14 +3400,6 @@
   }
 }
 
-void PepperPluginInstanceImpl::RecordFlashJavaScriptUse() {
-  if (initialized_ && !javascript_used_ && is_flash_plugin_) {
-    javascript_used_ = true;
-    RenderThread::Get()->RecordAction(
-        base::UserMetricsAction("Flash.JavaScriptUsed"));
-  }
-}
-
 void PepperPluginInstanceImpl::ConvertRectToDIP(PP_Rect* rect) const {
   rect->point.x *= viewport_to_dip_scale_;
   rect->point.y *= viewport_to_dip_scale_;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h
index ada181f..c501abb7 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -12,6 +12,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/callback.h"
@@ -707,8 +708,6 @@
                                  int pending_host_id,
                                  const ppapi::URLResponseInfoData& data);
 
-  void RecordFlashJavaScriptUse();
-
   // Converts the PP_Rect between DIP and Viewport.
   void ConvertRectToDIP(PP_Rect* rect) const;
   void ConvertDIPToViewport(gfx::Rect* rect) const;
@@ -769,9 +768,6 @@
   // Set to true the first time the plugin is clicked. Used to collect metrics.
   bool has_been_clicked_;
 
-  // Used to track if JavaScript has ever been used for this plugin instance.
-  bool javascript_used_;
-
   // Responsible for turning on throttling if Power Saver is on.
   std::unique_ptr<PluginInstanceThrottlerImpl> throttler_;
 
diff --git a/content/renderer/push_messaging/PRESUBMIT.py b/content/renderer/push_messaging/PRESUBMIT.py
deleted file mode 100644
index aa4ae97d..0000000
--- a/content/renderer/push_messaging/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2015 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.
-
-"""Top-level presubmit script for Push Messaging.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index abfcafa4..5a11cf0 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -561,6 +561,7 @@
     const CommonNavigationParams& common_params,
     std::unique_ptr<StreamOverrideParameters> stream_override,
     bool is_view_source_mode_enabled,
+    bool is_same_document_navigation,
     int nav_entry_id) {
   WebURLRequest request(common_params.url);
   if (is_view_source_mode_enabled)
@@ -569,8 +570,7 @@
   request.setHTTPMethod(WebString::fromUTF8(common_params.method));
   if (common_params.referrer.url.is_valid()) {
     WebString web_referrer = WebSecurityPolicy::generateReferrerHeader(
-        common_params.referrer.policy,
-        common_params.url,
+        common_params.referrer.policy, common_params.url,
         WebString::fromUTF8(common_params.referrer.url.spec()));
     if (!web_referrer.isEmpty()) {
       request.setHTTPReferrer(web_referrer, common_params.referrer.policy);
@@ -579,6 +579,7 @@
     }
   }
 
+  request.setIsSameDocumentNavigation(is_same_document_navigation);
   request.setPreviewsState(
       static_cast<WebURLRequest::PreviewsState>(common_params.previews_state));
 
@@ -638,9 +639,13 @@
       static_cast<FrameMsg_UILoadMetricsReportType::Value>(
           info.urlRequest.inputPerfMetricReportPolicy());
 
-  // Determine the navigation type.
+  // No history-navigation is expected to happen.
+  DCHECK(info.navigationType != blink::WebNavigationTypeBackForward);
+
+  // Determine the navigation type. No same-document navigation is expected
+  // because it is loaded immediately by the FrameLoader.
   FrameMsg_Navigate_Type::Value navigation_type =
-      FrameMsg_Navigate_Type::NORMAL;
+      FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   if (info.navigationType == blink::WebNavigationTypeReload) {
     if (load_flags & net::LOAD_BYPASS_CACHE)
       navigation_type = FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE;
@@ -667,37 +672,20 @@
   return media::Context3D(provider->ContextGL(), provider->GrContext());
 }
 
-bool IsReload(FrameMsg_Navigate_Type::Value navigation_type) {
-  switch (navigation_type) {
-    case FrameMsg_Navigate_Type::RELOAD:
-    case FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE:
-    case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
-      return true;
-    case FrameMsg_Navigate_Type::RESTORE:
-    case FrameMsg_Navigate_Type::RESTORE_WITH_POST:
-    case FrameMsg_Navigate_Type::NORMAL:
-      return false;
-  }
-  NOTREACHED();
-  return false;
-}
-
 WebFrameLoadType ReloadFrameLoadTypeFor(
     FrameMsg_Navigate_Type::Value navigation_type) {
   switch (navigation_type) {
     case FrameMsg_Navigate_Type::RELOAD:
     case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
       return WebFrameLoadType::ReloadMainResource;
+
     case FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE:
       return WebFrameLoadType::ReloadBypassingCache;
-    case FrameMsg_Navigate_Type::RESTORE:
-    case FrameMsg_Navigate_Type::RESTORE_WITH_POST:
-    case FrameMsg_Navigate_Type::NORMAL:
+
+    default:
       NOTREACHED();
       return WebFrameLoadType::Standard;
   }
-  NOTREACHED();
-  return WebFrameLoadType::Standard;
 }
 
 RenderFrameImpl::CreateRenderFrameImplFunction g_create_render_frame_impl =
@@ -2830,8 +2818,7 @@
       RenderThreadImpl::current()->SharedMainThreadContextProvider());
 
   scoped_refptr<media::MediaLog> media_log(
-      new RenderMediaLog(url::Origin(frame_->getSecurityOrigin()).GetURL(),
-                         frame_->timerTaskRunner()));
+      new RenderMediaLog(url::Origin(frame_->getSecurityOrigin()).GetURL()));
 
 #if defined(OS_ANDROID)
   if (UseWebMediaPlayerImpl(url) && !media_surface_manager_)
@@ -5182,7 +5169,8 @@
     bool has_stale_copy_in_cache,
     int error_code) {
   DCHECK(IsBrowserSideNavigationEnabled());
-  bool is_reload = IsReload(common_params.navigation_type);
+  bool is_reload =
+      FrameMsg_Navigate_Type::IsReload(common_params.navigation_type);
   RenderFrameImpl::PrepareRenderViewForNavigation(
       common_params.url, request_params);
 
@@ -5203,7 +5191,9 @@
       CreateWebURLError(common_params.url, has_stale_copy_in_cache, error_code);
   WebURLRequest failed_request = CreateURLRequestForNavigation(
       common_params, std::unique_ptr<StreamOverrideParameters>(),
-      frame_->isViewSourceModeEnabled(), request_params.nav_entry_id);
+      frame_->isViewSourceModeEnabled(),
+      false,  // is_same_document_navigation
+      request_params.nav_entry_id);
 
   if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) {
     // The browser expects this frame to be loading an error page. Inform it
@@ -5830,7 +5820,8 @@
 
   // Lower bound for browser initiated navigation start time.
   base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
-  bool is_reload = IsReload(common_params.navigation_type);
+  bool is_reload =
+      FrameMsg_Navigate_Type::IsReload(common_params.navigation_type);
   bool is_history_navigation = request_params.page_state.IsValid();
   WebCachePolicy cache_policy = WebCachePolicy::UseProtocolCachePolicy;
   RenderFrameImpl::PrepareRenderViewForNavigation(
@@ -5876,10 +5867,17 @@
       blink::WebHistoryDifferentDocumentLoad;
   bool should_load_request = false;
   WebHistoryItem item_for_history_navigation;
-  WebURLRequest request =
-      CreateURLRequestForNavigation(common_params, std::move(stream_params),
-                                    frame_->isViewSourceModeEnabled(),
-                                    request_params.nav_entry_id);
+
+  // Enforce same-document navigation from the browser only if
+  // browser-side-navigation is enabled.
+  bool is_same_document =
+      IsBrowserSideNavigationEnabled() &&
+      FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type);
+
+  WebURLRequest request = CreateURLRequestForNavigation(
+      common_params, std::move(stream_params),
+      frame_->isViewSourceModeEnabled(), is_same_document,
+      request_params.nav_entry_id);
   request.setFrameType(IsTopLevelNavigation(frame_)
                            ? blink::WebURLRequest::FrameTypeTopLevel
                            : blink::WebURLRequest::FrameTypeNested);
@@ -5933,9 +5931,22 @@
       // store the relevant frame's WebHistoryItem in the root of the
       // PageState.
       item_for_history_navigation = entry->root();
-      history_load_type = request_params.is_same_document_history_load
-                              ? blink::WebHistorySameDocumentLoad
-                              : blink::WebHistoryDifferentDocumentLoad;
+      switch (common_params.navigation_type) {
+        case FrameMsg_Navigate_Type::RELOAD:
+        case FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE:
+        case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
+        case FrameMsg_Navigate_Type::RESTORE:
+        case FrameMsg_Navigate_Type::RESTORE_WITH_POST:
+        case FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT:
+          history_load_type = blink::WebHistoryDifferentDocumentLoad;
+          break;
+        case FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT:
+          history_load_type = blink::WebHistorySameDocumentLoad;
+          break;
+        default:
+          NOTREACHED();
+          history_load_type = blink::WebHistoryDifferentDocumentLoad;
+      }
       load_type = request_params.is_history_navigation_in_new_child
                       ? blink::WebFrameLoadType::InitialHistoryLoad
                       : blink::WebFrameLoadType::BackForward;
@@ -6123,14 +6134,16 @@
 }
 
 void RenderFrameImpl::InitializeUserMediaClient() {
-  if (!RenderThreadImpl::current())  // Will be NULL during unit tests.
+  RenderThreadImpl* render_thread = RenderThreadImpl::current();
+  if (!render_thread)  // Will be NULL during unit tests.
     return;
 
 #if BUILDFLAG(ENABLE_WEBRTC)
   DCHECK(!web_user_media_client_);
   web_user_media_client_ = new UserMediaClientImpl(
       this, RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(),
-      base::MakeUnique<MediaStreamDispatcher>(this));
+      base::MakeUnique<MediaStreamDispatcher>(this),
+      render_thread->GetWorkerTaskRunner());
   GetInterfaceRegistry()->AddInterface(
       base::Bind(&MediaDevicesListenerImpl::Create, GetRoutingID()));
 #endif
@@ -6150,8 +6163,7 @@
 
   return new WebMediaPlayerMS(
       frame_, client, GetWebMediaPlayerDelegate(),
-      new RenderMediaLog(url::Origin(security_origin).GetURL(),
-                         frame_->timerTaskRunner()),
+      new RenderMediaLog(url::Origin(security_origin).GetURL()),
       CreateRendererFactory(), render_thread->GetIOTaskRunner(),
       compositor_task_runner, render_thread->GetMediaThreadTaskRunner(),
       render_thread->GetWorkerTaskRunner(), render_thread->GetGpuFactories(),
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index dd92b7b..91dcc97 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -342,6 +342,7 @@
   // properly set when it is out of the default zoom limits of WebView.
   CommonNavigationParams common_params;
   common_params.url = GURL("data:text/html,min_zoomlimit_test");
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   GetMainRenderFrame()->SetHostZoomLevel(common_params.url, kMinZoomLevel);
   GetMainRenderFrame()->NavigateInternal(
       common_params, StartNavigationParams(), RequestNavigationParams(),
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index ec7d121d..acb26cb2 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -897,6 +897,7 @@
   record_purge_suspend_growth_metric_closure_.Reset(
       base::Bind(&RenderThreadImpl::RecordPurgeAndSuspendMemoryGrowthMetrics,
                  base::Unretained(this)));
+  needs_to_record_first_active_paint_ = false;
 
   base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
 
@@ -1641,6 +1642,7 @@
 
   if (backgrounded) {
     renderer_scheduler_->OnRendererBackgrounded();
+    needs_to_record_first_active_paint_ = false;
   } else {
     renderer_scheduler_->OnRendererForegrounded();
     // TODO(tasak): after enabling MemoryCoordinator, remove this Notify
@@ -1680,6 +1682,7 @@
   GetRendererScheduler()->DefaultTaskRunner()->PostDelayedTask(
       FROM_HERE, record_purge_suspend_metric_closure_.callback(),
       base::TimeDelta::FromSeconds(15));
+  needs_to_record_first_active_paint_ = true;
 }
 
 // TODO(tasak): Replace the following GetMallocUsage() with memory-infra
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 9a4affd..3924b340 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -497,6 +497,10 @@
   };
   void GetRendererMemoryMetrics(RendererMemoryMetrics* memory_metrics) const;
 
+  bool NeedsToRecordFirstActivePaint() const {
+    return needs_to_record_first_active_paint_;
+  }
+
  protected:
   RenderThreadImpl(
       const InProcessChildThreadParams& params,
@@ -767,6 +771,7 @@
   base::CancelableClosure record_purge_suspend_metric_closure_;
   RendererMemoryMetrics purge_and_suspend_memory_metrics_;
   base::CancelableClosure record_purge_suspend_growth_metric_closure_;
+  bool needs_to_record_first_active_paint_;
 
   int32_t client_id_;
 
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 2629721..90e361c 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -204,7 +204,7 @@
   CommonNavigationParams params;
   params.url = GURL("data:text/html,<div>Page</div>");
   params.navigation_start = base::TimeTicks::Now() + navigation_start_offset;
-  params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   params.transition = ui::PAGE_TRANSITION_TYPED;
   return params;
 }
@@ -600,7 +600,7 @@
   StartNavigationParams start_params;
   RequestNavigationParams request_params;
   common_params.url = GURL("data:text/html,<div>Page</div>");
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.transition = ui::PAGE_TRANSITION_TYPED;
   common_params.method = "POST";
 
@@ -641,7 +641,7 @@
 TEST_F(RenderViewImplTest, OnNavigationLoadDataWithBaseURL) {
   CommonNavigationParams common_params;
   common_params.url = GURL("data:text/html,");
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.transition = ui::PAGE_TRANSITION_TYPED;
   common_params.base_url_for_data_url = GURL("about:blank");
   common_params.history_url_for_data_url = GURL("about:blank");
@@ -968,7 +968,8 @@
   // Go back to C and commit, preparing for our real test.
   CommonNavigationParams common_params_C;
   RequestNavigationParams request_params_C;
-  common_params_C.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params_C.navigation_type =
+      FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
   common_params_C.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
   request_params_C.current_history_list_length = 4;
   request_params_C.current_history_list_offset = 3;
@@ -986,7 +987,8 @@
   // Back to page B without committing.
   CommonNavigationParams common_params_B;
   RequestNavigationParams request_params_B;
-  common_params_B.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params_B.navigation_type =
+      FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
   common_params_B.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
   request_params_B.current_history_list_length = 4;
   request_params_B.current_history_list_offset = 2;
@@ -998,7 +1000,8 @@
   // Back to page A and commit.
   CommonNavigationParams common_params;
   RequestNavigationParams request_params;
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type =
+      FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
   common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
   request_params.current_history_list_length = 4;
   request_params.current_history_list_offset = 2;
@@ -1341,7 +1344,7 @@
   // Start a load that will reach provisional state synchronously,
   // but won't complete synchronously.
   CommonNavigationParams common_params;
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.url = GURL("data:text/html,test data");
   frame()->Navigate(common_params, StartNavigationParams(),
                     RequestNavigationParams());
@@ -1364,7 +1367,7 @@
   // Start a load that will reach provisional state synchronously,
   // but won't complete synchronously.
   CommonNavigationParams common_params;
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.url = GURL("data:text/html,test data");
   frame()->Navigate(common_params, StartNavigationParams(),
                     RequestNavigationParams());
@@ -1676,7 +1679,7 @@
   CommonNavigationParams common_params;
   RequestNavigationParams request_params;
   common_params.url = GURL("data:text/html,world");
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.transition = ui::PAGE_TRANSITION_TYPED;
   common_params.navigation_start = base::TimeTicks::FromInternalValue(1);
   request_params.current_history_list_length = 1;
@@ -1788,7 +1791,7 @@
   // Start a load that will reach provisional state synchronously,
   // but won't complete synchronously.
   CommonNavigationParams common_params;
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.url = GURL("data:text/html,test data");
   TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame());
   main_frame->Navigate(common_params, StartNavigationParams(),
@@ -1820,7 +1823,7 @@
   // Start a load that will reach provisional state synchronously,
   // but won't complete synchronously.
   CommonNavigationParams common_params;
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.url = GURL("data:text/html,test data");
   TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame());
   main_frame->Navigate(common_params, StartNavigationParams(),
@@ -1854,7 +1857,7 @@
   // Start a load that will reach provisional state synchronously,
   // but won't complete synchronously.
   CommonNavigationParams common_params;
-  common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+  common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
   common_params.url = GURL("data:text/html,test data");
   TestRenderFrame* main_frame = static_cast<TestRenderFrame*>(frame());
   main_frame->Navigate(common_params, StartNavigationParams(),
@@ -2103,6 +2106,8 @@
   common_params_back.url =
       GURL("data:text/html;charset=utf-8,<div id=pagename>Page B</div>");
   common_params_back.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
+  common_params_back.navigation_type =
+      FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
   GoToOffsetWithParams(-1, back_state, common_params_back,
                        StartNavigationParams(), RequestNavigationParams());
   FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params =
@@ -2124,6 +2129,8 @@
   common_params_forward.url =
       GURL("data:text/html;charset=utf-8,<div id=pagename>Page C</div>");
   common_params_forward.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
+  common_params_forward.navigation_type =
+      FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
   GoToOffsetWithParams(1, forward_state, common_params_forward,
                        StartNavigationParams(), RequestNavigationParams());
   FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params2 =
@@ -2140,6 +2147,8 @@
 TEST_F(RenderViewImplTest, NavigationStartForCrossProcessHistoryNavigation) {
   auto common_params = MakeCommonNavigationParams(-TimeDelta::FromSeconds(1));
   common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
+  common_params.navigation_type =
+      FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT;
 
   RequestNavigationParams request_params;
   request_params.page_state =
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index f3b38e8..0788677 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -826,6 +826,7 @@
   settings->setLoadsImagesAutomatically(prefs.loads_images_automatically);
   settings->setImagesEnabled(prefs.images_enabled);
   settings->setPluginsEnabled(prefs.plugins_enabled);
+  settings->setEncryptedMediaEnabled(prefs.encrypted_media_enabled);
   settings->setDOMPasteAllowed(prefs.dom_paste_enabled);
   settings->setTextAreasAreResizable(prefs.text_areas_are_resizable);
   settings->setAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 268f83d..645363b2 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -375,6 +375,8 @@
       text_input_client_observer_(new TextInputClientObserver(this)),
 #endif
       focused_pepper_plugin_(nullptr),
+      time_to_first_active_paint_recorded_(true),
+      was_shown_time_(base::TimeTicks::Now()),
       weak_ptr_factory_(this) {
   DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
   if (!swapped_out)
@@ -773,6 +775,7 @@
   if (!GetWebWidget())
     return;
 
+  was_shown_time_ = base::TimeTicks::Now();
   // See OnWasHidden
   SetHidden(false);
   for (auto& observer : render_frames_)
@@ -929,6 +932,18 @@
 
 void RenderWidget::UpdateVisualState() {
   GetWebWidget()->updateAllLifecyclePhases();
+
+  if (time_to_first_active_paint_recorded_)
+    return;
+
+  RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
+  if (!render_thread_impl->NeedsToRecordFirstActivePaint())
+    return;
+
+  time_to_first_active_paint_recorded_ = true;
+  base::TimeDelta sample = base::TimeTicks::Now() - was_shown_time_;
+  UMA_HISTOGRAM_TIMES("PurgeAndSuspend.Experimental.TimeToFirstActivePaint",
+                      sample);
 }
 
 void RenderWidget::WillBeginCompositorFrame() {
@@ -1882,9 +1897,10 @@
   // throttled acks are released in case frame production ceases.
   is_hidden_ = hidden;
 
-  if (is_hidden_)
+  if (is_hidden_) {
     RenderThreadImpl::current()->WidgetHidden();
-  else
+    time_to_first_active_paint_recorded_ = false;
+  } else
     RenderThreadImpl::current()->WidgetRestored();
 
   if (render_widget_scheduling_state_)
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index c40009f..a22fec6 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -844,6 +844,9 @@
   // session, this info is sent to the browser along with other drag/drop info.
   DragEventSourceInfo possible_drag_event_info_;
 
+  bool time_to_first_active_paint_recorded_;
+  base::TimeTicks was_shown_time_;
+
   base::WeakPtrFactory<RenderWidget> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidget);
diff --git a/content/renderer/service_worker/PRESUBMIT.py b/content/renderer/service_worker/PRESUBMIT.py
deleted file mode 100644
index 928d9fe0..0000000
--- a/content/renderer/service_worker/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for service_worker.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 7ceb3dd5..60a035f 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -209,6 +209,10 @@
   Shutdown();
 }
 
+void EmbeddedSharedWorkerStub::countFeature(uint32_t feature) {
+  Send(new WorkerHostMsg_CountFeature(route_id_, feature));
+}
+
 void EmbeddedSharedWorkerStub::workerContextClosed() {
   Send(new WorkerHostMsg_WorkerContextClosed(route_id_));
 }
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h
index 3f0c250..9ad827e 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -59,6 +59,7 @@
   void OnChannelError() override;
 
   // blink::WebSharedWorkerClient implementation.
+  void countFeature(uint32_t feature) override;
   void workerContextClosed() override;
   void workerContextDestroyed() override;
   void workerReadyForInspection() override;
diff --git a/content/renderer/shared_worker/shared_worker_repository.cc b/content/renderer/shared_worker/shared_worker_repository.cc
index dfbcf70ad8..fe5c846 100644
--- a/content/renderer/shared_worker/shared_worker_repository.cc
+++ b/content/renderer/shared_worker/shared_worker_repository.cc
@@ -39,7 +39,7 @@
   params.creation_context_type = creation_context_type;
   ViewHostMsg_CreateWorker_Reply reply;
 
-  // This proxy will self-destruct when a connection is established.
+  // This proxy will self-destruct when a worker is destroyed.
   new WebSharedWorkerProxy(std::move(listener), params, channel);
 }
 
diff --git a/content/renderer/shared_worker/websharedworker_proxy.cc b/content/renderer/shared_worker/websharedworker_proxy.cc
index 628b14df..e29fa0b2 100644
--- a/content/renderer/shared_worker/websharedworker_proxy.cc
+++ b/content/renderer/shared_worker/websharedworker_proxy.cc
@@ -60,6 +60,8 @@
                         OnWorkerScriptLoadFailed)
     IPC_MESSAGE_HANDLER(ViewMsg_WorkerConnected,
                         OnWorkerConnected)
+    IPC_MESSAGE_HANDLER(ViewMsg_WorkerDestroyed, OnWorkerDestroyed)
+    IPC_MESSAGE_HANDLER(ViewMsg_CountFeatureOnSharedWorker, OnCountFeature)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -76,9 +78,19 @@
   delete this;
 }
 
-void WebSharedWorkerProxy::OnWorkerConnected() {
+void WebSharedWorkerProxy::OnWorkerConnected(
+    const std::set<uint32_t>& used_features) {
   listener_->connected();
+  for (uint32_t feature : used_features)
+    listener_->countFeature(feature);
+}
+
+void WebSharedWorkerProxy::OnWorkerDestroyed() {
   delete this;
 }
 
+void WebSharedWorkerProxy::OnCountFeature(uint32_t feature) {
+  listener_->countFeature(feature);
+}
+
 }  // namespace content
diff --git a/content/renderer/shared_worker/websharedworker_proxy.h b/content/renderer/shared_worker/websharedworker_proxy.h
index 78cd84c..1e561fd1 100644
--- a/content/renderer/shared_worker/websharedworker_proxy.h
+++ b/content/renderer/shared_worker/websharedworker_proxy.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_RENDERER_SHARED_WORKER_WEBSHAREDWORKER_PROXY_H_
 #define CONTENT_RENDERER_SHARED_WORKER_WEBSHAREDWORKER_PROXY_H_
 
+#include <set>
+
 #include "base/macros.h"
 #include "ipc/ipc_listener.h"
 #include "third_party/WebKit/public/web/WebSharedWorkerConnectListener.h"
@@ -22,11 +24,9 @@
 
 namespace content {
 
-// Implementation of the WebSharedWorker APIs. This object is intended to only
-// live long enough to allow the caller to send a "connect" event to the worker
-// thread. Once the connect event has been sent, all future communication will
-// happen via the WebMessagePortChannel. This instance will self-destruct when a
-// connection is established.
+// A proxy between a renderer process hosting a document and the browser
+// process. This instance has the same lifetime as a shared worker, and
+// self-destructs when the worker is destroyed.
 class WebSharedWorkerProxy : private IPC::Listener {
  public:
   // |channel| should be passed with its ownership.
@@ -45,7 +45,9 @@
 
   void OnWorkerCreated();
   void OnWorkerScriptLoadFailed();
-  void OnWorkerConnected();
+  void OnWorkerConnected(const std::set<uint32_t>& used_features);
+  void OnWorkerDestroyed();
+  void OnCountFeature(uint32_t feature);
 
   // Routing id associated with this worker - used to receive messages from the
   // worker, and also to route messages to the worker (WorkerService contains
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn
index 3eed8d5..278ab5f 100644
--- a/content/shell/android/BUILD.gn
+++ b/content/shell/android/BUILD.gn
@@ -55,6 +55,7 @@
     "java/src/org/chromium/content_shell/Shell.java",
     "java/src/org/chromium/content_shell/ShellLayoutTestUtils.java",
     "java/src/org/chromium/content_shell/ShellManager.java",
+    "java/src/org/chromium/content_shell/ShellViewAndroidDelegate.java",
   ]
 }
 
diff --git a/content/shell/android/java/src/org/chromium/content_shell/Shell.java b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
index e2f82e34..6215bf40 100644
--- a/content/shell/android/java/src/org/chromium/content_shell/Shell.java
+++ b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
@@ -36,7 +36,6 @@
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.WebContents;
-import org.chromium.ui.base.ViewAndroidDelegate;
 import org.chromium.ui.base.WindowAndroid;
 
 /**
@@ -68,6 +67,7 @@
     private long mNativeShell;
     private ContentViewRenderView mContentViewRenderView;
     private WindowAndroid mWindow;
+    private ShellViewAndroidDelegate mViewAndroidDelegate;
 
     private boolean mLoading;
     private boolean mIsFullscreen;
@@ -286,6 +286,10 @@
         }
     }
 
+    public ShellViewAndroidDelegate getViewAndroidDelegate() {
+        return mViewAndroidDelegate;
+    }
+
     /**
      * Initializes the ContentView based on the native tab contents pointer passed in.
      * @param webContents A {@link WebContents} object.
@@ -296,8 +300,8 @@
         Context context = getContext();
         mContentViewCore = new ContentViewCore(context, "");
         ContentView cv = ContentView.createContentView(context, mContentViewCore);
-        mContentViewCore.initialize(ViewAndroidDelegate.createBasicDelegate(cv), cv,
-                webContents, mWindow);
+        mViewAndroidDelegate = new ShellViewAndroidDelegate(cv);
+        mContentViewCore.initialize(mViewAndroidDelegate, cv, webContents, mWindow);
         mContentViewCore.setActionModeCallback(defaultActionCallback());
         mContentViewCore.setContentViewClient(mContentViewClient);
         mWebContents = mContentViewCore.getWebContents();
diff --git a/content/shell/android/java/src/org/chromium/content_shell/ShellViewAndroidDelegate.java b/content/shell/android/java/src/org/chromium/content_shell/ShellViewAndroidDelegate.java
new file mode 100644
index 0000000..b1102b3
--- /dev/null
+++ b/content/shell/android/java/src/org/chromium/content_shell/ShellViewAndroidDelegate.java
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content_shell;
+
+import android.content.Intent;
+import android.view.ViewGroup;
+
+import org.chromium.ui.base.ViewAndroidDelegate;
+
+/**
+ * Implementation of the abstract class {@link ViewAndroidDelegate} for content shell.
+ * Extended for testing.
+ */
+public class ShellViewAndroidDelegate extends ViewAndroidDelegate {
+    private final ViewGroup mContainerView;
+    private ContentIntentHandler mContentIntentHandler;
+
+    /**
+     * Interface used to define/modify what {@link #startContentIntent} does.
+     */
+    public interface ContentIntentHandler {
+        /**
+         * Called when intent url from content is received.
+         * @param intentUrl intent url.
+         */
+        void onIntentUrlReceived(String intentUrl);
+    }
+
+    public ShellViewAndroidDelegate(ViewGroup containerView) {
+        mContainerView = containerView;
+    }
+
+    /**
+     * Set the {@link ContentIntentHandler} for {@link #starContentIntent}.
+     * @param handler Handler to inject to {@link #startContentIntent}.
+     */
+    public void setContentIntentHandler(ContentIntentHandler handler) {
+        mContentIntentHandler = handler;
+    }
+
+    @Override
+    public void startContentIntent(Intent intent, String intentUrl, boolean isMainFrame) {
+        if (mContentIntentHandler != null) mContentIntentHandler.onIntentUrlReceived(intentUrl);
+    }
+
+    @Override
+    public ViewGroup getContainerView() {
+        return mContainerView;
+    }
+}
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 6268be8..4c72abf 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1039,6 +1039,7 @@
     "../browser/download/download_item_impl_unittest.cc",
     "../browser/download/download_job_unittest.cc",
     "../browser/download/download_manager_impl_unittest.cc",
+    "../browser/download/download_request_core_unittest.cc",
     "../browser/download/rate_estimator_unittest.cc",
     "../browser/download/save_package_unittest.cc",
     "../browser/fileapi/copy_or_move_file_validator_unittest.cc",
@@ -1336,7 +1337,6 @@
     "../common/quarantine/quarantine_linux_unittest.cc",
     "../common/quarantine/quarantine_mac_unittest.mm",
     "../common/quarantine/quarantine_win_unittest.cc",
-    "../common/sandbox_mac_compiler_unittest.mm",
     "../common/sandbox_mac_diraccess_unittest.mm",
     "../common/sandbox_mac_fontloading_unittest.mm",
     "../common/sandbox_mac_system_access_unittest.mm",
@@ -1655,6 +1655,7 @@
   }
   if (is_mac) {
     deps += [
+      "//sandbox/mac:seatbelt",
       "//third_party/mozilla",
       "//third_party/ocmock",
       "//ui/accelerated_widget_mac",
diff --git a/content/test/data/dom_storage/store_data.html b/content/test/data/dom_storage/store_data.html
new file mode 100644
index 0000000..91b08444
--- /dev/null
+++ b/content/test/data/dom_storage/store_data.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="common.js"></script>
+<script>
+function test() {
+  window.localStorage.clear();
+  window.localStorage.setItem("foo", "bar");
+  done();
+}
+</script>
+<body onload="setTimeout(test, 0)">
+<div id="status">Starting...<br/></div>
diff --git a/content/test/data/dom_storage/verify_data.html b/content/test/data/dom_storage/verify_data.html
new file mode 100644
index 0000000..cc845bb8
--- /dev/null
+++ b/content/test/data/dom_storage/verify_data.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<script src="common.js"></script>
+<script>
+function test() {
+  let val = window.localStorage['foo'];
+  if (val !== 'bar')
+    fail('Read incorrect value from localStorage. Excpected "bar", got "' + val + '"');
+  else
+    done();
+}
+</script>
+<body onload="setTimeout(test, 0)">
+<div id="status">Starting...<br/></div>
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index ff3fb67..e335b3ee 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -36,6 +36,8 @@
 
     self.Fail('Pixel_OffscreenCanvasUnaccelerated2DGPUCompositingWorker',
               ['mac', ('nvidia', 0xfe9)], bug=652931)
+    self.Flaky('Pixel_CSSFilterEffects',
+        ['mac', ('nvidia', 0xfe9)], bug=690277)
 
     # TODO(kbr): flakily timing out on this configuration.
     self.Flaky('*', ['linux', 'intel', 'debug'], bug=648369)
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 91ddb49..93ed068 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -53,7 +53,7 @@
         bug=483282) # owner:cwallez, test might be buggy
 
     # Win and Mac
-    self.Flaky('deqp/functional/gles3/sync.html', ['win', 'mac'], bug=676848)
+    self.Fail('deqp/functional/gles3/sync.html', ['win', 'mac'], bug=676848)
 
     # Windows only.
     self.Fail('conformance2/rendering/blitframebuffer-outside-readbuffer.html',
@@ -655,17 +655,6 @@
     self.Fail('deqp/functional/gles3/uniformbuffers/random.html',
         ['mac', 'intel'], bug=618464)
 
-    # Mac ASAN only
-    self.Fail('conformance/more/functions/copyTexImage2D.html',
-        ['mac', 'asan'], bug=681641)
-    self.Fail('conformance/more/functions/copyTexSubImage2D.html',
-        ['mac', 'asan'], bug=681641)
-    self.Fail('deqp/functional/gles3/negativetextureapi.html',
-        ['mac', 'asan'], bug=681641)
-    self.Fail(
-        'deqp/functional/gles3/texturespecification/basic_copyteximage2d.html',
-        ['mac', 'asan'], bug=681641)
-
     # Linux only.
     self.Flaky('conformance/textures/video/' +
                'tex-2d-rgba-rgba-unsigned_byte.html',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index 44918e6..f613d150 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -136,6 +136,10 @@
               'copy-tex-image-and-sub-image-2d.html',
               ['win7', 'intel', 'no_passthrough'])
 
+    # Win7 / NVIDIA D3D9 failures
+    self.Flaky('conformance/canvas/canvas-test.html',
+        ['win7', 'nvidia', 'd3d9'], bug=690248)
+
     # Win / Intel HD 530 failures
     self.Fail('conformance/canvas/to-data-url-test.html',
         ['win', 'intel'], bug=680797)
@@ -370,14 +374,6 @@
     self.Fail('conformance/textures/misc/tex-input-validation.html',
         ['mac', ('nvidia', 0xfe9)], bug=635081)
 
-    # Mac ASAN only
-    self.Fail(
-      'conformance/more/functions/copyTexImage2D.html',
-      ['mac', 'asan'], bug=681641)
-    self.Fail(
-      'conformance/more/functions/copyTexSubImage2D.html',
-      ['mac', 'asan'], bug=681641)
-
     # Linux failures
     self.Flaky('conformance/textures/video/' +
                'tex-2d-rgba-rgba-unsigned_byte.html',
@@ -585,7 +581,7 @@
     self.Fail('conformance/textures/misc/' +
         'copy-tex-image-and-sub-image-2d.html',
         ['android', ('qualcomm', 'Adreno (TM) 420')], bug=499555)
-    self.Flaky('conformance/uniforms/uniform-samplers-test.html',
+    self.Fail('conformance/uniforms/uniform-samplers-test.html',
         ['android', ('qualcomm', 'Adreno (TM) 430')], bug=663071)
     self.Fail('WebglExtension_EXT_sRGB',
         ['android',
@@ -610,25 +606,6 @@
         ['android', ('nvidia', 'NVIDIA Tegra')], bug=478572)
 
     # Pixel C
-    self.Flaky('conformance/textures/video/' +
-        'tex-2d-rgb-rgb-unsigned_byte.html',
-        ['android', 'android-chromium',
-         ('nvidia', 'NVIDIA Tegra')], bug=624621)
-    self.Flaky('conformance/textures/video/' +
-        'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
-        ['android', 'android-chromium',
-         ('nvidia', 'NVIDIA Tegra')], bug=624621)
-    self.Flaky('conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html',
-        ['android', 'android-chromium',
-         ('nvidia', 'NVIDIA Tegra')], bug=624621)
-    self.Flaky('conformance/textures/video/' +
-        'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html',
-        ['android', 'android-chromium',
-         ('nvidia', 'NVIDIA Tegra')], bug=624621)
-    self.Flaky('conformance/textures/video/' +
-        'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html',
-        ['android', 'android-chromium',
-         ('nvidia', 'NVIDIA Tegra')], bug=624621)
     self.Fail('conformance/glsl/bugs/constant-precision-qualifier.html',
         ['android', 'android-chromium',
          ('nvidia', 'NVIDIA Tegra')], bug=624621)
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index ff25114..6558a12 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -429,6 +429,7 @@
     common_params.url = url;
     common_params.referrer = Referrer(GURL(), blink::WebReferrerPolicyDefault);
     common_params.transition = ui::PAGE_TRANSITION_LINK;
+    common_params.navigation_type = FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
     OnBeginNavigation(common_params, begin_params);
   }
 }
@@ -458,8 +459,10 @@
   // PlzNavigate
   NavigationRequest* request = frame_tree_node_->navigation_request();
   CHECK(request);
-  bool have_to_make_network_request = ShouldMakeNetworkRequestForURL(
-      request->common_params().url);
+  bool have_to_make_network_request =
+      ShouldMakeNetworkRequestForURL(request->common_params().url) &&
+      !FrameMsg_Navigate_Type::IsSameDocument(
+          request->common_params().navigation_type);
 
   // Simulate a beforeUnload ACK from the renderer if the browser is waiting for
   // it. If it runs it will update the request state.
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 2fc9900..34360030 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -116,6 +116,21 @@
     const GURL& url,
     const Referrer& referrer,
     ui::PageTransition transition) {
+  TestDidNavigateWithSequenceNumber(render_frame_host, nav_entry_id,
+                                    did_create_new_entry, url, referrer,
+                                    transition, false, -1, -1);
+}
+
+void TestWebContents::TestDidNavigateWithSequenceNumber(
+    RenderFrameHost* render_frame_host,
+    int nav_entry_id,
+    bool did_create_new_entry,
+    const GURL& url,
+    const Referrer& referrer,
+    ui::PageTransition transition,
+    bool was_within_same_page,
+    int item_sequence_number,
+    int document_sequence_number) {
   TestRenderFrameHost* rfh =
       static_cast<TestRenderFrameHost*>(render_frame_host);
   rfh->InitializeRenderFrameIfNeeded();
@@ -126,19 +141,43 @@
   FrameHostMsg_DidCommitProvisionalLoad_Params params;
 
   params.nav_entry_id = nav_entry_id;
+  params.frame_unique_name = std::string();
+  params.item_sequence_number = item_sequence_number;
+  params.document_sequence_number = document_sequence_number;
   params.url = url;
+  params.base_url = GURL();
   params.referrer = referrer;
   params.transition = transition;
   params.redirects = std::vector<GURL>();
-  params.should_update_history = false;
+  params.should_update_history = true;
+  params.contents_mime_type = std::string("text/html");
+  params.socket_address = net::HostPortPair();
+  params.intended_as_new_entry = did_create_new_entry;
+  params.did_create_new_entry = did_create_new_entry;
+  params.should_replace_current_entry = false;
+  params.gesture = NavigationGestureUser;
+  params.method = "GET";
+  params.post_id = 0;
+  params.was_within_same_page = was_within_same_page;
+  params.http_status_code = 200;
+  params.url_is_unreachable = false;
+  if (item_sequence_number != -1 && document_sequence_number != -1) {
+    params.page_state = PageState::CreateForTestingWithSequenceNumbers(
+        url, item_sequence_number, document_sequence_number);
+  } else {
+    params.page_state = PageState::CreateFromURL(url);
+  }
+  params.original_request_url = GURL();
+  params.is_overriding_user_agent = false;
+  params.history_list_was_cleared = false;
+  params.render_view_routing_id = 0;
+  params.origin = url::Origin();
+  params.report_type = FrameMsg_UILoadMetricsReportType::NO_REPORT;
+  params.ui_timestamp = base::TimeTicks();
+  params.insecure_request_policy = blink::kLeaveInsecureRequestsAlone;
+  params.has_potentially_trustworthy_unique_origin = false;
   params.searchable_form_url = GURL();
   params.searchable_form_encoding = std::string();
-  params.did_create_new_entry = did_create_new_entry;
-  params.gesture = NavigationGestureUser;
-  params.was_within_same_page = false;
-  params.method = "GET";
-  params.page_state = PageState::CreateFromURL(url);
-  params.contents_mime_type = std::string("text/html");
 
   rfh->SendNavigateWithParams(&params);
 }
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 34d42a2..1deb67a 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -63,6 +63,15 @@
                                    const GURL& url,
                                    const Referrer& referrer,
                                    ui::PageTransition transition) override;
+  void TestDidNavigateWithSequenceNumber(RenderFrameHost* render_frame_host,
+                                         int nav_entry_id,
+                                         bool did_create_new_entry,
+                                         const GURL& url,
+                                         const Referrer& referrer,
+                                         ui::PageTransition transition,
+                                         bool was_within_same_page,
+                                         int item_sequence_number,
+                                         int document_sequence_number);
   const std::string& GetSaveFrameHeaders() override;
 
   // True if a cross-site navigation is pending.
diff --git a/device/BUILD.gn b/device/BUILD.gn
index f26a6bb..04415d9 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -68,8 +68,6 @@
     "gamepad/public/interfaces/gamepad_struct_traits_unittest.cc",
     "generic_sensor/platform_sensor_and_provider_unittest_win.cc",
     "generic_sensor/platform_sensor_provider_unittest.cc",
-    "power_monitor/power_monitor_message_broadcaster_unittest.cc",
-    "power_monitor/public/cpp/power_monitor_broadcast_source_unittest.cc",
     "sensors/data_fetcher_shared_memory_base_unittest.cc",
     "sensors/sensor_manager_android_unittest.cc",
     "sensors/sensor_manager_chromeos_unittest.cc",
@@ -93,9 +91,6 @@
     "//device/generic_sensor",
     "//device/generic_sensor:testing",
     "//device/geolocation:unittests",
-    "//device/power_monitor",
-    "//device/power_monitor/public/cpp",
-    "//device/power_monitor/public/interfaces",
     "//device/power_save_blocker",
     "//device/sensors",
     "//device/sensors/public/cpp",
diff --git a/device/PRESUBMIT.py b/device/PRESUBMIT.py
deleted file mode 100644
index 3f9babe..0000000
--- a/device/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/device/power_monitor/power_monitor_export.h b/device/power_monitor/power_monitor_export.h
deleted file mode 100644
index ff6e367..0000000
--- a/device/power_monitor/power_monitor_export.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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 DEVICE_POWER_MONITOR_POWER_MONITOR_EXPORT_H_
-#define DEVICE_POWER_MONITOR_POWER_MONITOR_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(DEVICE_POWER_MONITOR_IMPLEMENTATION)
-#define DEVICE_POWER_MONITOR_EXPORT __declspec(dllexport)
-#else
-#define DEVICE_POWER_MONITOR_EXPORT __declspec(dllimport)
-#endif  // defined(DEVICE_POWER_MONITOR_IMPLEMENTATION)
-
-#else  // defined(WIN32)
-#if defined(DEVICE_POWER_MONITOR_IMPLEMENTATION)
-#define DEVICE_POWER_MONITOR_EXPORT __attribute__((visibility("default")))
-#else
-#define DEVICE_POWER_MONITOR_EXPORT
-#endif
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define DEVICE_POWER_MONITOR_EXPORT
-#endif
-
-#endif  // DEVICE_POWER_MONITOR_POWER_MONITOR_EXPORT_H_
diff --git a/device/power_monitor/public/interfaces/BUILD.gn b/device/power_monitor/public/interfaces/BUILD.gn
deleted file mode 100644
index 4dc40ef..0000000
--- a/device/power_monitor/public/interfaces/BUILD.gn
+++ /dev/null
@@ -1,11 +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.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-
-mojom("interfaces") {
-  sources = [
-    "power_monitor.mojom",
-  ]
-}
diff --git a/device/power_monitor/public/interfaces/OWNERS b/device/power_monitor/public/interfaces/OWNERS
deleted file mode 100644
index 5e4aaef..0000000
--- a/device/power_monitor/public/interfaces/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Changes to Mojo interfaces require a security review to avoid
-# introducing new sandbox escapes.
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/docs/code_reviews.md b/docs/code_reviews.md
new file mode 100644
index 0000000..fb307e2
--- /dev/null
+++ b/docs/code_reviews.md
@@ -0,0 +1,201 @@
+# Code Reviews
+
+Code reviews are a central part of developing high-quality code for Chromium.
+All changes must be reviewed.
+
+The bigger patch-upload-and-land process is covered in more detail the
+[contributing code](https://www.chromium.org/developers/contributing-code)
+page.
+
+# Code review policies
+
+Ideally the reviewer is someone who is familiar with the area of code you are
+touching. Any committer can review code, but an owner must provide a review
+for each directory you are touching. If you have doubts, look at the git blame
+for the file and the `OWNERS` files (see below).
+
+To indicate a positive review, the reviewer types "LGTM" (case insensitive)
+into a comment on the code review. This stands for "Looks Good To Me." The text
+"not LGTM" will cancel out a previous positive review.
+
+If you have multiple reviewers, make it clear in the message you send
+requesting review what you expect from each reviewer. Otherwise people might
+assume their input is not required or waste time with redundant reviews.
+
+#### Expectations for all reviewers
+
+  * Aim to provide some kind of actionable response within 24 hours of receipt
+    (not counting weekends and holidays). This doesn't mean you have to have
+    done a complete review, but you should be able to give some initial
+    feedback, request more time, or suggest another reviewer.
+
+  * It can be nice to indicate if you're away in your name in the code review
+    tool. If you do this, indicate when you'll be back.
+
+  * Don't generally discourage people from sending you code reviews. This
+    includes writing a blanket ("slow") after your name in the review tool.
+
+## OWNERS files
+
+In various directories there are files named `OWNERS` that list the email
+addresses of people qualified to review changes in that directory. You must
+get a positive review from an owner of each directory your change touches.
+
+Owners files are recursive, so each file also applies to its subdirectories.
+It's generally best to pick more specific owners. People listed in higher-level
+directories may have less experience with the code in question. More detail on
+the owners file format is provided in the "More information" section below.
+
+*Tip:* The `git cl owners` command can help find owners.
+
+While owners must approve all patches, any committer can contribute to the
+review. In some directories the owners can be overloaded or there might be
+people not listed as owners who are more familiar with the low-level code in
+question. In these cases it's common to request a low-level review from an
+appropriate person, and then request a high-level owner review once that's
+complete. As always, be clear what you expect of each reviewer to avoid
+duplicated work.
+
+Owners do not have to pick other owners for reviews. Since they should already
+be familiar with the code in question, a thorough review from any appropriate
+committer is sufficient.
+
+#### Expectations of owners
+
+The existing owners of a directory approve additions to the list. It is
+preferrable to have many directories, each with a smaller number of specific
+owners rather than large directories with many owners. Owners must:
+
+  * Demonstrate excellent judgment, teamwork and ability to uphold Chrome
+    development principles.
+
+  * Be already acting as an owner, providing high-quality reviews and design
+    feedback
+
+  * Be a Chromium project member with full commit access of at least 6
+    months tenure.
+
+  * Have submitted a substantial number of non-trivial changes to the affected
+    directory.
+
+  * Have committed or reviewed substantial work to the affected directory
+    within the last 90 days.
+
+  * Have the bandwidth to contribute to reviews in a timely manner. If the load
+    is unsustainable, work to expand the number of owners. Don't try to
+    discourage people from sending reviews, including writing "slow" or
+    "emeritus" after your name.
+
+Seldom-updated directories may have exceptions. Directories in `third_party`
+should list those most familiar with the library.
+
+## TBR ("To Be Reviewed")
+
+"TBR" is our mechanism for post-commit review. It should be used rarely and
+only in cases where a review is unnecessary or as described below. The most
+common use of TBR is to revert patches that broke the build.
+
+TBR does not mean "no review." A reviewer TBR-ed on a change should still
+review the change. If there comments after landing the author is obligated to
+address them in a followup patch.
+
+Do not use TBR just because a change is urgent or the reviewer is being slow.
+Contact the reviewer directly or find somebody.
+
+To send a change TBR, annotate the description and send email like normal.
+Otherwise the reviewer won't know to review the patch.
+
+  * Add the reviewer's email address in the code review tool's reviewer field
+    like normal.
+
+  * Add a line "TBR=<reviewer's email>" to the bottom of the change list
+    description.
+
+  * Push the "send mail" button.
+
+### TBR-ing certain types of mechanical changes
+
+Sometimes you might do something that affects many callers in different
+directories. For example, adding a parameter to a common function in //base.
+If the updates to the callers is mechanical, you can:
+
+  * Get a normal owner of the lower-level directory you're changing (in this
+    example, `//base`) to do a proper review of those changes.
+
+  * Get _somebody_ to review the downstream changes. This is often the same
+    person from the previous step but could be somebody else.
+
+  * Add the owners of the affected downstream directories as TBR.
+
+This process ensures that all code is reviewed prior to checkin and that the
+concept of the change is reviewed by a qualified person, but you don't have to
+track down many individual owners for trivial changes to their directories.
+
+### TBR-ing documentation updates
+
+You can TBR documentation updates. Documentation means markdown files, text
+documents, and high-level comments in code. At finer levels of detail, comments
+in source files become more like code and should be reviewed normally (not
+using TBR). Non-TBR-able stuff includes things like function contracts and most
+comments inside functions.
+
+  * Use good judgement. If you're changing something very important, tricky,
+    or something you may not be very familiar with, ask for the code review
+    up-front.
+
+  * Don't TBR changes to policy documents like the style guide or this document.
+
+  * Don't mix unrelated documentation updates with code changes.
+
+  * Be sure to actually send out the email for the code review. If you get one,
+    please actually read the changes.
+
+## More information
+
+### OWNERS file details
+
+Refer to the [source code](https://chromium.googlesource.com/chromium/tools/depot_tools/+/master/owners.py)
+for all details on the file format. 
+
+This example indicates that two people are owners, in addition to any owners
+from the parent directory. `git cl owners` will list the comment after an
+owner address, so this is a good place to include restrictions or special
+instructions.
+```
+# You can include comments like this.
+a@chromium.org
+b@chromium.org  # Only for the frobinator.
+```
+
+A `*` indicates that all committers are owners:
+```
+*
+```
+
+The text `set noparent` it will stop owner propagation from parent directories.
+This is used for specialized code. In this example, only the two listed people
+are owners:
+```
+set noparent
+a@chromium.org
+b@chromium.org
+```
+
+The `per-file` directive allows owners to be added that apply only to files
+matching a pattern. In this example, owners from the parent directiory
+apply, plus one person for some classes of files, and all committers are
+owners for the readme:
+```
+per-file foo_bar.cc=a@chromium.org
+per-file foo.*=a@chromium.org
+
+per-file readme.txt=*
+```
+
+Other `OWNERS` files can be included by reference by listing the path to the
+file with `file://...`. This example indicates that only the people listed in
+`//ipc/SECURITY_OWNERS` can review the messages files:
+```
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
+```
diff --git a/docs/testing/test_browser_dialog.md b/docs/testing/test_browser_dialog.md
new file mode 100644
index 0000000..c960455
--- /dev/null
+++ b/docs/testing/test_browser_dialog.md
@@ -0,0 +1,279 @@
+# Testing Chrome browser dialogs with TestBrowserDialog
+
+\#include "[chrome/browser/ui/test/test_browser_dialog.h]"
+
+`TestBrowserDialog` provides a way to register an `InProcessBrowserTest` testing
+harness with a framework that invokes Chrome browser dialogs in a consistent
+way. It optionally provides a way to invoke dialogs "interactively". This allows
+screenshots to be generated easily, with the same test data, to assist with UI
+review. It also provides a registry of dialogs so they can be systematically
+checked for subtle changes and regressions.
+
+[TOC]
+
+## How to register a dialog
+
+If registering an existing dialog, there's a chance it already has a test
+harness inheriting, using, or with `typedef InProcessBrowserTest` (or a
+descendant of it). If so, using `TestBrowserDialog` is straightforward. Assume
+the existing InProcessBrowserTest is in `foo_dialog_browsertest.cc`:
+
+    class FooDialogTest : public InProcessBrowserTest { ...
+
+Change this to inherit from DialogBrowserTest, and override
+`ShowDialog(std::string)`. See [Advanced Usage](#Advanced-Usage) for details.
+
+```cpp
+class FooDialogTest : public DialogBrowserTest {
+ public:
+  ..
+  // DialogBrowserTest:
+  void ShowDialog(const std::string& name) override {
+    /* Show dialog attached to browser() and leave it open. */
+  }
+  ..
+};
+```
+
+Then add test invocations using the usual GTest macros, in
+`foo_dialog_browsertest.cc`:
+
+```cpp
+IN_PROC_BROWSER_TEST_F(FooDialogTest, InvokeDialog_default) {
+  RunDialog();
+}
+```
+
+Notes:
+
+*   The body of the test is always just "`RunDialog();`".
+*   "`default`" is the `std::string` passed to `ShowDialog()` and can be
+    customized. See
+    [Testing additional dialog "styles"](#Testing-additional-dialog-styles_).
+*   The text before `default` (in this case) must always be "`InvokeDialog_`".
+
+### Concrete examples
+
+*   [chrome/browser/ui/ask_google_for_suggestions_dialog_browsertest.cc]
+*   [chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc]
+*   [chrome/browser/ui/collected_cookies_browsertest.cc]
+*   [chrome/browser/ui/update_chrome_dialog_browsertest.cc]
+
+##  Running the tests
+
+List the available dialogs with
+
+    $ ./browser_tests --gtest_filter=BrowserDialogTest.Invoke
+
+E.g. `FooDialogTest.InvokeDialog_default` should be listed. To show the dialog
+interactively, run
+
+    $ ./browser_tests --gtest_filter=BrowserDialogTest.Invoke --interactive \
+      --dialog=FooDialogTest.InvokeDialog_default
+
+### Implementation
+
+`BrowserDialogTest.Invoke` searches for gtests that have "`InvokeDialog_`"  in
+their name, so they can be collected in a list. Providing a `--dialog` argument
+will invoke that test case in a subprocess. Including `--interactive` will set
+up an environment for that subprocess that allows interactivity, e.g., to take
+screenshots. The test ends once the dialog is dismissed.
+
+The `FooDialogTest.InvokeDialog_default` test case **will still be run in the
+usual browser_tests test suite**. Ensure it passes, and isn’t flaky. This will
+give your dialog some regression test coverage. `RunDialog()` checks to ensure a
+dialog is actually created when it invokes `ShowDialog("default")`.
+
+### BrowserDialogTest.Invoke
+
+This is also run in browser_tests but, when run that way, the test case just
+lists the registered test harnesses (it does *not* iterate over them). A
+subprocess is never created unless --dialog is passed on the command line.
+
+## Advanced Usage
+
+If your test harness inherits from a descendant of `InProcessBrowserTest` (one
+example: [ExtensionBrowserTest]) then the `SupportsTestDialog<>` template is
+provided. E.g.
+
+```cpp
+class ExtensionInstallDialogViewTestBase : public ExtensionBrowserTest { ...
+```
+
+becomes
+
+```cpp
+class ExtensionInstallDialogViewTestBase :
+    public SupportsTestDialog<ExtensionBrowserTest> { ...
+```
+
+### Testing additional dialog "styles"
+
+Add additional test cases, with a different string after "`InvokeDialog_`".
+Example:
+
+```cpp
+IN_PROC_BROWSER_TEST_F(CardUnmaskViewBrowserTest, InvokeDialog_expired) {
+  RunDialog();
+}
+
+IN_PROC_BROWSER_TEST_F(CardUnmaskViewBrowserTest, InvokeDialog_valid) {
+  RunDialog();
+}
+```
+
+The strings "`expired`" or “`valid`” will be given as arguments to
+`ShowDialog(std::string)`.
+
+## Rationale
+
+Bug reference: [Issue 654151](http://crbug.com/654151).
+
+Chrome has a lot of browser dialogs; often for obscure use-cases and often hard
+to invoke. It has traditionally been difficult to be systematic while checking
+dialogs for possible regressions. For example, to investigate changes to shared
+layout parameters which are testable only with visual inspection.
+
+For Chrome UI review, screenshots need to be taken. Iterating over all the
+"styles" that a dialog may appear with is fiddly. E.g. a login or particular web
+server setup may be required. It’s important to provide a consistent “look” for
+UI review (e.g. same test data, same browser size, anchoring position, etc.).
+
+Some dialogs lack tests. Some dialogs have zero coverage on the bots. Dialogs
+can have tricky lifetimes and common mistakes are repeated. TestBrowserDialog
+runs simple "Show dialog" regression tests and can be extended to do more.
+
+Even discovering the full set of dialogs present for each platform in Chrome is
+[difficult](http://crbug.com/686239).
+
+### Why browser_tests?
+
+*   `browser_tests` already provides a `browser()->window()` of a consistent
+    size that can be used as a dialog anchor and to take screenshots for UI
+    review.
+    *   UI review have requested that screenshots be provided with the entire
+        browser window so that the relative size of the dialog/change under
+        review can be assessed.
+
+*   Some dialogs already have a test harness with appropriate setup (e.g. test
+    data) running in browser_tests.
+    *   Supporting `BrowserDialogTest` should require minimal setup and minimal
+        ongoing maintenance.
+
+*   An alternative is to maintain a working end-to-end build target executable
+    to do this, but this has additional costs (and is hard).
+    *    E.g. setup/teardown of low-level functions (
+         `InitializeGLOneOffPlatform()`,
+         `MaterialDesignController::Initialize()`, etc.).
+
+*   Why not chrome.exe?
+    *   E.g. a scrappy chrome:// page with links to invoke dialogs would be
+        great!
+    *   But...
+        *   A dialog may have test data (e.g. credit card info) which shouldn’t
+        be in the release build.
+        *   A dialog may use EmbeddedTestServer.
+        *   Higher maintenance cost - can’t leverage existing test harnesses.
+
+## Future Work
+
+*   Opt in more dialogs!
+    *    Eventually, all of them.
+    *    A `BrowserDialogTest` for every descendant of `views::DialogDelegate`.
+
+*   Automatically generate screenshots (for each platform, in various languages)
+    *    Build upon [CL 2008283002](https://codereview.chromium.org/2008283002/)
+
+*   (maybe) Try removing the subprocess
+    *    Probably requires altering the browser_test suite code directly rather
+         than just adding a test case as in the current approach
+
+*   An automated test suite for dialogs
+    *    Test various ways to dismiss or hide a dialog
+         *    e.g. native close (via taskbar?)
+         *    close parent window (possibly via task bar)
+         *    close parent tab
+         *    switch tabs
+         *    close via `DialogClientView::AcceptWindow` (and `CancelWindow`)
+         *    close via `Widget::Close`
+         *    close via `Widget::CloseNow`
+    *    Drag tab off browser into a new window
+    *    Fullscreen that may create a new window/parent
+
+*   Find obscure workflows for invoking dialogs that have no test coverage and
+    cause crashes (e.g. [http://crrev.com/426302](http://crrev.com/426302))
+    *   Supporting window-modal dialogs with a null parent window.
+
+*   Find memory leaks, e.g. [http://crrev.com/432320](http://crrev.com/432320)
+    *   "Fix memory leak for extension uninstall dialog".
+
+## Appendix: Sample output
+
+**$ ./out/gn_Debug/browser_tests --gtest_filter=BrowserDialogTest.Invoke**
+```
+Note: Google Test filter = BrowserDialogTest.Invoke
+[==========] Running 1 test from 1 test case.
+[----------] Global test environment set-up.
+[----------] 1 test from BrowserDialogTest
+[ RUN      ] BrowserDialogTest.Invoke
+[26879:775:0207/134949.118352:30434675...:INFO:browser_dialog_browsertest.cc(46)
+Pass one of the following after --dialog=
+  AskGoogleForSuggestionsDialogTest.InvokeDialog_default
+  CardUnmaskPromptViewBrowserTest.InvokeDialog_expired
+  CardUnmaskPromptViewBrowserTest.InvokeDialog_valid
+  CollectedCookiesTestMd.InvokeDialog_default
+  UpdateRecommendedDialogTest.InvokeDialog_default
+/* lots more will eventually be listed here */
+[       OK ] BrowserDialogTest.Invoke (0 ms)
+[----------] 1 test from BrowserDialogTest (0 ms total)
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test case ran. (1 ms total)
+[  PASSED  ] 1 test.
+[1/1] BrowserDialogTest.Invoke (334 ms)
+SUCCESS: all tests passed.
+```
+
+**$ ./out/gn_Debug/browser_tests --gtest_filter=BrowserDialogTest.Invoke
+--dialog=CardUnmaskPromptViewBrowserTest.InvokeDialog_expired**
+
+```
+Note: Google Test filter = BrowserDialogTest.Invoke
+[==========] Running 1 test from 1 test case.
+[----------] Global test environment set-up.
+[----------] 1 test from BrowserDialogTest
+[ RUN      ] BrowserDialogTest.Invoke
+Note: Google Test filter = CardUnmaskPromptViewBrowserTest.InvokeDefault
+[==========] Running 1 test from 1 test case.
+[----------] Global test environment set-up.
+[----------] 1 test from CardUnmaskPromptViewBrowserTest, where TypeParam =
+[ RUN      ] CardUnmaskPromptViewBrowserTest.InvokeDialog_expired
+/* 7 lines of uninteresting log spam */
+[       OK ] CardUnmaskPromptViewBrowserTest.InvokeDialog_expired (1324 ms)
+[----------] 1 test from CardUnmaskPromptViewBrowserTest (1324 ms total)
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test case ran. (1325 ms total)
+[  PASSED  ] 1 test.
+[       OK ] BrowserDialogTest.Invoke (1642 ms)
+[----------] 1 test from BrowserDialogTest (1642 ms total)
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test case ran. (1642 ms total)
+[  PASSED  ] 1 test.
+[1/1] BrowserDialogTest.Invoke (2111 ms)
+SUCCESS: all tests passed.
+```
+
+**$ ./out/gn_Debug/browser_tests --gtest_filter=BrowserDialogTest.Invoke
+--dialog=CardUnmaskPromptViewBrowserTest.InvokeDialog_expired --interactive**
+```
+/*
+ * Output as above, except the test are not interleaved, and the browser window
+ * should remain open until the dialog is dismissed
+ */
+```
+
+[chrome/browser/ui/test/test_browser_dialog.h]: https://cs.chromium.org/chromium/src/chrome/browser/ui/test/test_browser_dialog.h
+[chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc?l=104&q=ShowDialog
+[chrome/browser/ui/collected_cookies_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/collected_cookies_browsertest.cc?l=26&q=ShowDialog
+[chrome/browser/ui/ask_google_for_suggestions_dialog_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/ask_google_for_suggestions_dialog_browsertest.cc?l=18&q=ShowDialog
+[chrome/browser/ui/update_chrome_dialog_browsertest.cc]: https://cs.chromium.org/chromium/src/chrome/browser/ui/update_chrome_dialog_browsertest.cc?l=15&q=ShowDialog
+[ExtensionBrowserTest]: https://cs.chromium.org/chromium/src/chrome/browser/extensions/extension_browsertest.h?q=extensionbrowsertest&l=40
diff --git a/extensions/browser/PRESUBMIT.py b/extensions/browser/PRESUBMIT.py
index 5bd5fad..1a82b42 100644
--- a/extensions/browser/PRESUBMIT.py
+++ b/extensions/browser/PRESUBMIT.py
@@ -54,7 +54,6 @@
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results += _RunHistogramValueCheckers(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   results += _RunHistogramChecks(input_api, output_api,
     "BadMessageReasonExtensions")
   return results
diff --git a/extensions/browser/extension_navigation_throttle.cc b/extensions/browser/extension_navigation_throttle.cc
index 68c0a92..0c06bd83 100644
--- a/extensions/browser/extension_navigation_throttle.cc
+++ b/extensions/browser/extension_navigation_throttle.cc
@@ -90,7 +90,7 @@
             is_guest, extension, owner_extension, partition_id, resource_path,
             navigation_handle()->GetPageTransition(), &allowed);
         if (!allowed)
-          return content::NavigationThrottle::CANCEL;
+          return content::NavigationThrottle::BLOCK_REQUEST;
       }
     }
 
diff --git a/extensions/browser/guest_view/app_view/app_view_apitest.cc b/extensions/browser/guest_view/app_view/app_view_apitest.cc
index 43f997e6..ffa7020 100644
--- a/extensions/browser/guest_view/app_view/app_view_apitest.cc
+++ b/extensions/browser/guest_view/app_view/app_view_apitest.cc
@@ -146,6 +146,10 @@
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     AppShellTest::SetUpCommandLine(command_line);
+    // This switch ensures that there will always be at least one media device,
+    // even on machines without physical devices. This is required by tests that
+    // request permission to use media devices.
+    command_line->AppendSwitch("use-fake-device-for-media-stream");
 
     bool use_cross_process_frames_for_guests = GetParam();
     if (use_cross_process_frames_for_guests) {
diff --git a/extensions/common/PRESUBMIT.py b/extensions/common/PRESUBMIT.py
deleted file mode 100644
index 16c1946..0000000
--- a/extensions/common/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Chromium presubmit script for src/extensions/common.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details on the presubmit API built into depot_tools.
-"""
-
-import sys
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc
index 3d7128ad..31d2db8d 100644
--- a/extensions/renderer/module_system.cc
+++ b/extensions/renderer/module_system.cc
@@ -544,11 +544,12 @@
 
 void ModuleSystem::OnNativeBindingCreated(
     const std::string& api_name,
-    v8::Local<v8::Value> api_bridge_value) {
+    v8::Local<v8::Value> api_bridge_value,
+    v8::Local<v8::Value> get_internal_api) {
   v8::HandleScope scope(GetIsolate());
   if (source_map_->Contains(api_name)) {
     NativesEnabledScope enabled(this);
-    LoadModuleWithNativeAPIBridge(api_name, api_bridge_value);
+    LoadModuleWithNativeAPIBridge(api_name, api_bridge_value, get_internal_api);
   }
 }
 
@@ -632,7 +633,7 @@
   v8::Local<v8::String> left = ToV8StringUnsafe(
       GetIsolate(),
       "(function(define, require, requireNative, requireAsync, exports, "
-      "console, privates, apiBridge,"
+      "console, privates, apiBridge, getInternalApi,"
       "$Array, $Function, $JSON, $Object, $RegExp, $String, $Error) {"
       "'use strict';");
   v8::Local<v8::String> right = ToV8StringUnsafe(GetIsolate(), "\n})");
@@ -670,13 +671,14 @@
 }
 
 v8::Local<v8::Value> ModuleSystem::LoadModule(const std::string& module_name) {
-  return LoadModuleWithNativeAPIBridge(module_name,
+  return LoadModuleWithNativeAPIBridge(module_name, v8::Undefined(GetIsolate()),
                                        v8::Undefined(GetIsolate()));
 }
 
 v8::Local<v8::Value> ModuleSystem::LoadModuleWithNativeAPIBridge(
     const std::string& module_name,
-    v8::Local<v8::Value> api_bridge) {
+    v8::Local<v8::Value> api_bridge,
+    v8::Local<v8::Value> get_internal_api) {
   v8::EscapableHandleScope handle_scope(GetIsolate());
   v8::Local<v8::Context> v8_context = context()->v8_context();
   v8::Context::Scope context_scope(v8_context);
@@ -746,7 +748,8 @@
       console::AsV8Object(GetIsolate()),
       GetPropertyUnsafe(v8_context, natives, "privates",
                         v8::NewStringType::kInternalized),
-      api_bridge,  // exposed as apiBridge.
+      api_bridge,        // exposed as apiBridge.
+      get_internal_api,  // exposed as getInternalApi.
       // Each safe builtin. Keep in order with the arguments in WrapSource.
       context_->safe_builtins()->GetArray(),
       context_->safe_builtins()->GetFunction(),
diff --git a/extensions/renderer/module_system.h b/extensions/renderer/module_system.h
index c15ffb0..9ef1f89b 100644
--- a/extensions/renderer/module_system.h
+++ b/extensions/renderer/module_system.h
@@ -158,7 +158,8 @@
   // TODO(devlin): We can get rid of this once we convert all our custom
   // bindings.
   void OnNativeBindingCreated(const std::string& api_name,
-                              v8::Local<v8::Value> api_bridge_value);
+                              v8::Local<v8::Value> api_bridge_value,
+                              v8::Local<v8::Value> get_internal_api);
 
  protected:
   friend class ModuleSystemTestEnvironment;
@@ -218,7 +219,8 @@
   v8::Local<v8::Value> LoadModule(const std::string& module_name);
   v8::Local<v8::Value> LoadModuleWithNativeAPIBridge(
       const std::string& module_name,
-      v8::Local<v8::Value> api_object);
+      v8::Local<v8::Value> api_object,
+      v8::Local<v8::Value> get_internal_api);
 
   // Invoked when a module is loaded in response to a requireAsync call.
   // Resolves |resolver| with |value|.
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc
index e20a54f..1ff3cd5 100644
--- a/extensions/renderer/native_extension_bindings_system.cc
+++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -63,6 +63,7 @@
   ~BindingsSystemPerContextData() override {}
 
   v8::Global<v8::Object> api_object;
+  v8::Global<v8::Object> internal_apis;
   base::WeakPtr<NativeExtensionBindingsSystem> bindings_system;
 };
 
@@ -99,6 +100,23 @@
   return v8::Local<v8::Object>();
 }
 
+BindingsSystemPerContextData* GetBindingsDataFromContext(
+    v8::Local<v8::Context> context) {
+  gin::PerContextData* per_context_data = gin::PerContextData::From(context);
+  if (!per_context_data)
+    return nullptr;  // Context is shutting down.
+
+  auto* data = static_cast<BindingsSystemPerContextData*>(
+      per_context_data->GetUserData(kBindingsSystemPerContextKey));
+  CHECK(data);
+  if (!data->bindings_system) {
+    NOTREACHED() << "Context outlived bindings system.";
+    return nullptr;
+  }
+
+  return data;
+}
+
 // Handler for calling safely into JS.
 void CallJsFunction(v8::Local<v8::Function> function,
                     v8::Local<v8::Context> context,
@@ -152,6 +170,32 @@
   return context->GetAvailability(method_name).is_available();
 }
 
+// Instantiates the binding object for the given |name|. |name| must specify a
+// specific feature.
+v8::Local<v8::Object> CreateRootBinding(
+    v8::Local<v8::Context> context,
+    ScriptContext* script_context,
+    const std::string& name,
+    APIBindingsSystem* bindings_system,
+    v8::Local<v8::Function> get_internal_api) {
+  v8::Local<v8::Object> hooks_interface;
+  v8::Local<v8::Object> binding_object = bindings_system->CreateAPIInstance(
+      name, context, context->GetIsolate(),
+      base::Bind(&IsAPIMethodAvailable, script_context), &hooks_interface);
+
+  gin::Handle<APIBindingBridge> bridge_handle = gin::CreateHandle(
+      context->GetIsolate(),
+      new APIBindingBridge(context, binding_object, hooks_interface,
+                           script_context->GetExtensionID(),
+                           script_context->GetContextTypeDescription(),
+                           base::Bind(&CallJsFunction)));
+  v8::Local<v8::Value> native_api_bridge = bridge_handle.ToV8();
+  script_context->module_system()->OnNativeBindingCreated(
+      name, native_api_bridge, get_internal_api);
+
+  return binding_object;
+}
+
 // Creates the binding object for the given |root_name|. This can be
 // complicated, since APIs may have prefixed names, like 'app.runtime' or
 // 'system.cpu'. This method accepts the first name (i.e., the key that we are
@@ -169,7 +213,8 @@
     ScriptContext* script_context,
     APIBindingsSystem* bindings_system,
     const FeatureProvider* api_feature_provider,
-    const std::string& root_name) {
+    const std::string& root_name,
+    v8::Local<v8::Function> get_internal_api) {
   const FeatureMap& features = api_feature_provider->GetAllFeatures();
   auto lower = features.lower_bound(root_name);
   DCHECK(lower != features.end());
@@ -183,22 +228,8 @@
   if (lower->first == root_name) {
     if (script_context->IsAnyFeatureAvailableToContext(
             *lower->second, CheckAliasStatus::NOT_ALLOWED)) {
-      v8::Local<v8::Object> hooks_interface;
-      v8::Local<v8::Object> binding_object = bindings_system->CreateAPIInstance(
-          root_name, context, context->GetIsolate(),
-          base::Bind(&IsAPIMethodAvailable, script_context), &hooks_interface);
-
-      gin::Handle<APIBindingBridge> bridge_handle = gin::CreateHandle(
-          context->GetIsolate(),
-          new APIBindingBridge(context, binding_object, hooks_interface,
-                               script_context->GetExtensionID(),
-                               script_context->GetContextTypeDescription(),
-                               base::Bind(&CallJsFunction)));
-      v8::Local<v8::Value> native_api_bridge = bridge_handle.ToV8();
-      script_context->module_system()->OnNativeBindingCreated(
-          root_name, native_api_bridge);
-
-      root_binding = binding_object;
+      root_binding = CreateRootBinding(context, script_context, root_name,
+                                       bindings_system, get_internal_api);
     }
     ++lower;
   }
@@ -252,9 +283,9 @@
     base::StringPiece binding_name =
         GetFirstDifferentAPIName(iter->first, root_name);
 
-    v8::Local<v8::Object> nested_binding =
-        CreateFullBinding(context, script_context, bindings_system,
-                          api_feature_provider, binding_name.as_string());
+    v8::Local<v8::Object> nested_binding = CreateFullBinding(
+        context, script_context, bindings_system, api_feature_provider,
+        binding_name.as_string(), get_internal_api);
     // It's possible that we don't create a binding if no features or
     // prefixed features are available to the context.
     if (nested_binding.IsEmpty())
@@ -411,25 +442,28 @@
   v8::Isolate* isolate = info.GetIsolate();
   v8::HandleScope handle_scope(isolate);
   v8::Local<v8::Context> context = info.Holder()->CreationContext();
-  gin::PerContextData* per_context_data = gin::PerContextData::From(context);
-  if (!per_context_data)
-    return;  // Context is shutting down.
-  BindingsSystemPerContextData* data =
-      static_cast<BindingsSystemPerContextData*>(
-          per_context_data->GetUserData(kBindingsSystemPerContextKey));
-  CHECK(data);
-  if (!data->bindings_system) {
-    NOTREACHED() << "Context outlived bindings system.";
+  BindingsSystemPerContextData* data = GetBindingsDataFromContext(context);
+  if (!data)
     return;
-  }
 
   v8::Local<v8::Object> apis;
   if (data->api_object.IsEmpty()) {
     apis = v8::Object::New(isolate);
     data->api_object = v8::Global<v8::Object>(isolate, apis);
+    if (data->bindings_system->get_internal_api_.IsEmpty()) {
+      data->bindings_system->get_internal_api_.Set(
+          isolate, v8::FunctionTemplate::New(
+                       isolate, &NativeExtensionBindingsSystem::GetInternalAPI,
+                       v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0,
+                       v8::ConstructorBehavior::kThrow));
+    }
   } else {
     apis = data->api_object.Get(isolate);
   }
+  v8::Local<v8::Function> get_internal_api =
+      data->bindings_system->get_internal_api_.Get(isolate)
+          ->GetFunction(context)
+          .ToLocalChecked();
 
   // We use info.Data() to store a real name here instead of using the provided
   // one to handle any weirdness from the caller (non-existent strings, etc).
@@ -448,10 +482,9 @@
     CHECK(gin::Converter<std::string>::FromV8(isolate, api_name,
                                               &api_name_string));
 
-    v8::Local<v8::Object> root_binding =
-        CreateFullBinding(context, script_context,
-                          &data->bindings_system->api_system_,
-                          FeatureProvider::GetAPIFeatures(), api_name_string);
+    v8::Local<v8::Object> root_binding = CreateFullBinding(
+        context, script_context, &data->bindings_system->api_system_,
+        FeatureProvider::GetAPIFeatures(), api_name_string, get_internal_api);
     if (root_binding.IsEmpty())
       return;
 
@@ -466,6 +499,82 @@
   info.GetReturnValue().Set(result);
 }
 
+// static
+void NativeExtensionBindingsSystem::GetInternalAPI(
+    const v8::FunctionCallbackInfo<v8::Value>& info) {
+  CHECK_EQ(1, info.Length());
+  CHECK(info[0]->IsString());
+
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
+  v8::Local<v8::String> v8_name = info[0].As<v8::String>();
+
+  BindingsSystemPerContextData* data = GetBindingsDataFromContext(context);
+  CHECK(data);
+
+  v8::Local<v8::Object> internal_apis;
+  if (data->internal_apis.IsEmpty()) {
+    internal_apis = v8::Object::New(isolate);
+    data->internal_apis.Reset(isolate, internal_apis);
+  } else {
+    internal_apis = data->internal_apis.Get(isolate);
+  }
+
+  v8::Maybe<bool> has_property =
+      internal_apis->HasOwnProperty(context, v8_name);
+  if (!has_property.IsJust())
+    return;
+
+  if (has_property.FromJust()) {
+    // API was already instantiated.
+    info.GetReturnValue().Set(
+        internal_apis->GetRealNamedProperty(context, v8_name).ToLocalChecked());
+    return;
+  }
+
+  std::string api_name = gin::V8ToString(info[0]);
+  const Feature* feature = FeatureProvider::GetAPIFeature(api_name);
+  ScriptContext* script_context =
+      ScriptContextSet::GetContextByV8Context(context);
+  if (!feature ||
+      !script_context->IsAnyFeatureAvailableToContext(
+          *feature, CheckAliasStatus::NOT_ALLOWED)) {
+    NOTREACHED();
+    return;
+  }
+
+  CHECK(feature->IsInternal());
+
+  // This is only called from the custom bindings for another API, so
+  // |get_internal_api| must have been initialized.
+  DCHECK(!data->bindings_system->get_internal_api_.IsEmpty());
+  v8::Local<v8::Function> get_internal_api =
+      data->bindings_system->get_internal_api_.Get(isolate)
+          ->GetFunction(context)
+          .ToLocalChecked();
+
+  // We don't need to go through CreateFullBinding here because internal APIs
+  // are always acquired through getInternalBinding and specified by full name,
+  // rather than through access on the chrome object. So we can just instantiate
+  // a binding keyed with any name, even a prefixed one (e.g.
+  // 'app.currentWindowInternal').
+  v8::Local<v8::Object> api_binding =
+      CreateRootBinding(context, script_context, api_name,
+                        &data->bindings_system->api_system_, get_internal_api);
+
+  if (api_binding.IsEmpty())
+    return;
+
+  v8::Maybe<bool> success =
+      internal_apis->CreateDataProperty(context, v8_name, api_binding);
+  if (!success.IsJust() || !success.FromJust())
+    return;
+
+  info.GetReturnValue().Set(api_binding);
+}
+
 void NativeExtensionBindingsSystem::SendRequest(
     std::unique_ptr<APIBinding::Request> request,
     v8::Local<v8::Context> context) {
diff --git a/extensions/renderer/native_extension_bindings_system.h b/extensions/renderer/native_extension_bindings_system.h
index da55d76..b414fc1 100644
--- a/extensions/renderer/native_extension_bindings_system.h
+++ b/extensions/renderer/native_extension_bindings_system.h
@@ -71,6 +71,9 @@
   static void GetAPIHelper(v8::Local<v8::Name> name,
                            const v8::PropertyCallbackInfo<v8::Value>& info);
 
+  // Callback to get an API binding for an internal API.
+  static void GetInternalAPI(const v8::FunctionCallbackInfo<v8::Value>& info);
+
   // Handler to send request IPCs. Abstracted out for testing purposes.
   SendRequestIPCMethod send_request_ipc_;
 
@@ -81,6 +84,9 @@
   // The APIBindingsSystem associated with this class.
   APIBindingsSystem api_system_;
 
+  // A function to acquire an internal API.
+  v8::Eternal<v8::FunctionTemplate> get_internal_api_;
+
   base::WeakPtrFactory<NativeExtensionBindingsSystem> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(NativeExtensionBindingsSystem);
diff --git a/extensions/renderer/resources/app_runtime_custom_bindings.js b/extensions/renderer/resources/app_runtime_custom_bindings.js
index 4dfa0c4..f40f44df 100644
--- a/extensions/renderer/resources/app_runtime_custom_bindings.js
+++ b/extensions/renderer/resources/app_runtime_custom_bindings.js
@@ -4,10 +4,12 @@
 
 // Custom binding for the chrome.app.runtime API.
 
-var binding = require('binding').Binding.create('app.runtime');
+var binding = apiBridge || require('binding').Binding.create('app.runtime');
 
 var AppViewGuestInternal =
-    require('binding').Binding.create('appViewGuestInternal').generate();
+    getInternalApi ?
+        getInternalApi('appViewGuestInternal') :
+        require('binding').Binding.create('appViewGuestInternal').generate();
 var eventBindings = require('event_bindings');
 var fileSystemHelpers = requireNative('file_system_natives');
 var GetIsolatedFileSystem = fileSystemHelpers.GetIsolatedFileSystem;
@@ -81,4 +83,5 @@
   }
 });
 
-exports.$set('binding', binding.generate());
+if (!apiBridge)
+  exports.$set('binding', binding.generate());
diff --git a/extensions/renderer/resources/app_window_custom_bindings.js b/extensions/renderer/resources/app_window_custom_bindings.js
index 376e367..2917c32 100644
--- a/extensions/renderer/resources/app_window_custom_bindings.js
+++ b/extensions/renderer/resources/app_window_custom_bindings.js
@@ -6,7 +6,6 @@
 
 var appWindowNatives = requireNative('app_window_natives');
 var runtimeNatives = requireNative('runtime');
-var Binding = require('binding').Binding;
 var Event = require('event_bindings').Event;
 var forEach = require('utils').forEach;
 var renderFrameObserverNatives = requireNative('renderFrameObserverNatives');
@@ -18,6 +17,9 @@
 var kSetBoundsFunction = 'setBounds';
 var kSetSizeConstraintsFunction = 'setSizeConstraints';
 
+if (!apiBridge)
+  var binding = require('binding').Binding;
+
 // Bounds class definition.
 var Bounds = function(boundsKey) {
   privates(this).boundsKey_ = boundsKey;
@@ -109,7 +111,7 @@
                         { maxWidth: maxWidth, maxHeight: maxHeight });
 };
 
-var appWindow = Binding.create('app.window');
+var appWindow = apiBridge || binding.create('app.window');
 appWindow.registerCustomHook(function(bindingsAPI) {
   var apiFunctions = bindingsAPI.apiFunctions;
 
@@ -207,7 +209,9 @@
   // currentWindowInternal, appWindowData, etc.
   apiFunctions.setHandleRequest('initializeAppWindow', function(params) {
     currentWindowInternal =
-        Binding.create('app.currentWindowInternal').generate();
+        getInternalApi ?
+            getInternalApi('app.currentWindowInternal') :
+        binding.create('app.currentWindowInternal').generate();
     var AppWindow = function() {
       this.innerBounds = new Bounds('innerBounds');
       this.outerBounds = new Bounds('outerBounds');
@@ -384,6 +388,7 @@
   currentWindowInternal.setSizeConstraints(boundsType, constraints);
 }
 
-exports.$set('binding', appWindow.generate());
+if (!apiBridge)
+  exports.$set('binding', appWindow.generate());
 exports.$set('onAppWindowClosed', onAppWindowClosed);
 exports.$set('updateAppWindowProperties', updateAppWindowProperties);
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h
index 6566974..21a2a281 100644
--- a/gpu/command_buffer/service/context_state.h
+++ b/gpu/command_buffer/service/context_state.h
@@ -63,56 +63,80 @@
   // glBindTexture
   scoped_refptr<TextureRef> bound_texture_2d_array;
 
-  scoped_refptr<TextureRef> GetInfoForSamplerType(
-      GLenum type) {
+  TextureRef* GetInfoForSamplerType(GLenum type) {
     switch (type) {
       case GL_SAMPLER_2D:
       case GL_SAMPLER_2D_SHADOW:
       case GL_INT_SAMPLER_2D:
       case GL_UNSIGNED_INT_SAMPLER_2D:
-        return bound_texture_2d;
+        return bound_texture_2d.get();
       case GL_SAMPLER_CUBE:
       case GL_SAMPLER_CUBE_SHADOW:
       case GL_INT_SAMPLER_CUBE:
       case GL_UNSIGNED_INT_SAMPLER_CUBE:
-        return bound_texture_cube_map;
+        return bound_texture_cube_map.get();
       case GL_SAMPLER_EXTERNAL_OES:
-        return bound_texture_external_oes;
+        return bound_texture_external_oes.get();
       case GL_SAMPLER_2D_RECT_ARB:
-        return bound_texture_rectangle_arb;
+        return bound_texture_rectangle_arb.get();
       case GL_SAMPLER_3D:
       case GL_INT_SAMPLER_3D:
       case GL_UNSIGNED_INT_SAMPLER_3D:
-        return bound_texture_3d;
+        return bound_texture_3d.get();
       case GL_SAMPLER_2D_ARRAY:
       case GL_SAMPLER_2D_ARRAY_SHADOW:
       case GL_INT_SAMPLER_2D_ARRAY:
       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
-        return bound_texture_2d_array;
+        return bound_texture_2d_array.get();
+      default:
+        NOTREACHED();
+        return nullptr;
     }
-
-    NOTREACHED();
-    return nullptr;
   }
 
-  scoped_refptr<TextureRef>& GetInfoForTarget(GLenum target) {
+  TextureRef* GetInfoForTarget(GLenum target) {
     switch (target) {
       case GL_TEXTURE_2D:
-        return bound_texture_2d;
+        return bound_texture_2d.get();
       case GL_TEXTURE_CUBE_MAP:
-        return bound_texture_cube_map;
+        return bound_texture_cube_map.get();
       case GL_TEXTURE_EXTERNAL_OES:
-        return bound_texture_external_oes;
+        return bound_texture_external_oes.get();
       case GL_TEXTURE_RECTANGLE_ARB:
-        return bound_texture_rectangle_arb;
+        return bound_texture_rectangle_arb.get();
       case GL_TEXTURE_3D:
-        return bound_texture_3d;
+        return bound_texture_3d.get();
       case GL_TEXTURE_2D_ARRAY:
-        return bound_texture_2d_array;
+        return bound_texture_2d_array.get();
+      default:
+        NOTREACHED();
+        return nullptr;
     }
+  }
 
-    NOTREACHED();
-    return bound_texture_2d;
+  void SetInfoForTarget(GLenum target, TextureRef* texture_ref) {
+    switch (target) {
+      case GL_TEXTURE_2D:
+        bound_texture_2d = texture_ref;
+        break;
+      case GL_TEXTURE_CUBE_MAP:
+        bound_texture_cube_map = texture_ref;
+        break;
+      case GL_TEXTURE_EXTERNAL_OES:
+        bound_texture_external_oes = texture_ref;
+        break;
+      case GL_TEXTURE_RECTANGLE_ARB:
+        bound_texture_rectangle_arb = texture_ref;
+        break;
+      case GL_TEXTURE_3D:
+        bound_texture_3d = texture_ref;
+        break;
+      case GL_TEXTURE_2D_ARRAY:
+        bound_texture_2d_array = texture_ref;
+        break;
+      default:
+        NOTREACHED();
+    }
   }
 };
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index ca955da..355540c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2474,8 +2474,8 @@
   DCHECK(!state->texture_units.empty());
   TextureUnit& info = state->texture_units[0];
   GLuint last_id;
-  scoped_refptr<TextureRef>& texture_ref = info.GetInfoForTarget(target);
-  if (texture_ref.get()) {
+  TextureRef* texture_ref = info.GetInfoForTarget(target);
+  if (texture_ref) {
     last_id = texture_ref->service_id();
   } else {
     last_id = 0;
@@ -5788,7 +5788,7 @@
 
   TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
   unit.bind_target = target;
-  unit.GetInfoForTarget(target) = texture_ref;
+  unit.SetInfoForTarget(target, texture_ref);
 }
 
 void GLES2DecoderImpl::DoBindSampler(GLuint unit, GLuint client_id) {
@@ -8854,7 +8854,7 @@
         continue;
       TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
       TextureRef* texture_ref =
-          texture_unit.GetInfoForSamplerType(uniform_info->type).get();
+          texture_unit.GetInfoForSamplerType(uniform_info->type);
       if (attachment->IsTexture(texture_ref))
         return true;
     }
@@ -9562,7 +9562,7 @@
       if (texture_unit_index < state_.texture_units.size()) {
         TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
         TextureRef* texture_ref =
-            texture_unit.GetInfoForSamplerType(uniform_info->type).get();
+            texture_unit.GetInfoForSamplerType(uniform_info->type);
         GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
         const SamplerState& sampler_state = GetSamplerStateForTextureUnit(
             uniform_info->type, texture_unit_index);
@@ -9623,7 +9623,7 @@
       if (texture_unit_index < state_.texture_units.size()) {
         TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
         TextureRef* texture_ref =
-            texture_unit.GetInfoForSamplerType(uniform_info->type).get();
+            texture_unit.GetInfoForSamplerType(uniform_info->type);
         const SamplerState& sampler_state = GetSamplerStateForTextureUnit(
             uniform_info->type, texture_unit_index);
         if (!texture_ref ||
@@ -9632,7 +9632,7 @@
           glActiveTexture(GL_TEXTURE0 + texture_unit_index);
           // Get the texture_ref info that was previously bound here.
           texture_ref =
-              texture_unit.GetInfoForTarget(texture_unit.bind_target).get();
+              texture_unit.GetInfoForTarget(texture_unit.bind_target);
           glBindTexture(texture_unit.bind_target,
                         texture_ref ? texture_ref->service_id() : 0);
           continue;
@@ -9663,7 +9663,7 @@
         if (texture_unit_index < state_.texture_units.size()) {
           TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
           TextureRef* texture_ref =
-              texture_unit.GetInfoForSamplerType(uniform_info->type).get();
+              texture_unit.GetInfoForSamplerType(uniform_info->type);
           if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
             if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
               return false;
@@ -14166,8 +14166,8 @@
         target != GL_TEXTURE_CUBE_MAP_POSITIVE_X) {
       for (int i = 0; i < 2; ++i) {
         TextureManager::DoTexImageArguments args = {
-          target, i, final_internal_format, 1, 1, 1, border,
-          format, type, nullptr, 1, 0,
+          target, i, final_internal_format, width, height, 1, border,
+          format, type, nullptr, pixels_size, 0,
           TextureManager::DoTexImageArguments::kTexImage2D };
         texture_manager()->WorkaroundCopyTexImageCubeMap(&texture_state_,
             &state_, &framebuffer_state_, texture_ref, func_name, args);
@@ -17247,9 +17247,9 @@
                                        "mailbox that was not generated by "
                                        "GenMailboxCHROMIUM.";
 
-  scoped_refptr<TextureRef> texture_ref =
+  TextureRef* texture_ref =
       texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
-  if (!texture_ref.get()) {
+  if (!texture_ref) {
     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
                        "glConsumeTextureCHROMIUM",
                        "unknown texture for target");
@@ -17284,7 +17284,7 @@
 
   TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
   unit.bind_target = target;
-  unit.GetInfoForTarget(target) = texture_ref;
+  unit.SetInfoForTarget(target, texture_ref);
 }
 
 void GLES2DecoderImpl::EnsureTextureForClientId(
@@ -19020,7 +19020,7 @@
       return sampler->sampler_state();
   }
   TextureUnit& texture_unit = state_.texture_units[unit];
-  TextureRef* texture_ref = texture_unit.GetInfoForSamplerType(target).get();
+  TextureRef* texture_ref = texture_unit.GetInfoForSamplerType(target);
   if (texture_ref)
     return texture_ref->texture()->sampler_state();
 
diff --git a/ios/BUILD.gn b/ios/BUILD.gn
index 59c46da..b080ddbf 100644
--- a/ios/BUILD.gn
+++ b/ios/BUILD.gn
@@ -4,12 +4,9 @@
 
 assert(!is_component_build, "component build is unsupported on iOS")
 
-declare_args() {
-  # Control whether cronet is build (this is usually set by the script
-  # components/cronet/tools/cr_cronet.py as cronet requires specific
-  # gn args to build correctly).
-  is_cronet_build = false
+import("//ios/features.gni")
 
+declare_args() {
   # TODO(brettw) bug 684096: Remove these. These are to prevent unused
   # override warnings on iOS from the setting of the default_args in the
   # toplevel //.gn file. Since iOS doesn't compile V8, GN complains that
diff --git a/ios/PRESUBMIT.py b/ios/PRESUBMIT.py
deleted file mode 100644
index 07c61c0c..0000000
--- a/ios/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Presubmit script for ios.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/ios/build/bots/chromium.mac/ios-simulator.json b/ios/build/bots/chromium.mac/ios-simulator.json
index 2b810acc..b0c0181 100644
--- a/ios/build/bots/chromium.mac/ios-simulator.json
+++ b/ios/build/bots/chromium.mac/ios-simulator.json
@@ -1,8 +1,6 @@
 {
   "comments": [
-    "Tests for 64-bit iOS 10.0 simulators.",
-    "Tests run on iPhone 6s and iPad Air 2, both 64-bit.",
-    "Build is performed with gn+ninja."
+    "Runs tests on @3x, @2x, 64-bit, 32-bit, phone, tablet, iOS 10, and iOS 9."
   ],
   "xcode version": "8.0",
   "gn_args": [
@@ -23,13 +21,53 @@
   "tests": [
     {
       "include": "common_tests.json",
+      "device type": "iPhone 6s Plus",
+      "os": "10.0"
+    },
+    {
+      "include": "common_tests.json",
       "device type": "iPhone 6s",
       "os": "10.0"
     },
     {
       "include": "common_tests.json",
+      "device type": "iPhone 5",
+      "os": "10.0"
+    },
+    {
+      "include": "common_tests.json",
       "device type": "iPad Air 2",
       "os": "10.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPad Retina",
+      "os": "10.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone 6s Plus",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone 6s",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone 5",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPad Air 2",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPad Retina",
+      "os": "9.0"
     }
   ]
 }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 3aaa1d9..fa2f5539 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -534,8 +534,6 @@
 // Initializes the application to INITIALIZATION_STAGE_FOREGROUND, which is
 // needed when application runs in foreground.
 - (void)startUpBrowserForegroundInitialization;
-// Swaps the UI between Incognito and normal modes.
-- (void)swapBrowserModes;
 @end
 
 @implementation MainController
@@ -820,17 +818,13 @@
 - (void)deleteIncognitoBrowserState {
   BOOL otrBVCIsCurrent = (self.currentBVC == self.otrBVC);
 
-  const BOOL isOnIPadWithTabSwitcherEnabled =
-      IsIPadIdiom() && experimental_flags::IsTabSwitcherEnabled();
-
   // If the current BVC is the otr BVC, then the user should be in the card
   // stack, this is not true for the iPad tab switcher.
-  DCHECK(isOnIPadWithTabSwitcherEnabled ||
-         (!otrBVCIsCurrent || _tabSwitcherIsActive));
+  DCHECK(IsIPadIdiom() || (!otrBVCIsCurrent || _tabSwitcherIsActive));
 
   // We always clear the otr tab model on iPad.
   // Notify the _tabSwitcherController that its otrBVC will be destroyed.
-  if (isOnIPadWithTabSwitcherEnabled || _tabSwitcherIsActive)
+  if (IsIPadIdiom() || _tabSwitcherIsActive)
     [_tabSwitcherController setOtrTabModel:nil];
 
   [_browserViewWrangler
@@ -842,7 +836,7 @@
 
   // Always set the new otr tab model on iPad with tab switcher enabled.
   // Notify the _tabSwitcherController with the new otrBVC.
-  if (isOnIPadWithTabSwitcherEnabled || _tabSwitcherIsActive)
+  if (IsIPadIdiom() || _tabSwitcherIsActive)
     [_tabSwitcherController setOtrTabModel:self.otrTabModel];
 }
 
@@ -1442,10 +1436,6 @@
     case IDC_OPEN_URL:
       [self openUrl:base::mac::ObjCCast<OpenUrlCommand>(sender)];
       break;
-    case IDC_SWITCH_BROWSER_MODES:
-      DCHECK(IsIPadIdiom());
-      [self swapBrowserModes];
-      break;
     case IDC_OPTIONS:
       [self showSettings];
       break;
@@ -1484,8 +1474,7 @@
       break;
     case IDC_TOGGLE_TAB_SWITCHER:
       DCHECK(!_tabSwitcherIsActive);
-      if ((!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) &&
-          !_isProcessingVoiceSearchCommand) {
+      if (!_isProcessingVoiceSearchCommand) {
         [self showTabSwitcher];
         _isProcessingTabSwitcherCommand = YES;
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
@@ -1702,12 +1691,7 @@
   }
 
   if (IsIPadIdiom()) {
-    if (experimental_flags::IsTabSwitcherEnabled()) {
-      [self showTabSwitcher];
-    } else {
-      // Mode switch if not in regular mode.
-      [self swapBrowserModes];
-    }
+    [self showTabSwitcher];
   } else {
     self.currentBVC = self.mainBVC;
     if ([self.currentTabModel count] == 0U) {
@@ -1727,13 +1711,7 @@
     return;
   }
 
-  if (IsIPadIdiom()) {
-    if (experimental_flags::IsTabSwitcherEnabled()) {
-      [self showTabSwitcher];
-    }
-  } else {
-    [self showTabSwitcher];
-  }
+  [self showTabSwitcher];
 }
 
 #pragma mark - Mode Switching
@@ -1775,17 +1753,6 @@
   return self.currentBVC.browserState;
 }
 
-- (void)swapBrowserModes {
-  if (self.mainBVC == self.currentBVC)
-    self.currentBVC = self.otrBVC;
-  else
-    self.currentBVC = self.mainBVC;
-  // Make sure there is at least one tab open.
-  if ([self shouldOpenNTPTabOnActivationOfTabModel:[self currentTabModel]])
-    [self.currentBVC newTab:nil];
-  [_browserViewWrangler updateModeToggle];
-}
-
 // NOTE: If you change this function, it may have an effect on the performance
 // of opening the stack view. Please make sure you also change the corresponding
 // code in StackViewControllerPerfTest::MainControllerShowTabSwitcher().
@@ -1804,8 +1771,7 @@
     [currentTab setSnapshotCoalescingEnabled:NO];
   }));
 
-  if (experimental_flags::IsTabSwitcherEnabled())
-    [currentBVC prepareToEnterTabSwitcher:nil];
+  [currentBVC prepareToEnterTabSwitcher:nil];
 
   if (!_tabSwitcherController.get()) {
     if (IsIPadIdiom()) {
@@ -1831,7 +1797,7 @@
   }
   _tabSwitcherIsActive = YES;
   [_tabSwitcherController setDelegate:self];
-  if (IsIPadIdiom() && experimental_flags::IsTabSwitcherEnabled()) {
+  if (IsIPadIdiom()) {
     TabSwitcherTransitionContext* transitionContext =
         [TabSwitcherTransitionContext
             tabSwitcherTransitionContextWithCurrent:currentBVC
@@ -1914,7 +1880,6 @@
 }
 
 - (void)beginDismissingStackViewWithCurrentModel:(TabModel*)tabModel {
-  DCHECK(experimental_flags::IsTabSwitcherEnabled() || !IsIPadIdiom());
   DCHECK(tabModel == self.mainTabModel || tabModel == self.otrTabModel);
 
   _dismissingStackView = YES;
@@ -1927,7 +1892,6 @@
 }
 
 - (void)finishDismissingStackView {
-  DCHECK(!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
   DCHECK_EQ(self.mainViewController.activeViewController,
             _tabSwitcherController.get());
 
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 5a1edc00..1011ccab 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -948,6 +948,9 @@
       <message name="IDS_IOS_PAYMENT_REQUEST_PAYMENT_ITEMS_TITLE" desc="Title of the view that displays the payment items in a payment request (for example subtotal, tax, shipping cost) to the user [iOS only].">
         Order Summary
       </message>
+      <message name="IDS_IOS_PAYMENT_REQUEST_PAYMENT_ITEMS_TOTAL_FORMAT" desc="The format specifier of the Total label in the payment items in a payment request [iOS only].">
+        <ph name="FORMATTED_CURRENCY_CODE">$1<ex>USD</ex></ph> <ph name="FORMATTED_TOTAL_AMOUNT">$2<ex>$ 12.34</ex></ph>
+      </message>
       <message name="IDS_IOS_PAYMENT_REQUEST_SHIPPING_ADDRESS_HEADER" desc="Label of the header of the section which displays the currently selected shipping address and the available shipping options for satisfying a payment request [iOS only].">
         Shipping
       </message>
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 016e262d..872fde97 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -48,6 +48,7 @@
   "+components/password_manager/core/browser",
   "+components/password_manager/core/common",
   "+components/password_manager/sync/browser",
+  "+components/payments",
   "+components/physical_web/data_source",
   "+components/physical_web/webui",
   "+components/pref_registry",
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index 3092b48..74c51763 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -103,15 +103,6 @@
   if ([defaults boolForKey:@"TabStripAutoScrollNewTabsDisabled"])
     command_line->AppendSwitch(switches::kDisableTabStripAutoScrollNewTabs);
 
-  // Populate command line flag for the Tab Switcher experiment from the
-  // configuration plist.
-  NSString* enableTabSwitcher = [defaults stringForKey:@"EnableTabSwitcher"];
-  if ([enableTabSwitcher isEqualToString:@"Enabled"]) {
-    command_line->AppendSwitch(switches::kEnableTabSwitcher);
-  } else if ([enableTabSwitcher isEqualToString:@"Disabled"]) {
-    command_line->AppendSwitch(switches::kDisableTabSwitcher);
-  }
-
   // Populate command line flag for the SnapshotLRUCache experiment from the
   // configuration plist.
   NSString* enableLRUSnapshotCache =
diff --git a/ios/chrome/browser/chrome_switches.cc b/ios/chrome/browser/chrome_switches.cc
index 9b0f375..13698f9c2 100644
--- a/ios/chrome/browser/chrome_switches.cc
+++ b/ios/chrome/browser/chrome_switches.cc
@@ -47,9 +47,6 @@
 const char kDisableTabStripAutoScrollNewTabs[] =
     "disable-tab-strip-autoscroll-new-tabs";
 
-// Disables the tab switcher.
-const char kDisableTabSwitcher[] = "disable-tab-switcher";
-
 // Disables Physical Web scanning for nearby URLs.
 const char kDisableIOSPhysicalWeb[] = "disable-ios-physical-web";
 
@@ -93,9 +90,6 @@
 // Enables the Spotlight actions.
 const char kEnableSpotlightActions[] = "enable-spotlight-actions";
 
-// Enables the tab switcher.
-const char kEnableTabSwitcher[] = "enable-tab-switcher";
-
 // Enables Physical Web scanning for nearby URLs.
 const char kEnableIOSPhysicalWeb[] = "enable-ios-physical-web";
 
diff --git a/ios/chrome/browser/chrome_switches.h b/ios/chrome/browser/chrome_switches.h
index 7734db9a..057a4194 100644
--- a/ios/chrome/browser/chrome_switches.h
+++ b/ios/chrome/browser/chrome_switches.h
@@ -20,7 +20,6 @@
 extern const char kDisablePaymentRequest[];
 extern const char kDisableSpotlightActions[];
 extern const char kDisableTabStripAutoScrollNewTabs[];
-extern const char kDisableTabSwitcher[];
 extern const char kDisableIOSPhysicalWeb[];
 extern const char kDisableDownloadImageRenaming[];
 extern const char kDisableSuggestionsUI[];
@@ -36,7 +35,6 @@
 extern const char kEnablePaymentRequest[];
 extern const char kEnableReaderModeToolbarIcon[];
 extern const char kEnableSpotlightActions[];
-extern const char kEnableTabSwitcher[];
 extern const char kEnableIOSPhysicalWeb[];
 extern const char kEnableDownloadImageRenaming[];
 extern const char kEnableSuggestionsUI[];
diff --git a/ios/chrome/browser/crash_report/crash_keys.cc b/ios/chrome/browser/crash_report/crash_keys.cc
index 4d2e9ef..11d62d89 100644
--- a/ios/chrome/browser/crash_report/crash_keys.cc
+++ b/ios/chrome/browser/crash_report/crash_keys.cc
@@ -18,7 +18,7 @@
       {crash_keys::kChannel, crash_keys::kSmallSize},
       {crash_keys::kMetricsClientId, crash_keys::kSmallSize},
       {crash_keys::kNumVariations, crash_keys::kSmallSize},
-      {crash_keys::kVariations, crash_keys::kLargeSize},
+      {crash_keys::kVariations, crash_keys::kHugeSize},
       {crash_keys::mac::kZombie, crash_keys::kMediumSize},
       {crash_keys::mac::kZombieTrace, crash_keys::kMediumSize},
   };
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h
index dc22d51..a5b1b1c2 100644
--- a/ios/chrome/browser/experimental_flags.h
+++ b/ios/chrome/browser/experimental_flags.h
@@ -100,9 +100,6 @@
 // Whether or not the tab strip scrolls new tabs to be visible.
 bool IsTabStripAutoScrollNewTabsEnabled();
 
-// Whether the Tab Switcher is enabled for iPad or not.
-bool IsTabSwitcherEnabled();
-
 // Whether viewing and copying passwords is enabled.
 bool IsViewCopyPasswordsEnabled();
 
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm
index 4361aaf3..92ce248 100644
--- a/ios/chrome/browser/experimental_flags.mm
+++ b/ios/chrome/browser/experimental_flags.mm
@@ -249,19 +249,6 @@
   return !command_line->HasSwitch(switches::kDisableTabStripAutoScrollNewTabs);
 }
 
-bool IsTabSwitcherEnabled() {
-  // Check if the experimental flag is forced off.
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kDisableTabSwitcher)) {
-    return false;
-  }
-
-  // Check if the finch experiment is turned off.
-  std::string group_name = base::FieldTrialList::FindFullName("IOSTabSwitcher");
-  return !base::StartsWith(group_name, "Disabled",
-                           base::CompareCase::INSENSITIVE_ASCII);
-}
-
 bool IsViewCopyPasswordsEnabled() {
   NSString* viewCopyPasswordFlag = [[NSUserDefaults standardUserDefaults]
       objectForKey:kEnableViewCopyPasswords];
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
index d6d01e0..58a7b36 100644
--- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
+++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -163,29 +163,21 @@
   GREYAssertTrue(chrome_test_util::IsIncognitoMode(),
                  @"Switching to normal mode is only allowed from Incognito.");
   if (IsIPadIdiom()) {
-    if (experimental_flags::IsTabSwitcherEnabled()) {
-      // Enter the tab switcher.
-      id<GREYMatcher> tabSwitcherEnterButton =
-          grey_accessibilityLabel(l10n_util::GetNSStringWithFixup(
-              IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER));
-      [[EarlGrey selectElementWithMatcher:tabSwitcherEnterButton]
-          performAction:grey_tap()];
+    // Enter the tab switcher.
+    id<GREYMatcher> tabSwitcherEnterButton = grey_accessibilityLabel(
+        l10n_util::GetNSStringWithFixup(IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER));
+    [[EarlGrey selectElementWithMatcher:tabSwitcherEnterButton]
+        performAction:grey_tap()];
 
-      // Select the non incognito panel.
-      id<GREYMatcher> tabSwitcherHeaderPanelButton =
-          grey_accessibilityLabel(l10n_util::GetNSStringWithFixup(
-              IDS_IOS_TAB_SWITCHER_HEADER_NON_INCOGNITO_TABS));
-      [[EarlGrey selectElementWithMatcher:tabSwitcherHeaderPanelButton]
-          performAction:grey_tap()];
+    // Select the non incognito panel.
+    id<GREYMatcher> tabSwitcherHeaderPanelButton =
+        grey_accessibilityLabel(l10n_util::GetNSStringWithFixup(
+            IDS_IOS_TAB_SWITCHER_HEADER_NON_INCOGNITO_TABS));
+    [[EarlGrey selectElementWithMatcher:tabSwitcherHeaderPanelButton]
+        performAction:grey_tap()];
 
-      // Leave the tab switcher.
-      CloseTabSwitcher();
-    } else {
-      [[EarlGrey selectElementWithMatcher:
-                     chrome_test_util::ButtonWithAccessibilityLabelId(
-                         IDS_IOS_SWITCH_BROWSER_MODE_LEAVE_INCOGNITO)]
-          performAction:grey_tap()];
-    }
+    // Leave the tab switcher.
+    CloseTabSwitcher();
   } else {
     [[EarlGrey selectElementWithMatcher:
                    chrome_test_util::ButtonWithAccessibilityLabelId(
diff --git a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
index 5df921a..2c6a3d1a 100644
--- a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
+++ b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
@@ -154,16 +154,15 @@
             ->GetSequencedTaskRunnerWithShutdownBehavior(
                 base::SequencedWorkerPool::GetSequenceToken(),
                 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
+    auto suggestions_fetcher = base::MakeUnique<RemoteSuggestionsFetcher>(
+        signin_manager, token_service, request_context, prefs, nullptr,
+        base::Bind(&ParseJson), GetChannel() == version_info::Channel::STABLE
+                                    ? google_apis::GetAPIKey()
+                                    : google_apis::GetNonStableAPIKey(),
+        service->user_classifier());
     auto provider = base::MakeUnique<RemoteSuggestionsProviderImpl>(
         service.get(), prefs, GetApplicationContext()->GetApplicationLocale(),
-        service->category_ranker(),
-        base::MakeUnique<RemoteSuggestionsFetcher>(
-            signin_manager, token_service, request_context, prefs, nullptr,
-            base::Bind(&ParseJson),
-            GetChannel() == version_info::Channel::STABLE
-                ? google_apis::GetAPIKey()
-                : google_apis::GetNonStableAPIKey(),
-            service->user_classifier()),
+        service->category_ranker(), std::move(suggestions_fetcher),
         base::MakeUnique<ImageFetcherImpl>(request_context.get(),
                                            web::WebThread::GetBlockingPool()),
         CreateIOSImageDecoder(task_runner),
diff --git a/ios/chrome/browser/payments/BUILD.gn b/ios/chrome/browser/payments/BUILD.gn
index 22fa141..4989170 100644
--- a/ios/chrome/browser/payments/BUILD.gn
+++ b/ios/chrome/browser/payments/BUILD.gn
@@ -45,6 +45,7 @@
     ":injected_js",
     "//base",
     "//components/autofill/core/browser",
+    "//components/payments:payment_validation",
     "//components/strings",
     "//ios/chrome/app/strings",
     "//ios/chrome/app/theme",
@@ -72,6 +73,7 @@
     "payment_items_display_coordinator_unittest.mm",
     "payment_items_display_view_controller_unittest.mm",
     "payment_method_selection_view_controller_unittest.mm",
+    "payment_request_unittest.mm",
     "shipping_address_selection_coordinator_unittest.mm",
     "shipping_address_selection_view_controller_unittest.mm",
     "shipping_option_selection_coordinator_unittest.mm",
@@ -83,7 +85,9 @@
     "//base/test:test_support",
     "//components/autofill/core/browser",
     "//components/autofill/core/browser:test_support",
+    "//components/payments:payment_validation",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser",
     "//ios/chrome/browser/payments/cells",
     "//ios/chrome/browser/ui/autofill/cells",
     "//ios/chrome/browser/ui/collection_view:test_support",
diff --git a/ios/chrome/browser/payments/payment_items_display_coordinator.h b/ios/chrome/browser/payments/payment_items_display_coordinator.h
index e573ae1..2a8a3af1e 100644
--- a/ios/chrome/browser/payments/payment_items_display_coordinator.h
+++ b/ios/chrome/browser/payments/payment_items_display_coordinator.h
@@ -34,8 +34,8 @@
 @interface PaymentItemsDisplayCoordinator : ChromeCoordinator
 
 // The PaymentRequest object owning an instance of web::PaymentRequest as
-// provided by the page invoking the Payment Request API. This is a weak
-// reference and should outlive this class.
+// provided by the page invoking the Payment Request API. This pointer is not
+// owned by this class and should outlive it.
 @property(nonatomic, assign) PaymentRequest* paymentRequest;
 
 // The delegate to be notified when the user selects touches the return button
diff --git a/ios/chrome/browser/payments/payment_items_display_view_controller.mm b/ios/chrome/browser/payments/payment_items_display_view_controller.mm
index df0aa83..f0db4060 100644
--- a/ios/chrome/browser/payments/payment_items_display_view_controller.mm
+++ b/ios/chrome/browser/payments/payment_items_display_view_controller.mm
@@ -8,7 +8,9 @@
 #include "base/mac/foundation_util.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/credit_card.h"
+#include "components/payments/currency_formatter.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/payments/cells/price_item.h"
 #import "ios/chrome/browser/payments/payment_request_utils.h"
@@ -153,15 +155,13 @@
   totalItem.accessibilityIdentifier = kPaymentItemsDisplayItemId;
   totalItem.item =
       base::SysUTF16ToNSString(_paymentRequest->payment_details().total.label);
-
-  NSString* currencyCode = base::SysUTF16ToNSString(
-      _paymentRequest->payment_details().total.amount.currency);
-  NSDecimalNumber* value = [NSDecimalNumber
-      decimalNumberWithString:SysUTF16ToNSString(
-                                  _paymentRequest->payment_details()
-                                      .total.amount.value)];
-  totalItem.price =
-      payment_request_utils::FormattedCurrencyString(value, currencyCode);
+  payments::CurrencyFormatter* currencyFormatter =
+      _paymentRequest->GetOrCreateCurrencyFormatter();
+  totalItem.price = SysUTF16ToNSString(l10n_util::GetStringFUTF16(
+      IDS_IOS_PAYMENT_REQUEST_PAYMENT_ITEMS_TOTAL_FORMAT,
+      base::UTF8ToUTF16(currencyFormatter->formatted_currency_code()),
+      currencyFormatter->Format(base::UTF16ToASCII(
+          _paymentRequest->payment_details().total.amount.value))));
 
   [model addItem:totalItem toSectionWithIdentifier:SectionIdentifierPayment];
 
@@ -172,13 +172,10 @@
         [[[PriceItem alloc] initWithType:ItemTypePaymentItem] autorelease];
     paymentItemItem.accessibilityIdentifier = kPaymentItemsDisplayItemId;
     paymentItemItem.item = base::SysUTF16ToNSString(paymentItem.label);
-
-    NSString* currencyCode =
-        base::SysUTF16ToNSString(paymentItem.amount.currency);
-    NSDecimalNumber* value = [NSDecimalNumber
-        decimalNumberWithString:SysUTF16ToNSString(paymentItem.amount.value)];
-    paymentItemItem.price =
-        payment_request_utils::FormattedCurrencyString(value, currencyCode);
+    payments::CurrencyFormatter* currencyFormatter =
+        _paymentRequest->GetOrCreateCurrencyFormatter();
+    paymentItemItem.price = SysUTF16ToNSString(currencyFormatter->Format(
+        base::UTF16ToASCII(paymentItem.amount.value)));
     [model addItem:paymentItemItem
         toSectionWithIdentifier:SectionIdentifierPayment];
   }
diff --git a/ios/chrome/browser/payments/payment_method_selection_coordinator.h b/ios/chrome/browser/payments/payment_method_selection_coordinator.h
index acd89313..885205e 100644
--- a/ios/chrome/browser/payments/payment_method_selection_coordinator.h
+++ b/ios/chrome/browser/payments/payment_method_selection_coordinator.h
@@ -40,8 +40,8 @@
     : ChromeCoordinator<PaymentMethodSelectionViewControllerDelegate>
 
 // The PaymentRequest object owning an instance of web::PaymentRequest as
-// provided by the page invoking the Payment Request API. This is a weak
-// reference and should outlive this class.
+// provided by the page invoking the Payment Request API. This pointer is not
+// owned by this class and should outlive it.
 @property(nonatomic, assign) PaymentRequest* paymentRequest;
 
 // The delegate to be notified when the user selects a payment method or returns
diff --git a/ios/chrome/browser/payments/payment_request.h b/ios/chrome/browser/payments/payment_request.h
index 8278ee2..966fb2a 100644
--- a/ios/chrome/browser/payments/payment_request.h
+++ b/ios/chrome/browser/payments/payment_request.h
@@ -17,6 +17,10 @@
 class PersonalDataManager;
 }  // namespace autofill
 
+namespace payments {
+class CurrencyFormatter;
+}  // namespace payments
+
 // Owns an instance of web::PaymentRequest as provided by the page invoking the
 // PaymentRequest API. Also caches credit cards and addresses provided by the
 // |personal_data_manager| and manages shared resources and user selections for
@@ -40,6 +44,11 @@
   // well as the reference to the selected shipping option.
   void set_payment_details(const web::PaymentDetails& details);
 
+  // Returns the payments::CurrencyFormatter instance for this PaymentRequest.
+  // Note: Having multiple currencies per PaymentRequest flow is not supported;
+  // hence the CurrencyFormatter is cached here.
+  payments::CurrencyFormatter* GetOrCreateCurrencyFormatter();
+
   // Returns the available autofill profiles for this user to be used as
   // shipping profiles.
   const std::vector<autofill::AutofillProfile*>& shipping_profiles() const {
@@ -112,6 +121,9 @@
   // Never null and outlives this object.
   autofill::PersonalDataManager* personal_data_manager_;
 
+  // The currency formatter instance for this PaymentRequest flow.
+  std::unique_ptr<payments::CurrencyFormatter> currency_formatter_;
+
   // Profiles returned by the Data Manager may change due to (e.g.) sync events,
   // meaning PaymentRequest may outlive them. Therefore, profiles are fetched
   // once and owned here. Whenever profiles are requested a vector of pointers
diff --git a/ios/chrome/browser/payments/payment_request.mm b/ios/chrome/browser/payments/payment_request.mm
index 48351ce..9e099fa8 100644
--- a/ios/chrome/browser/payments/payment_request.mm
+++ b/ios/chrome/browser/payments/payment_request.mm
@@ -11,6 +11,8 @@
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/payments/currency_formatter.h"
+#include "ios/chrome/browser/application_context.h"
 #include "ios/web/public/payments/payment_request.h"
 
 PaymentRequest::PaymentRequest(
@@ -29,10 +31,23 @@
 PaymentRequest::~PaymentRequest() {}
 
 void PaymentRequest::set_payment_details(const web::PaymentDetails& details) {
+  DCHECK(web_payment_request_);
   web_payment_request_->details = details;
   PopulateShippingOptionCache();
 }
 
+payments::CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter() {
+  DCHECK(web_payment_request_);
+  if (!currency_formatter_) {
+    currency_formatter_.reset(new payments::CurrencyFormatter(
+        base::UTF16ToASCII(web_payment_request_->details.total.amount.currency),
+        base::UTF16ToASCII(
+            web_payment_request_->details.total.amount.currency_system),
+        GetApplicationContext()->GetApplicationLocale()));
+  }
+  return currency_formatter_.get();
+}
+
 void PaymentRequest::PopulateProfileCache() {
   for (const auto& profile : personal_data_manager_->GetProfilesToSuggest()) {
     profile_cache_.push_back(
@@ -45,6 +60,7 @@
 }
 
 void PaymentRequest::PopulateCreditCardCache() {
+  DCHECK(web_payment_request_);
   std::unordered_set<base::string16> supported_method_types;
   for (const auto& method_data : web_payment_request_->method_data) {
     for (const auto& supported_method : method_data.supported_methods)
@@ -71,6 +87,7 @@
 }
 
 void PaymentRequest::PopulateShippingOptionCache() {
+  DCHECK(web_payment_request_);
   shipping_options_.clear();
   shipping_options_.reserve(
       web_payment_request_->details.shipping_options.size());
diff --git a/ios/chrome/browser/payments/payment_request_coordinator.h b/ios/chrome/browser/payments/payment_request_coordinator.h
index 4c7830d..10d11e29 100644
--- a/ios/chrome/browser/payments/payment_request_coordinator.h
+++ b/ios/chrome/browser/payments/payment_request_coordinator.h
@@ -54,8 +54,8 @@
     NS_DESIGNATED_INITIALIZER;
 
 // The PaymentRequest object owning an instance of web::PaymentRequest as
-// provided by the page invoking the Payment Request API. This is a weak
-// reference and should outlive this class.
+// provided by the page invoking the Payment Request API. This pointer is not
+// owned by this class and should outlive it.
 @property(nonatomic, assign) PaymentRequest* paymentRequest;
 
 // The favicon of the page invoking the PaymentRequest API. Should be set before
diff --git a/ios/chrome/browser/payments/payment_request_unittest.mm b/ios/chrome/browser/payments/payment_request_unittest.mm
new file mode 100644
index 0000000..a800898
--- /dev/null
+++ b/ios/chrome/browser/payments/payment_request_unittest.mm
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/payments/payment_request.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/payments/currency_formatter.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/web/public/payments/payment_request.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Tests that the payments::CurrencyFormatter is constructed with the correct
+// currency code and currency system.
+TEST(PaymentRequestTest, CreatesCurrencyFormatterCorrectly) {
+  ASSERT_EQ("en", GetApplicationContext()->GetApplicationLocale());
+
+  autofill::TestPersonalDataManager personal_data_manager;
+
+  std::unique_ptr<web::PaymentRequest> web_payment_request =
+      base::MakeUnique<web::PaymentRequest>();
+  web_payment_request->details.total.amount.currency =
+      base::ASCIIToUTF16("USD");
+  PaymentRequest payment_request1(std::move(web_payment_request),
+                                  &personal_data_manager);
+  payments::CurrencyFormatter* currency_formatter =
+      payment_request1.GetOrCreateCurrencyFormatter();
+  ASSERT_EQ(base::UTF8ToUTF16("$55.00"), currency_formatter->Format("55.00"));
+  ASSERT_EQ("USD", currency_formatter->formatted_currency_code());
+
+  web_payment_request = base::MakeUnique<web::PaymentRequest>();
+  web_payment_request->details.total.amount.currency =
+      base::ASCIIToUTF16("JPY");
+  PaymentRequest payment_request2(std::move(web_payment_request),
+                                  &personal_data_manager);
+  currency_formatter = payment_request2.GetOrCreateCurrencyFormatter();
+  ASSERT_EQ(base::UTF8ToUTF16("¥55"), currency_formatter->Format("55.00"));
+  ASSERT_EQ("JPY", currency_formatter->formatted_currency_code());
+
+  web_payment_request = base::MakeUnique<web::PaymentRequest>();
+  web_payment_request->details.total.amount.currency_system =
+      base::ASCIIToUTF16("NOT_ISO4217");
+  web_payment_request->details.total.amount.currency =
+      base::ASCIIToUTF16("USD");
+  PaymentRequest payment_request3(std::move(web_payment_request),
+                                  &personal_data_manager);
+  currency_formatter = payment_request3.GetOrCreateCurrencyFormatter();
+  ASSERT_EQ(base::UTF8ToUTF16("55.00"), currency_formatter->Format("55.00"));
+  ASSERT_EQ("USD", currency_formatter->formatted_currency_code());
+}
diff --git a/ios/chrome/browser/payments/payment_request_utils.h b/ios/chrome/browser/payments/payment_request_utils.h
index e8b9841..10f9069 100644
--- a/ios/chrome/browser/payments/payment_request_utils.h
+++ b/ios/chrome/browser/payments/payment_request_utils.h
@@ -21,11 +21,6 @@
 // Helper function to get the address label from an autofill profile.
 NSString* AddressLabelFromAutofillProfile(autofill::AutofillProfile* profile);
 
-// Helper function that returns a formatted currency string given the value and
-// the currency code.
-NSString* FormattedCurrencyString(NSDecimalNumber* value,
-                                  NSString* currencyCode);
-
 // Helper function to get the phone number label from an autofill profile.
 NSString* PhoneNumberLabelFromAutofillProfile(
     autofill::AutofillProfile* profile);
diff --git a/ios/chrome/browser/payments/payment_request_utils.mm b/ios/chrome/browser/payments/payment_request_utils.mm
index 873fc3d2..f6b2ae08 100644
--- a/ios/chrome/browser/payments/payment_request_utils.mm
+++ b/ios/chrome/browser/payments/payment_request_utils.mm
@@ -34,15 +34,6 @@
       GetApplicationContext()->GetApplicationLocale()));
 }
 
-NSString* FormattedCurrencyString(NSDecimalNumber* value,
-                                  NSString* currencyCode) {
-  NSNumberFormatter* currencyFormatter =
-      [[[NSNumberFormatter alloc] init] autorelease];
-  [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
-  [currencyFormatter setCurrencyCode:currencyCode];
-  return [currencyFormatter stringFromNumber:value];
-}
-
 NSString* PhoneNumberLabelFromAutofillProfile(
     autofill::AutofillProfile* profile) {
   return base::SysUTF16ToNSString(profile->GetInfo(
diff --git a/ios/chrome/browser/payments/payment_request_view_controller.mm b/ios/chrome/browser/payments/payment_request_view_controller.mm
index 0d87f678..3e02a17 100644
--- a/ios/chrome/browser/payments/payment_request_view_controller.mm
+++ b/ios/chrome/browser/payments/payment_request_view_controller.mm
@@ -9,22 +9,23 @@
 #include "base/mac/objc_property_releaser.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/payments/currency_formatter.h"
 #include "components/strings/grit/components_strings.h"
-#include "ios/chrome/browser/application_context.h"
 #import "ios/chrome/browser/payments/cells/page_info_item.h"
 #import "ios/chrome/browser/payments/cells/payment_method_item.h"
 #import "ios/chrome/browser/payments/cells/price_item.h"
 #import "ios/chrome/browser/payments/cells/shipping_address_item.h"
 #import "ios/chrome/browser/payments/payment_request_utils.h"
+#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_detail_item.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
-#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
@@ -361,14 +362,12 @@
 - (void)fillPaymentSummaryItem:(PriceItem*)item
                withPaymentItem:(web::PaymentItem)paymentItem {
   item.item = l10n_util::GetNSString(IDS_IOS_PAYMENT_REQUEST_TOTAL_HEADER);
-  NSString* currencyCode = base::SysUTF16ToNSString(
-      _paymentRequest->payment_details().total.amount.currency);
-  NSDecimalNumber* value = [NSDecimalNumber
-      decimalNumberWithString:SysUTF16ToNSString(
-                                  _paymentRequest->payment_details()
-                                      .total.amount.value)];
-  item.price =
-      payment_request_utils::FormattedCurrencyString(value, currencyCode);
+  payments::CurrencyFormatter* currencyFormatter =
+      _paymentRequest->GetOrCreateCurrencyFormatter();
+  item.price = SysUTF16ToNSString(l10n_util::GetStringFUTF16(
+      IDS_IOS_PAYMENT_REQUEST_PAYMENT_ITEMS_TOTAL_FORMAT,
+      base::UTF8ToUTF16(currencyFormatter->formatted_currency_code()),
+      currencyFormatter->Format(base::UTF16ToASCII(paymentItem.amount.value))));
 }
 
 - (void)fillShippingAddressItem:(ShippingAddressItem*)item
@@ -381,11 +380,10 @@
 - (void)fillShippingOptionItem:(CollectionViewTextItem*)item
                     withOption:(web::PaymentShippingOption*)option {
   item.text = base::SysUTF16ToNSString(option->label);
-  NSString* currencyCode = base::SysUTF16ToNSString(option->amount.currency);
-  NSDecimalNumber* value = [NSDecimalNumber
-      decimalNumberWithString:SysUTF16ToNSString(option->amount.value)];
-  item.detailText =
-      payment_request_utils::FormattedCurrencyString(value, currencyCode);
+  payments::CurrencyFormatter* currencyFormatter =
+      _paymentRequest->GetOrCreateCurrencyFormatter();
+  item.detailText = SysUTF16ToNSString(
+      currencyFormatter->Format(base::UTF16ToASCII(option->amount.value)));
 }
 
 #pragma mark UICollectionViewDataSource
diff --git a/ios/chrome/browser/payments/resources/payment_request_manager.js b/ios/chrome/browser/payments/resources/payment_request_manager.js
index 2dca58c..ab68593 100644
--- a/ios/chrome/browser/payments/resources/payment_request_manager.js
+++ b/ios/chrome/browser/payments/resources/payment_request_manager.js
@@ -487,7 +487,8 @@
 /**
  * @typedef {{
  *   currency: string,
- *   value: string
+ *   value: string,
+ *   currencySystem: (string|undefined)
  * }}
  */
 window.PaymentCurrencyAmount;
diff --git a/ios/chrome/browser/payments/shipping_address_selection_coordinator.h b/ios/chrome/browser/payments/shipping_address_selection_coordinator.h
index c91ebee..09c0a63 100644
--- a/ios/chrome/browser/payments/shipping_address_selection_coordinator.h
+++ b/ios/chrome/browser/payments/shipping_address_selection_coordinator.h
@@ -39,8 +39,8 @@
 @interface ShippingAddressSelectionCoordinator : ChromeCoordinator
 
 // The PaymentRequest object owning an instance of web::PaymentRequest as
-// provided by the page invoking the Payment Request API. This is a weak
-// reference and should outlive this class.
+// provided by the page invoking the Payment Request API. This pointer is not
+// owned by this class and should outlive it.
 @property(nonatomic, assign) PaymentRequest* paymentRequest;
 
 // The delegate to be notified when the user selects a shipping address or
diff --git a/ios/chrome/browser/payments/shipping_option_selection_coordinator.h b/ios/chrome/browser/payments/shipping_option_selection_coordinator.h
index 73cd293b..81030f22 100644
--- a/ios/chrome/browser/payments/shipping_option_selection_coordinator.h
+++ b/ios/chrome/browser/payments/shipping_option_selection_coordinator.h
@@ -36,8 +36,8 @@
 @interface ShippingOptionSelectionCoordinator : ChromeCoordinator
 
 // The PaymentRequest object owning an instance of web::PaymentRequest as
-// provided by the page invoking the Payment Request API. This is a weak
-// reference and should outlive this class.
+// provided by the page invoking the Payment Request API. This pointer is not
+// owned by this class and should outlive it.
 @property(nonatomic, assign) PaymentRequest* paymentRequest;
 
 // The delegate to be notified when the user selects a shipping option or
diff --git a/ios/chrome/browser/payments/shipping_option_selection_view_controller.mm b/ios/chrome/browser/payments/shipping_option_selection_view_controller.mm
index 588e1e1..a1f756a33 100644
--- a/ios/chrome/browser/payments/shipping_option_selection_view_controller.mm
+++ b/ios/chrome/browser/payments/shipping_option_selection_view_controller.mm
@@ -7,6 +7,8 @@
 #import "base/ios/weak_nsobject.h"
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/payments/currency_formatter.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/payments/cells/payments_text_item.h"
 #include "ios/chrome/browser/payments/payment_request.h"
@@ -129,13 +131,10 @@
     CollectionViewTextItem* item = [[[CollectionViewTextItem alloc]
         initWithType:ItemTypeShippingOption] autorelease];
     item.text = base::SysUTF16ToNSString(shippingOption->label);
-    NSString* currencyCode =
-        base::SysUTF16ToNSString(shippingOption->amount.currency);
-    NSDecimalNumber* value = [NSDecimalNumber
-        decimalNumberWithString:SysUTF16ToNSString(
-                                    shippingOption->amount.value)];
-    item.detailText =
-        payment_request_utils::FormattedCurrencyString(value, currencyCode);
+    payments::CurrencyFormatter* currencyFormatter =
+        _paymentRequest->GetOrCreateCurrencyFormatter();
+    item.detailText = SysUTF16ToNSString(currencyFormatter->Format(
+        base::UTF16ToASCII(shippingOption->amount.value)));
 
     // Styling.
     item.textFont = [MDCTypography body2Font];
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
index a06e05b..5cc98e9 100644
--- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -56,34 +56,6 @@
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 			<key>Title</key>
-			<string>iPad Tab Switcher</string>
-		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSMultiValueSpecifier</string>
-			<key>Title</key>
-			<string>Enable Tab Switcher</string>
-			<key>Key</key>
-			<string>EnableTabSwitcher</string>
-			<key>DefaultValue</key>
-			<string></string>
-			<key>Values</key>
-			<array>
-				<string></string>
-				<string>Enabled</string>
-				<string>Disabled</string>
-			</array>
-			<key>Titles</key>
-			<array>
-				<string>Default</string>
-				<string>Enabled</string>
-				<string>Disabled</string>
-			</array>
-		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSGroupSpecifier</string>
-			<key>Title</key>
 			<string>Reader mode</string>
 		</dict>
 		<dict>
diff --git a/ios/chrome/browser/snapshots/snapshot_cache.mm b/ios/chrome/browser/snapshots/snapshot_cache.mm
index d648eba7..7fb720d 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache.mm
@@ -232,9 +232,6 @@
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
   DCHECK(sessionID);
 
-  if (![self inMemoryCacheIsEnabled] && !callback)
-    return;
-
   UIImage* img = nil;
   if (lruCache_)
     img = [lruCache_ objectForKey:sessionID];
@@ -256,7 +253,7 @@
             [SnapshotCache imagePathForSessionID:sessionID]) retain]);
       }),
       base::BindBlock(^(base::scoped_nsobject<UIImage> image) {
-        if ([self inMemoryCacheIsEnabled] && image) {
+        if (image) {
           if (lruCache_)
             [lruCache_ setObject:image forKey:sessionID];
           else
@@ -272,12 +269,11 @@
   if (!img || !sessionID)
     return;
 
-  if ([self inMemoryCacheIsEnabled]) {
-    if (lruCache_)
-      [lruCache_ setObject:img forKey:sessionID];
-    else
-      [imageDictionary_ setObject:img forKey:sessionID];
-  }
+  if (lruCache_)
+    [lruCache_ setObject:img forKey:sessionID];
+  else
+    [imageDictionary_ setObject:img forKey:sessionID];
+
   // Save the image to disk.
   web::WebThread::PostBlockingPoolSequencedTask(
       kSequenceToken, FROM_HERE,
@@ -403,15 +399,9 @@
   }
 }
 
-- (BOOL)inMemoryCacheIsEnabled {
-  // In-memory cache on iPad is enabled only when the tab switcher is enabled.
-  return !IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled();
-}
-
 - (BOOL)usesLRUCache {
-  // Always use the LRUCache when the tab switcher is enabled.
-  return experimental_flags::IsTabSwitcherEnabled() ||
-         experimental_flags::IsLRUSnapshotCacheEnabled();
+  // TODO(crbug.com/687904): Remove the non-LRU cache code.
+  return true;
 }
 
 - (void)handleLowMemory {
diff --git a/ios/chrome/browser/snapshots/snapshot_cache_internal.h b/ios/chrome/browser/snapshots/snapshot_cache_internal.h
index 794d8680..dcc2e8f 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache_internal.h
+++ b/ios/chrome/browser/snapshots/snapshot_cache_internal.h
@@ -20,9 +20,6 @@
 + (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
 // Returns whether the snapshots are cached in a LRU cache.
 - (BOOL)usesLRUCache;
-// Returns whether the in-memory cache (as opposed to the on-disk cache) is
-// enabled.
-- (BOOL)inMemoryCacheIsEnabled;
 @end
 
 #endif  // IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_CACHE_INTERNAL_H_
diff --git a/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm b/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm
index 1e33eb0..4912f1b5 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm
@@ -218,9 +218,6 @@
 TEST_F(SnapshotCacheTest, Cache) {
   SnapshotCache* cache = GetSnapshotCache();
 
-  if (![cache inMemoryCacheIsEnabled])
-    return;
-
   NSUInteger expectedCacheSize = kSessionCount;
   if ([cache usesLRUCache])
     expectedCacheSize = MIN(kSessionCount, [cache lruCacheMaxSize]);
@@ -361,13 +358,8 @@
 
   TriggerMemoryWarning();
 
-  if ([cache inMemoryCacheIsEnabled]) {
-    EXPECT_EQ(YES, [cache hasImageInMemory:firstPinnedID]);
-    EXPECT_EQ(YES, [cache hasImageInMemory:secondPinnedID]);
-  } else {
-    EXPECT_EQ(NO, [cache hasImageInMemory:firstPinnedID]);
-    EXPECT_EQ(NO, [cache hasImageInMemory:secondPinnedID]);
-  }
+  EXPECT_EQ(YES, [cache hasImageInMemory:firstPinnedID]);
+  EXPECT_EQ(YES, [cache hasImageInMemory:secondPinnedID]);
 
   NSString* notPinnedID = [testSessions_ objectAtIndex:2];
   EXPECT_FALSE([cache hasImageInMemory:notPinnedID]);
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h
index a68fdd7..a383a87 100644
--- a/ios/chrome/browser/tabs/tab.h
+++ b/ios/chrome/browser/tabs/tab.h
@@ -165,7 +165,13 @@
 
 // Create a new tab with given web state and tab model. All must be non-nil.
 - (instancetype)initWithWebState:(std::unique_ptr<web::WebState>)webState
+                           model:(TabModel*)parentModel;
+
+// Create a new tab with given web state and tab model, optionally attaching
+// the tab helpers (controlled by |attachTabHelpers|). All must be non-nil.
+- (instancetype)initWithWebState:(std::unique_ptr<web::WebState>)webState
                            model:(TabModel*)parentModel
+                attachTabHelpers:(BOOL)attachTabHelpers
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
index cd84b0fc..3bc61e190 100644
--- a/ios/chrome/browser/tabs/tab.mm
+++ b/ios/chrome/browser/tabs/tab.mm
@@ -514,6 +514,14 @@
 
 - (instancetype)initWithWebState:(std::unique_ptr<web::WebState>)webState
                            model:(TabModel*)parentModel {
+  return [self initWithWebState:std::move(webState)
+                          model:parentModel
+               attachTabHelpers:YES];
+}
+
+- (instancetype)initWithWebState:(std::unique_ptr<web::WebState>)webState
+                           model:(TabModel*)parentModel
+                attachTabHelpers:(BOOL)attachTabHelpers {
   DCHECK(webState);
   self = [super init];
   if (self) {
@@ -542,88 +550,93 @@
                 delegate:self]);
 
     [self initNativeAppNavigationController];
-    // IOSChromeSessionTabHelper comes first because it sets up the tab ID, and
-    // other helpers may rely on that.
-    IOSChromeSessionTabHelper::CreateForWebState(self.webState);
 
-    NetworkActivityIndicatorTabHelper::CreateForWebState(self.webState,
-                                                         self.tabId);
-    IOSChromeSyncedTabDelegate::CreateForWebState(self.webState);
-    InfoBarManagerImpl::CreateForWebState(self.webState);
-    IOSSecurityStateTabHelper::CreateForWebState(self.webState);
-    RepostFormTabHelper::CreateForWebState(self.webState);
-    BlockedPopupTabHelper::CreateForWebState(self.webState);
+    if (attachTabHelpers) {
+      // IOSChromeSessionTabHelper comes first because it sets up the tab ID,
+      // and other helpers may rely on that.
+      IOSChromeSessionTabHelper::CreateForWebState(self.webState);
 
-    if (reading_list::switches::IsReadingListEnabled()) {
-      ReadingListModel* model =
-          ReadingListModelFactory::GetForBrowserState(browserState_);
-      ReadingListWebStateObserver::FromWebState(self.webState, model);
-    }
+      NetworkActivityIndicatorTabHelper::CreateForWebState(self.webState,
+                                                           self.tabId);
+      IOSChromeSyncedTabDelegate::CreateForWebState(self.webState);
+      InfoBarManagerImpl::CreateForWebState(self.webState);
+      IOSSecurityStateTabHelper::CreateForWebState(self.webState);
+      RepostFormTabHelper::CreateForWebState(self.webState);
+      BlockedPopupTabHelper::CreateForWebState(self.webState);
 
-    tabInfoBarObserver_.reset(new TabInfoBarObserver(self));
-    tabInfoBarObserver_->SetShouldObserveInfoBarManager(true);
+      if (reading_list::switches::IsReadingListEnabled()) {
+        ReadingListModel* model =
+            ReadingListModelFactory::GetForBrowserState(browserState_);
+        ReadingListWebStateObserver::FromWebState(self.webState, model);
+      }
 
-    if (AccountConsistencyService* account_consistency_service =
-            ios::AccountConsistencyServiceFactory::GetForBrowserState(
-                browserState_)) {
-      account_consistency_service->SetWebStateHandler(self.webState, self);
-    }
-    ChromeIOSTranslateClient::CreateForWebState(self.webState);
-    if (experimental_flags::IsAutoReloadEnabled()) {
-      autoReloadBridge_.reset([[AutoReloadBridge alloc] initWithTab:self]);
-    }
-    printObserver_.reset(new PrintObserver(self.webState));
+      tabInfoBarObserver_.reset(new TabInfoBarObserver(self));
+      tabInfoBarObserver_->SetShouldObserveInfoBarManager(true);
 
-    base::scoped_nsprotocol<id<PasswordsUiDelegate>> passwordsUiDelegate(
-        [[PasswordsUiDelegateImpl alloc] init]);
-    passwordController_.reset([[PasswordController alloc]
-           initWithWebState:self.webState
-        passwordsUiDelegate:passwordsUiDelegate]);
-    password_manager::PasswordGenerationManager* passwordGenerationManager =
-        [passwordController_ passwordGenerationManager];
-    autofillController_.reset([[AutofillController alloc]
-             initWithBrowserState:browserState_
-        passwordGenerationManager:passwordGenerationManager
-                         webState:self.webState]);
-    suggestionController_.reset([[FormSuggestionController alloc]
-        initWithWebState:self.webState
-               providers:[self suggestionProviders]]);
-    inputAccessoryViewController_.reset(
-        [[FormInputAccessoryViewController alloc]
-            initWithWebState:self.webState
-                   providers:[self accessoryViewProviders]]);
+      if (AccountConsistencyService* account_consistency_service =
+              ios::AccountConsistencyServiceFactory::GetForBrowserState(
+                  browserState_)) {
+        account_consistency_service->SetWebStateHandler(self.webState, self);
+      }
+      ChromeIOSTranslateClient::CreateForWebState(self.webState);
+      if (experimental_flags::IsAutoReloadEnabled()) {
+        autoReloadBridge_.reset([[AutoReloadBridge alloc] initWithTab:self]);
+      }
+      printObserver_.reset(new PrintObserver(self.webState));
 
-    ios::ChromeBrowserState* original_browser_state =
-        ios::ChromeBrowserState::FromBrowserState(
-            self.webState->GetBrowserState())
-            ->GetOriginalChromeBrowserState();
-    favicon::WebFaviconDriver::CreateForWebState(
-        self.webState,
-        ios::FaviconServiceFactory::GetForBrowserState(
-            original_browser_state, ServiceAccessType::IMPLICIT_ACCESS),
-        ios::HistoryServiceFactory::GetForBrowserState(
-            original_browser_state, ServiceAccessType::IMPLICIT_ACCESS),
-        ios::BookmarkModelFactory::GetForBrowserState(original_browser_state));
-    history::WebStateTopSitesObserver::CreateForWebState(
-        self.webState,
-        ios::TopSitesFactory::GetForBrowserState(original_browser_state).get());
-    [self setShouldObserveFaviconChanges:YES];
-
-    if (parentModel && parentModel.syncedWindowDelegate) {
-      IOSChromeSessionTabHelper::FromWebState(self.webState)
-          ->SetWindowID(parentModel.sessionID);
-    }
-
-    // Create the ReaderModeController immediately so it can register for
-    // WebState changes.
-    if (experimental_flags::IsReaderModeEnabled()) {
-      readerModeController_.reset([[ReaderModeController alloc]
+      base::scoped_nsprotocol<id<PasswordsUiDelegate>> passwordsUiDelegate(
+          [[PasswordsUiDelegateImpl alloc] init]);
+      passwordController_.reset([[PasswordController alloc]
+             initWithWebState:self.webState
+          passwordsUiDelegate:passwordsUiDelegate]);
+      password_manager::PasswordGenerationManager* passwordGenerationManager =
+          [passwordController_ passwordGenerationManager];
+      autofillController_.reset([[AutofillController alloc]
+               initWithBrowserState:browserState_
+          passwordGenerationManager:passwordGenerationManager
+                           webState:self.webState]);
+      suggestionController_.reset([[FormSuggestionController alloc]
           initWithWebState:self.webState
-                  delegate:self]);
-    }
+                 providers:[self suggestionProviders]]);
+      inputAccessoryViewController_.reset(
+          [[FormInputAccessoryViewController alloc]
+              initWithWebState:self.webState
+                     providers:[self accessoryViewProviders]]);
 
-    // Allow the embedder to attach tab helpers.
-    ios::GetChromeBrowserProvider()->AttachTabHelpers(self.webState, self);
+      ios::ChromeBrowserState* original_browser_state =
+          ios::ChromeBrowserState::FromBrowserState(
+              self.webState->GetBrowserState())
+              ->GetOriginalChromeBrowserState();
+      favicon::WebFaviconDriver::CreateForWebState(
+          self.webState,
+          ios::FaviconServiceFactory::GetForBrowserState(
+              original_browser_state, ServiceAccessType::IMPLICIT_ACCESS),
+          ios::HistoryServiceFactory::GetForBrowserState(
+              original_browser_state, ServiceAccessType::IMPLICIT_ACCESS),
+          ios::BookmarkModelFactory::GetForBrowserState(
+              original_browser_state));
+      history::WebStateTopSitesObserver::CreateForWebState(
+          self.webState,
+          ios::TopSitesFactory::GetForBrowserState(original_browser_state)
+              .get());
+      [self setShouldObserveFaviconChanges:YES];
+
+      if (parentModel && parentModel.syncedWindowDelegate) {
+        IOSChromeSessionTabHelper::FromWebState(self.webState)
+            ->SetWindowID(parentModel.sessionID);
+      }
+
+      // Create the ReaderModeController immediately so it can register for
+      // WebState changes.
+      if (experimental_flags::IsReaderModeEnabled()) {
+        readerModeController_.reset([[ReaderModeController alloc]
+            initWithWebState:self.webState
+                    delegate:self]);
+      }
+
+      // Allow the embedder to attach tab helpers.
+      ios::GetChromeBrowserProvider()->AttachTabHelpers(self.webState, self);
+    }
 
     [[NSNotificationCenter defaultCenter]
         addObserver:self
@@ -1789,16 +1802,7 @@
       finishPageLoadForTab:self
                loadSuccess:loadSuccess];
 
-  // Always take snapshots on iPad if the tab switcher is enabled.
-  // If the tab switcher is not enabled, don't take snapshot of chrome scheme
-  // pages.
-  BOOL takeSnapshotOnIpad =
-      IsIPadIdiom() &&
-      (experimental_flags::IsTabSwitcherEnabled() ||
-       !web::GetWebClient()->IsAppSpecificURL(lastCommittedURL));
-  // Always take snapshot on iPhone.
-  BOOL takeSnapshot = !IsIPadIdiom() || takeSnapshotOnIpad;
-  if (loadSuccess && takeSnapshot) {
+  if (loadSuccess) {
     [self updateSnapshotWithOverlay:YES visibleFrameOnly:YES];
   }
   [webControllerSnapshotHelper_ setSnapshotCoalescingEnabled:NO];
@@ -2229,27 +2233,6 @@
 
 @implementation Tab (TestingSupport)
 
-- (void)replaceWebState:(std::unique_ptr<web::WebStateImpl>)webState {
-  // Stop observing the old InfoBarManager and FaviconDriver since they will
-  // be deleted with the old web controller.
-  [self setShouldObserveInfoBarManager:NO];
-  [self setShouldObserveFaviconChanges:NO];
-  [self.webController setDelegate:nil];
-  // Set the new web state.
-  webStateImpl_ = std::move(webState);
-  [self.webController setDelegate:self];
-  webStateObserver_.reset(
-      new web::WebStateObserverBridge(webStateImpl_.get(), self));
-  // SessionTabHelper comes first because it sets up the tab ID, and other
-  // helpers may rely on that.
-  IOSChromeSessionTabHelper::CreateForWebState(webStateImpl_.get());
-  IOSChromeSyncedTabDelegate::CreateForWebState(webStateImpl_.get());
-  // Start observing the new web controller's InfoBarManager and FaviconDriver.
-  [self setShouldObserveInfoBarManager:YES];
-  [self setShouldObserveFaviconChanges:YES];
-  findInPageController_.reset();
-}
-
 - (void)replaceExternalAppLauncher:(id)externalAppLauncher {
   externalAppLauncher_.reset([externalAppLauncher retain]);
 }
diff --git a/ios/chrome/browser/tabs/tab_model.h b/ios/chrome/browser/tabs/tab_model.h
index e2e0a8fe..c577489 100644
--- a/ios/chrome/browser/tabs/tab_model.h
+++ b/ios/chrome/browser/tabs/tab_model.h
@@ -228,10 +228,8 @@
 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)index;
 
 // Replaces |oldTab| in the model with |newTab|. Closes the oldTab when
-// replacing it in the model unless |keepOldTabOpen|.
-- (void)replaceTab:(Tab*)oldTab
-           withTab:(Tab*)newTab
-    keepOldTabOpen:(BOOL)keepOldTabOpen;
+// replacing it in the model.
+- (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab;
 
 // Closes the tab at the given |index|. |index| must be valid.
 - (void)closeTabAtIndex:(NSUInteger)index;
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm
index 94ee048..6b405c2 100644
--- a/ios/chrome/browser/tabs/tab_model.mm
+++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -4,7 +4,6 @@
 
 #import "ios/chrome/browser/tabs/tab_model.h"
 
-#include <list>
 #include <utility>
 #include <vector>
 
@@ -16,6 +15,7 @@
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/task/cancelable_task_tracker.h"
 #include "components/sessions/core/serialized_navigation_entry.h"
 #include "components/sessions/core/session_id.h"
 #include "components/sessions/core/tab_restore_service.h"
@@ -66,12 +66,11 @@
 namespace {
 
 // Updates CRWSessionCertificatePolicyManager's certificate policy cache.
-void UpdateCertificatePolicyCacheFromWebState(web::WebState* web_state) {
-  DCHECK([NSThread isMainThread]);
+void UpdateCertificatePolicyCacheFromWebState(
+    const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
+    web::WebState* web_state) {
   DCHECK(web_state);
-  scoped_refptr<web::CertificatePolicyCache> policy_cache =
-      web::BrowserState::GetCertificatePolicyCache(
-          web_state->GetBrowserState());
+  DCHECK_CURRENTLY_ON(web::WebThread::UI);
   // TODO(crbug.com/454984): Remove CRWSessionController usage once certificate
   // policy manager is moved to NavigationManager.
   CRWSessionController* controller = static_cast<web::WebStateImpl*>(web_state)
@@ -81,26 +80,31 @@
       updateCertificatePolicyCache:policy_cache];
 }
 
-// Populates the certificate policy cache based on the current entries of the
-// given tabs.
-void RestoreCertificatePolicyCacheFromTabs(NSArray* tabs) {
-  DCHECK([NSThread isMainThread]);
-  for (Tab* tab in tabs) {
-    UpdateCertificatePolicyCacheFromWebState(tab.webState);
-  }
+// Populates the certificate policy cache based on the WebStates of |tab_model|.
+void RestoreCertificatePolicyCacheFromModel(
+    const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
+    TabModel* tab_model) {
+  DCHECK_CURRENTLY_ON(web::WebThread::UI);
+  for (Tab* tab in tab_model)
+    UpdateCertificatePolicyCacheFromWebState(policy_cache, tab.webState);
 }
 
-// Scrubs the certificate policy cache of all the certificate policies except
-// those for the current entries of the given tabs.
+// Scrubs the certificate policy cache of all certificates policies except
+// those for the current entries in |tab_model|.
 void CleanCertificatePolicyCache(
-    scoped_refptr<web::CertificatePolicyCache> policy_cache,
-    NSArray* tabs) {
-  DCHECK_CURRENTLY_ON(web::WebThread::IO);
+    base::CancelableTaskTracker* task_tracker,
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+    const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
+    TabModel* tab_model) {
+  DCHECK(tab_model);
   DCHECK(policy_cache);
-  policy_cache->ClearCertificatePolicies();
-  web::WebThread::PostTask(
-      web::WebThread::UI, FROM_HERE,
-      base::Bind(&RestoreCertificatePolicyCacheFromTabs, tabs));
+  DCHECK_CURRENTLY_ON(web::WebThread::UI);
+  task_tracker->PostTaskAndReply(
+      task_runner.get(), FROM_HERE,
+      base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies,
+                 policy_cache),
+      base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache,
+                 base::Unretained(tab_model)));
 }
 
 }  // anonymous namespace
@@ -134,6 +138,9 @@
   base::scoped_nsobject<SessionServiceIOS> _sessionService;
   // List of TabModelObservers.
   base::scoped_nsobject<TabModelObservers> _observers;
+
+  // Used to ensure thread-safety of the certificate policy management code.
+  base::CancelableTaskTracker _clearPoliciesTaskTracker;
 }
 
 // Session window for the contents of the tab model.
@@ -201,6 +208,8 @@
   // happen on -closeAllTabs.
   [self closeAllTabs];
 
+  _clearPoliciesTaskTracker.TryCancelAll();
+
   [super dealloc];
 }
 
@@ -551,9 +560,7 @@
   [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex];
 }
 
-- (void)replaceTab:(Tab*)oldTab
-           withTab:(Tab*)newTab
-    keepOldTabOpen:(BOOL)keepOldTabOpen {
+- (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab {
   NSUInteger index = [self indexOfTab:oldTab];
   DCHECK_NE(NSNotFound, static_cast<NSInteger>(index));
 
@@ -569,8 +576,7 @@
     [self changeSelectedTabFrom:nil to:newTab persistState:NO];
 
   [oldTab setParentTabModel:nil];
-  if (!keepOldTabOpen)
-    [oldTab close];
+  [oldTab close];
 
   // Record a tab clobber, since swapping tabs bypasses the tab code that would
   // normally log clobbers.
@@ -954,6 +960,8 @@
 
   size_t oldCount = [_tabs count];
   web::WebState::CreateParams params(_browserState);
+  scoped_refptr<web::CertificatePolicyCache> policyCache =
+      web::BrowserState::GetCertificatePolicyCache(_browserState);
 
   for (CRWNavigationManagerStorage* session in sessions) {
     std::unique_ptr<web::WebState> webState =
@@ -965,7 +973,7 @@
 
     // Restore the CertificatePolicyCache (note that webState is invalid after
     // passing it via move semantic to -insertTabWithWebState:atIndex:).
-    UpdateCertificatePolicyCacheFromWebState(tab.webState);
+    UpdateCertificatePolicyCacheFromWebState(policyCache, tab.webState);
   }
   DCHECK_GT([_tabs count], oldCount);
 
@@ -1012,14 +1020,13 @@
 - (void)applicationDidEnterBackground:(NSNotification*)notify {
   if (!_browserState)
     return;
+
   // Evict all the certificate policies except for the current entries of the
   // active sessions.
-  scoped_refptr<web::CertificatePolicyCache> policy_cache =
-      web::BrowserState::GetCertificatePolicyCache(_browserState);
-  DCHECK(policy_cache);
-  web::WebThread::PostTask(
-      web::WebThread::IO, FROM_HERE,
-      base::Bind(&CleanCertificatePolicyCache, policy_cache, _tabs));
+  CleanCertificatePolicyCache(
+      &_clearPoliciesTaskTracker,
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
+      web::BrowserState::GetCertificatePolicyCache(_browserState), self);
 
   if (_tabUsageRecorder)
     _tabUsageRecorder->AppDidEnterBackground();
diff --git a/ios/chrome/browser/tabs/tab_model_unittest.mm b/ios/chrome/browser/tabs/tab_model_unittest.mm
index c9e60b5d..56507f5 100644
--- a/ios/chrome/browser/tabs/tab_model_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_model_unittest.mm
@@ -13,6 +13,7 @@
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
+#include "ios/chrome/browser/sessions/ios_chrome_session_tab_helper.h"
 #import "ios/chrome/browser/sessions/session_window.h"
 #import "ios/chrome/browser/sessions/test_session_service.h"
 #import "ios/chrome/browser/tabs/tab.h"
@@ -64,29 +65,26 @@
               lastVisitedTimestamp:(double)lastVisitedTimestamp
                       browserState:(ios::ChromeBrowserState*)browserState
                           tabModel:(TabModel*)tabModel {
-  self = [super initWithWindowName:windowName
-                            opener:nil
-                       openedByDOM:NO
-                             model:tabModel
-                      browserState:browserState];
-  if (self) {
-    id webControllerMock =
-        [OCMockObject niceMockForClass:[CRWWebController class]];
+  id webControllerMock =
+      [OCMockObject niceMockForClass:[CRWWebController class]];
 
-    auto webStateImpl = base::MakeUnique<WebStateImpl>(browserState);
-    webStateImpl->SetWebController(webControllerMock);
-    webStateImpl->GetNavigationManagerImpl().InitializeSession(
-        windowName, @"opener", NO, -1);
-    [webStateImpl->GetNavigationManagerImpl().GetSessionController()
-        setLastVisitedTimestamp:lastVisitedTimestamp];
+  auto webStateImpl = base::MakeUnique<WebStateImpl>(browserState);
+  webStateImpl->SetWebController(webControllerMock);
+  webStateImpl->GetNavigationManagerImpl().InitializeSession(windowName,
+                                                             @"opener", NO, -1);
+  [webStateImpl->GetNavigationManagerImpl().GetSessionController()
+      setLastVisitedTimestamp:lastVisitedTimestamp];
 
-    WebStateImpl* webStateImplPtr = webStateImpl.get();
-    [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(webStateImplPtr)]
-        webStateImpl];
-    BOOL yes = YES;
-    [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(yes)] isViewAlive];
+  WebStateImpl* webStateImplPtr = webStateImpl.get();
+  [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(webStateImplPtr)]
+      webStateImpl];
+  BOOL yes = YES;
+  [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(yes)] isViewAlive];
 
-    [self replaceWebState:std::move(webStateImpl)];
+  if ((self = [super initWithWebState:std::move(webStateImpl)
+                                model:tabModel
+                     attachTabHelpers:NO])) {
+    IOSChromeSessionTabHelper::CreateForWebState(self.webState);
   }
   return self;
 }
diff --git a/ios/chrome/browser/tabs/tab_private.h b/ios/chrome/browser/tabs/tab_private.h
index 9dbe8ac..3095c9bc 100644
--- a/ios/chrome/browser/tabs/tab_private.h
+++ b/ios/chrome/browser/tabs/tab_private.h
@@ -24,12 +24,6 @@
 
 @interface Tab (TestingSupport)
 
-// Replaces the existing web state. This method should be called once
-// right after init and before any call to |view|.
-// TODO(crbug.com/620465): change to std::unique_ptr<web::WebState> once
-// Tab no longer uses private //ios/web APIs.
-- (void)replaceWebState:(std::unique_ptr<web::WebStateImpl>)webState;
-
 // Replaces the existing |externalAppLauncher_|.
 - (void)replaceExternalAppLauncher:(id)externalAppLauncher;
 
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm
index f3924d59..c611f47d 100644
--- a/ios/chrome/browser/tabs/tab_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -194,25 +194,21 @@
 
     mock_web_controller_ =
         [OCMockObject niceMockForClass:[CRWWebController class]];
-    std::unique_ptr<WebStateImpl> web_state_impl;
-    web_state_impl.reset(new WebStateImpl(browser_state));
+    auto web_state_impl = base::MakeUnique<WebStateImpl>(browser_state);
     web_state_impl->SetWebController(mock_web_controller_);
     web_state_impl->GetNavigationManagerImpl().InitializeSession(
         @"window1", @"opener", NO, 0);
     web_state_impl_ = web_state_impl.get();
-    [[[(OCMockObject*)mock_web_controller_ stub]
+    [[[static_cast<OCMockObject*>(mock_web_controller_) stub]
         andReturnValue:OCMOCK_VALUE(web_state_impl_)] webStateImpl];
     web_controller_view_.reset([[UIView alloc] init]);
-    [[[(OCMockObject*)mock_web_controller_ stub]
+    [[[static_cast<OCMockObject*>(mock_web_controller_) stub]
         andReturn:web_controller_view_.get()] view];
-    tab_.reset([[Tab alloc] initWithWindowName:nil
-                                        opener:nullptr
-                                   openedByDOM:NO
-                                         model:nil
-                                  browserState:browser_state]);
+    tab_.reset([[Tab alloc] initWithWebState:std::move(web_state_impl)
+                                       model:nil
+                            attachTabHelpers:NO]);
     web::NavigationManager::WebLoadParams params(GURL("chrome://version/"));
     [[tab_ webController] loadWithParams:params];
-    [tab_ replaceWebState:std::move(web_state_impl)];
 
     // There should be no entries in the history at this point.
     history::QueryResults results;
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 8c485b5..772bcf3d 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -286,7 +286,6 @@
     "//ios/chrome/browser/ui/first_run",
     "//ios/chrome/browser/ui/history",
     "//ios/chrome/browser/ui/keyboard",
-    "//ios/chrome/browser/ui/no_tabs",
     "//ios/chrome/browser/ui/ntp",
     "//ios/chrome/browser/ui/ntp:ntp_internal",
     "//ios/chrome/browser/ui/ntp/recent_tabs",
@@ -372,6 +371,7 @@
 }
 
 source_set("eg_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
     "browser_view_controller_egtest.mm",
diff --git a/ios/chrome/browser/ui/activity_services/BUILD.gn b/ios/chrome/browser/ui/activity_services/BUILD.gn
index cac485e..432bafc 100644
--- a/ios/chrome/browser/ui/activity_services/BUILD.gn
+++ b/ios/chrome/browser/ui/activity_services/BUILD.gn
@@ -95,6 +95,7 @@
 }
 
 source_set("eg_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
     "activity_service_controller_egtest.mm",
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
index 85f18be..9211cff 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
@@ -22,6 +22,10 @@
 #include "ios/web/public/test/response_providers/response_provider.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 // Assert the activity service is visible by checking the "copy" button.
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn
index 8d45776..7820ec6 100644
--- a/ios/chrome/browser/ui/autofill/BUILD.gn
+++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 source_set("autofill") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "autofill_client_ios.h",
     "autofill_client_ios.mm",
diff --git a/ios/chrome/browser/ui/autofill/autofill_client_ios.h b/ios/chrome/browser/ui/autofill/autofill_client_ios.h
index 68855edf..ccfd8adc 100644
--- a/ios/chrome/browser/ui/autofill/autofill_client_ios.h
+++ b/ios/chrome/browser/ui/autofill/autofill_client_ios.h
@@ -96,7 +96,7 @@
  private:
   ios::ChromeBrowserState* browser_state_;
   infobars::InfoBarManager* infobar_manager_;
-  id<AutofillClientIOSBridge> bridge_;  // Weak
+  __weak id<AutofillClientIOSBridge> bridge_;
   password_manager::PasswordGenerationManager* password_generation_manager_;
   std::unique_ptr<IdentityProvider> identity_provider_;
   CardUnmaskPromptControllerImpl unmask_controller_;
diff --git a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
index 427c0543..2e91efdb66 100644
--- a/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_client_ios.mm
@@ -28,6 +28,10 @@
 #include "ios/chrome/browser/web_data_service_factory.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace autofill {
 
 AutofillClientIOS::AutofillClientIOS(
diff --git a/ios/chrome/browser/ui/autofill/autofill_save_card_infobar.mm b/ios/chrome/browser/ui/autofill/autofill_save_card_infobar.mm
index 3f07713..c9ad438 100644
--- a/ios/chrome/browser/ui/autofill/autofill_save_card_infobar.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_save_card_infobar.mm
@@ -9,6 +9,10 @@
 #include "components/infobars/core/infobar.h"
 #include "ios/chrome/browser/infobars/infobar_utils.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace autofill {
 
 std::unique_ptr<infobars::InfoBar> CreateSaveCardInfoBarMobile(
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
index 04b6fd6..a0b1fd8 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
@@ -27,6 +27,10 @@
 #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 const CGFloat kTitleVerticalSpacing = 2.0f;
@@ -111,16 +115,16 @@
 }  // autofill
 
 @interface CardUnmaskPromptViewIOS ()<UITextFieldDelegate> {
-  base::scoped_nsobject<UIBarButtonItem> _cancelButton;
-  base::scoped_nsobject<UIBarButtonItem> _verifyButton;
-  base::scoped_nsobject<CVCItem> _CVCItem;
-  base::scoped_nsobject<StatusItem> _statusItem;
-  base::scoped_nsobject<StorageSwitchItem> _storageSwitchItem;
+  UIBarButtonItem* _cancelButton;
+  UIBarButtonItem* _verifyButton;
+  CVCItem* _CVCItem;
+  StatusItem* _statusItem;
+  StorageSwitchItem* _storageSwitchItem;
 
   // The tooltip is added as a child of the collection view rather than the
   // StorageSwitchContentView to allow it to overflow the bounds of the switch
   // view.
-  base::scoped_nsobject<StorageSwitchTooltip> _storageSwitchTooltip;
+  StorageSwitchTooltip* _storageSwitchTooltip;
 
   // Owns |self|.
   autofill::CardUnmaskPromptViewBridge* _bridge;  // weak
@@ -144,15 +148,14 @@
 
   self.styler.cellStyle = MDCCollectionViewCellStyleCard;
 
-  UILabel* titleLabel =
-      [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
+  UILabel* titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
   titleLabel.text =
       SysUTF16ToNSString(_bridge->GetController()->GetWindowTitle());
   titleLabel.font = [UIFont boldSystemFontOfSize:16];
   titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader;
   [titleLabel sizeToFit];
 
-  UIView* titleView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
+  UIView* titleView = [[UIView alloc] initWithFrame:CGRectZero];
   [titleView addSubview:titleLabel];
   CGRect titleBounds = titleView.bounds;
   titleBounds.origin.y -= kTitleVerticalSpacing;
@@ -164,20 +167,20 @@
   [self showCVCInputForm];
 
   // Add the navigation buttons.
-  _cancelButton.reset([[UIBarButtonItem alloc]
-      initWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-              style:UIBarButtonItemStylePlain
-             target:self
-             action:@selector(onCancel:)]);
+  _cancelButton =
+      [[UIBarButtonItem alloc] initWithTitle:l10n_util::GetNSString(IDS_CANCEL)
+                                       style:UIBarButtonItemStylePlain
+                                      target:self
+                                      action:@selector(onCancel:)];
   self.navigationItem.leftBarButtonItem = _cancelButton;
 
   NSString* verifyButtonText =
       SysUTF16ToNSString(_bridge->GetController()->GetOkButtonLabel());
-  _verifyButton.reset([[UIBarButtonItem alloc]
-      initWithTitle:verifyButtonText
-              style:UIBarButtonItemStylePlain
-             target:self
-             action:@selector(onVerify:)]);
+  _verifyButton =
+      [[UIBarButtonItem alloc] initWithTitle:verifyButtonText
+                                       style:UIBarButtonItemStylePlain
+                                      target:self
+                                      action:@selector(onVerify:)];
   [_verifyButton setTitleTextAttributes:@{
     NSForegroundColorAttributeName : [[MDCPalette cr_bluePalette] tint600]
   }
@@ -211,27 +214,27 @@
   NSString* instructions =
       SysUTF16ToNSString(controller->GetInstructionsMessage());
   int CVCImageResourceID = controller->GetCvcImageRid();
-  _CVCItem.reset([[CVCItem alloc] initWithType:ItemTypeCVC]);
-  _CVCItem.get().instructionsText = instructions;
-  _CVCItem.get().CVCImageResourceID = CVCImageResourceID;
+  _CVCItem = [[CVCItem alloc] initWithType:ItemTypeCVC];
+  _CVCItem.instructionsText = instructions;
+  _CVCItem.CVCImageResourceID = CVCImageResourceID;
   [model addItem:_CVCItem toSectionWithIdentifier:SectionIdentifierMain];
 
   if (controller->CanStoreLocally()) {
-    _storageSwitchItem.reset(
-        [[StorageSwitchItem alloc] initWithType:ItemTypeStorageSwitch]);
-    _storageSwitchItem.get().on = controller->GetStoreLocallyStartState();
+    _storageSwitchItem =
+        [[StorageSwitchItem alloc] initWithType:ItemTypeStorageSwitch];
+    _storageSwitchItem.on = controller->GetStoreLocallyStartState();
     [model addItem:_storageSwitchItem
         toSectionWithIdentifier:SectionIdentifierMain];
 
-    _storageSwitchTooltip.reset([[StorageSwitchTooltip alloc] init]);
+    _storageSwitchTooltip = [[StorageSwitchTooltip alloc] init];
     [_storageSwitchTooltip setHidden:YES];
     [self.collectionView addSubview:_storageSwitchTooltip];
   } else {
-    _storageSwitchItem.reset();
+    _storageSwitchItem = nil;
   }
 
   // No status item when loading the model.
-  _statusItem.reset();
+  _statusItem = nil;
 }
 
 #pragma mark - Private
@@ -244,7 +247,7 @@
   [_verifyButton setEnabled:NO];
 
   [self loadModel];
-  _CVCItem.get().errorMessage = errorMessage;
+  _CVCItem.errorMessage = errorMessage;
   // If the server requested a new expiration date, show the date input. If it
   // didn't and there was an error, show the "New card?" link which will show
   // the date inputs on click. This link is intended to remind the user that
@@ -253,10 +256,10 @@
   // we're not requesting a new date. Because if we're asking the user for both,
   // we don't know which is incorrect.
   if (_bridge->GetController()->ShouldRequestExpirationDate()) {
-    _CVCItem.get().showDateInput = YES;
+    _CVCItem.showDateInput = YES;
   } else if (errorMessage) {
-    _CVCItem.get().showNewCardButton = YES;
-    _CVCItem.get().showCVCInputError = YES;
+    _CVCItem.showNewCardButton = YES;
+    _CVCItem.showCVCInputError = YES;
   }
 }
 
@@ -287,9 +290,9 @@
 
 - (void)updateWithStatus:(StatusItemState)state text:(NSString*)text {
   if (!_statusItem) {
-    _statusItem.reset([[StatusItem alloc] initWithType:ItemTypeStatus]);
-    _statusItem.get().text = text;
-    _statusItem.get().state = state;
+    _statusItem = [[StatusItem alloc] initWithType:ItemTypeStatus];
+    _statusItem.text = text;
+    _statusItem.state = state;
     // Remove all the present items to replace them with the status item.
     [self.collectionViewModel
         removeSectionWithIdentifier:SectionIdentifierMain];
@@ -298,9 +301,9 @@
               toSectionWithIdentifier:SectionIdentifierMain];
     [self.collectionView reloadData];
   } else {
-    _statusItem.get().text = text;
-    _statusItem.get().state = state;
-    [self reconfigureCellsForItems:@[ _statusItem.get() ]
+    _statusItem.text = text;
+    _statusItem.state = state;
+    [self reconfigureCellsForItems:@[ _statusItem ]
            inSectionWithIdentifier:SectionIdentifierMain];
     [self.collectionViewLayout invalidateLayout];
   }
@@ -333,7 +336,7 @@
 - (void)layoutTooltipFromButton:(UIButton*)button {
   const CGRect buttonFrameInCollectionView =
       [self.collectionView convertRect:button.bounds fromView:button];
-  CGRect tooltipFrame = _storageSwitchTooltip.get().frame;
+  CGRect tooltipFrame = _storageSwitchTooltip.frame;
 
   // First, set the width and use sizeToFit to have the label flow the text and
   // set the height appropriately.
@@ -342,17 +345,17 @@
       CGRectGetMinX(buttonFrameInCollectionView) - 2 * kTooltipMargin;
   const CGFloat kMaxTooltipWidth = 210;
   tooltipFrame.size.width = MIN(availableWidth, kMaxTooltipWidth);
-  _storageSwitchTooltip.get().frame = tooltipFrame;
+  _storageSwitchTooltip.frame = tooltipFrame;
   [_storageSwitchTooltip sizeToFit];
 
   // Then use the size to position the tooltip appropriately, based on the
   // button position.
-  tooltipFrame = _storageSwitchTooltip.get().frame;
+  tooltipFrame = _storageSwitchTooltip.frame;
   tooltipFrame.origin.x = CGRectGetMinX(buttonFrameInCollectionView) -
                           kTooltipMargin - CGRectGetWidth(tooltipFrame);
   tooltipFrame.origin.y = CGRectGetMaxY(buttonFrameInCollectionView) -
                           CGRectGetHeight(tooltipFrame);
-  _storageSwitchTooltip.get().frame = tooltipFrame;
+  _storageSwitchTooltip.frame = tooltipFrame;
 }
 
 - (BOOL)inputCVCIsValid:(CVCItem*)item {
@@ -412,7 +415,7 @@
     if ((!CVC.monthInput.isFirstResponder || CVC.monthInput.text.length == 0) &&
         (!CVC.yearInput.isFirstResponder || CVC.yearInput.text.length == 0) &&
         (!CVC.CVCInput.isFirstResponder || CVC.CVCInput.text.length == 0)) {
-      if (_CVCItem.get().showDateInput) {
+      if (_CVCItem.showDateInput) {
         [CVC.monthInput becomeFirstResponder];
       } else {
         [CVC.CVCInput becomeFirstResponder];
@@ -428,7 +431,7 @@
   DCHECK(controller);
 
   // The controller requires a 4-digit year. Convert if necessary.
-  NSString* yearText = _CVCItem.get().yearText;
+  NSString* yearText = _CVCItem.yearText;
   if (yearText.length == 2) {
     NSInteger inputYear = yearText.integerValue;
     NSInteger currentYear =
@@ -439,10 +442,10 @@
     yearText = [@(inputYear) stringValue];
   }
 
-  controller->OnUnmaskResponse(
-      base::SysNSStringToUTF16(_CVCItem.get().CVCText),
-      base::SysNSStringToUTF16(_CVCItem.get().monthText),
-      base::SysNSStringToUTF16(yearText), _storageSwitchItem.get().on);
+  controller->OnUnmaskResponse(base::SysNSStringToUTF16(_CVCItem.CVCText),
+                               base::SysNSStringToUTF16(_CVCItem.monthText),
+                               base::SysNSStringToUTF16(yearText),
+                               _storageSwitchItem.on);
 }
 
 - (void)onCancel:(id)sender {
@@ -464,23 +467,23 @@
 
 - (void)onStorageSwitchChanged:(UISwitch*)switchView {
   // Update the item.
-  _storageSwitchItem.get().on = switchView.on;
+  _storageSwitchItem.on = switchView.on;
 }
 
 - (void)onNewCardLinkTapped:(UIButton*)button {
   _bridge->GetController()->NewCardLinkClicked();
-  _CVCItem.get().instructionsText =
+  _CVCItem.instructionsText =
       SysUTF16ToNSString(_bridge->GetController()->GetInstructionsMessage());
-  _CVCItem.get().monthText = @"";
-  _CVCItem.get().yearText = @"";
-  _CVCItem.get().CVCText = @"";
-  _CVCItem.get().errorMessage = @"";
-  _CVCItem.get().showDateInput = YES;
-  _CVCItem.get().showNewCardButton = NO;
-  _CVCItem.get().showDateInputError = NO;
-  _CVCItem.get().showCVCInputError = NO;
+  _CVCItem.monthText = @"";
+  _CVCItem.yearText = @"";
+  _CVCItem.CVCText = @"";
+  _CVCItem.errorMessage = @"";
+  _CVCItem.showDateInput = YES;
+  _CVCItem.showNewCardButton = NO;
+  _CVCItem.showDateInputError = NO;
+  _CVCItem.showCVCInputError = NO;
 
-  [self reconfigureCellsForItems:@[ _CVCItem.get() ]
+  [self reconfigureCellsForItems:@[ _CVCItem ]
          inSectionWithIdentifier:SectionIdentifierMain];
   [self.collectionViewLayout invalidateLayout];
 
@@ -490,23 +493,23 @@
 #pragma mark - UITextField Events
 
 - (void)monthInputDidChange:(UITextField*)textField {
-  _CVCItem.get().monthText = textField.text;
+  _CVCItem.monthText = textField.text;
   [self inputsDidChange:_CVCItem];
   [self updateDateErrorState:_CVCItem];
 }
 
 - (void)yearInputDidChange:(UITextField*)textField {
-  _CVCItem.get().yearText = textField.text;
+  _CVCItem.yearText = textField.text;
   [self inputsDidChange:_CVCItem];
   [self updateDateErrorState:_CVCItem];
 }
 
 - (void)CVCInputDidChange:(UITextField*)textField {
-  _CVCItem.get().CVCText = textField.text;
+  _CVCItem.CVCText = textField.text;
   [self inputsDidChange:_CVCItem];
   if (_bridge->GetController()->InputCvcIsValid(
           base::SysNSStringToUTF16(textField.text))) {
-    _CVCItem.get().showCVCInputError = NO;
+    _CVCItem.showCVCInputError = NO;
     [self updateDateErrorState:_CVCItem];
   }
 }
diff --git a/ios/chrome/browser/ui/autofill/storage_switch_tooltip.mm b/ios/chrome/browser/ui/autofill/storage_switch_tooltip.mm
index ea6e9a2..fc266c7 100644
--- a/ios/chrome/browser/ui/autofill/storage_switch_tooltip.mm
+++ b/ios/chrome/browser/ui/autofill/storage_switch_tooltip.mm
@@ -9,6 +9,10 @@
 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 const CGFloat kCornerRadius = 2.0f;
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h
index c532693..2ee314f 100644
--- a/ios/chrome/browser/ui/browser_view_controller.h
+++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -77,11 +77,6 @@
 // Invisible button used to dismiss the keyboard.
 @property(nonatomic, retain) UIButton* typingShield;
 
-// Valid only for tablet. YES if the tab strip will display the mode toggle
-// switch. May be set to the same value repeatedly with no layout penalty
-// (guaranteed by the tab strip).
-@property(nonatomic, assign) BOOL hasModeToggleSwitch;
-
 // Activates/deactivates the object. This will enable/disable the ability for
 // this object to browse, and to have live UIWebViews associated with it. While
 // not active, the UI will not react to changes in the tab model, so generally
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 830c378..09f2a6ac 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -118,7 +118,6 @@
 #import "ios/chrome/browser/ui/fullscreen_controller.h"
 #import "ios/chrome/browser/ui/history/tab_history_cell.h"
 #import "ios/chrome/browser/ui/key_commands_provider.h"
-#import "ios/chrome/browser/ui/no_tabs/no_tabs_controller.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_controller.h"
 #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_view_controller.h"
 #include "ios/chrome/browser/ui/omnibox/page_info_model.h"
@@ -242,9 +241,6 @@
   }
 }
 
-// Duration to show or hide the No-Tabs UI.
-const NSTimeInterval kNoTabsAnimationDuration = 0.25;
-
 const CGFloat kVoiceSearchBarHeight = 59.0;
 
 // Dimensions to use when downsizing an image for search-by-image.
@@ -396,9 +392,6 @@
   // Used to display the Find In Page UI. Nil if not visible.
   base::scoped_nsobject<FindBarControllerIOS> _findBarController;
 
-  // Used to display the No-Tabs UI for iPads.  Nil if not visible.
-  base::scoped_nsobject<NoTabsController> _noTabsController;
-
   // Used to display the Print UI. Nil if not visible.
   base::scoped_nsobject<PrintController> _printController;
 
@@ -453,10 +446,6 @@
   // Card side swipe view.
   base::scoped_nsobject<CardSideSwipeView> _sideSwipeView;
 
-  // Used to cache value of |hasModeToggleSwitch| if set before the tab strip
-  // controller has been created.
-  BOOL _modeToggleNeedsSetting;
-
   // Dominant color cache. Key: (NSString*)url, val: (UIColor*)dominantColor.
   base::scoped_nsobject<NSMutableDictionary> _dominantColorCache;
 
@@ -589,11 +578,6 @@
 // Initializes the bookmark interaction controller if not already initialized.
 - (void)initializeBookmarkInteractionController;
 
-// Shows the No-Tabs UI with animation.
-- (void)showNoTabsUI;
-// Dismisses the No-Tabs UI with animation.
-- (void)dismissNoTabsUI;
-
 // Shows the tools menu popup.
 - (void)showToolsMenuPopup;
 // Add all delegates to the provided |tab|.
@@ -964,27 +948,6 @@
 
 #pragma mark - Properties
 
-// Implements |hasModeToggleSwitch| property as pass-throughs to tab strip
-// controller and no-tabs controller. If set before the controller has been
-// created, cache it.
-- (void)setHasModeToggleSwitch:(BOOL)hasModeToggleSwitch {
-  if (!experimental_flags::IsTabSwitcherEnabled()) {
-    if (_tabStripController)
-      _tabStripController.get().hasModeToggleSwitch = hasModeToggleSwitch;
-    else
-      _modeToggleNeedsSetting = hasModeToggleSwitch;
-  }
-  [_noTabsController setHasModeToggleSwitch:hasModeToggleSwitch];
-}
-
-// Implements |hasModeToggleSwitch| property as pass-throughs to tab strip
-// controller, unless it hasn't been created in which return the cached version.
-- (BOOL)hasModeToggleSwitch {
-  if (_tabStripController)
-    return _tabStripController.get().hasModeToggleSwitch;
-  return _modeToggleNeedsSetting;
-}
-
 - (void)setActive:(BOOL)active {
   if (_active == active) {
     return;
@@ -1162,13 +1125,7 @@
   DCHECK(self.visible || self.dismissingModal);
   Tab* currentTab = [_model currentTab];
   if (currentTab) {
-    BOOL isChromeScheme =
-        web::GetWebClient()->IsAppSpecificURL([currentTab url]);
-    BOOL snapshotOnIpad =
-        (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
-    if (snapshotOnIpad || !isChromeScheme) {
-      [currentTab updateSnapshotWithOverlay:YES visibleFrameOnly:YES];
-    }
+    [currentTab updateSnapshotWithOverlay:YES visibleFrameOnly:YES];
   }
   [self addSelectedTabWithURL:GURL(kChromeUINewTabURL)
                    transition:ui::PAGE_TRANSITION_TYPED];
@@ -1234,7 +1191,7 @@
   self.visible = YES;
 
   // Restore hidden infobars.
-  if (IsIPadIdiom() && experimental_flags::IsTabSwitcherEnabled()) {
+  if (IsIPadIdiom()) {
     _infoBarContainer->RestoreInfobars();
   }
 
@@ -1255,7 +1212,7 @@
   [[_model currentTab] updateFullscreenWithToolbarVisible:YES];
   [[_model currentTab] wasHidden];
   [_bookmarkInteractionController dismissSnackbar];
-  if (IsIPadIdiom() && experimental_flags::IsTabSwitcherEnabled()) {
+  if (IsIPadIdiom()) {
     _infoBarContainer->SuspendInfobars();
   }
   [super viewWillDisappear:animated];
@@ -1311,7 +1268,6 @@
     _toolbarModelDelegate.reset();
     _toolbarModelIOS.reset();
     _tabStripController.reset();
-    _noTabsController.reset();
     _sideSwipeController.reset();
   }
 }
@@ -1745,20 +1701,10 @@
 
   // If needed, create the tabstrip.
   if (IsIPadIdiom()) {
-    // Determine if it's incognito. Whether or not the toggle button is
-    // visible is consolidated in logic elsewhere so it doesn't need to be set
-    // here.
     _tabStripController.reset(
         [_dependencyFactory newTabStripControllerWithTabModel:_model]);
     _tabStripController.get().fullscreenDelegate = self;
-    [_tabStripController setHasTabSwitcherToggleSwitch:
-                             experimental_flags::IsTabSwitcherEnabled()];
-
-    // If set before the views are loaded, pass the mode toggle to the
-    // toolbar controller (only needed if YES, defaults to NO).
-    if (_modeToggleNeedsSetting) {
-      _tabStripController.get().hasModeToggleSwitch = _modeToggleNeedsSetting;
-    }
+    [_tabStripController setHasTabSwitcherToggleSwitch:YES];
   }
 
   // Create infobar container.
@@ -1962,10 +1908,7 @@
 }
 
 - (void)dismissPopups {
-  if (_noTabsController.get())
-    [_noTabsController dismissToolsMenuPopup];
-  else
-    [_toolbarController dismissToolsMenuPopup];
+  [_toolbarController dismissToolsMenuPopup];
   [self hidePageInfoPopupForView:nil];
   [_toolbarController dismissTabHistoryPopup];
   [[_model currentTab].webController recordStateInHistory];
@@ -3260,98 +3203,11 @@
   }
 }
 
-#pragma mark - No-tabs UI methods
-
-// Show the No-Tabs UI (hiding normal tab/web ui).
-- (void)showNoTabsUI {
-  // The No-Tabs UI is only shown on tablet for non-incognito BVCs.  (Incognito
-  // mode does not have a No-Tabs UI; the user is simply shown the non-incognito
-  // BVC when the last incognito tab is closed.)
-  DCHECK(IsIPadIdiom());
-  DCHECK(!_isOffTheRecord);
-
-  // The method showNoTabsUI is called asynchronously when the number of tabs
-  // reaches zero. Do not show the no tabs UI if a tab was added in the mean
-  // time.
-  if ([_model count])
-    return;
-
-  DCHECK([_model currentTab] == nil);
-  DCHECK([_contentArea subviews].count == 0 ||
-         experimental_flags::IsTabSwitcherEnabled());
-  _noTabsController.reset([[NoTabsController alloc] initWithView:self.view]);
-
-  // Close the tools popup menu if it is open, as its contents/location were
-  // specific to being in the tabs UI.
-  [_toolbarController dismissToolsMenuPopup];
-
-  // Immediately hide the web, toolbar, and tabstrip.
-  [[_toolbarController view] setHidden:YES];
-  [[_tabStripController view] setHidden:YES];
-
-  // Set up the toggle switch animation, if needed.
-  if ([self hasModeToggleSwitch]) {
-    UIButton* animationStartButton = [_tabStripController modeToggleButton];
-    [_noTabsController installAnimationImageForButton:animationStartButton
-                                               inView:self.view
-                                                 show:YES];
-  }
-
-  [_noTabsController prepareForShowAnimation];
-  [UIView animateWithDuration:kNoTabsAnimationDuration
-      animations:^{
-        [_noTabsController showNoTabsUI];
-      }
-      completion:^(BOOL finished) {
-        [_noTabsController showAnimationDidFinish];
-        [_noTabsController setHasModeToggleSwitch:[self hasModeToggleSwitch]];
-      }];
-}
-
-// Hide the No-Tabs UI (restoring normal tab/web ui).
-- (void)dismissNoTabsUI {
-  // The No-Tabs UI is only shown on tablet for non-incognito BVCs, so there is
-  // no need to dismiss it for an incognito BVC.
-  DCHECK(IsIPadIdiom());
-  if (_isOffTheRecord)
-    return;
-
-  // Set up the toggle switch animation, if needed.
-  if ([self hasModeToggleSwitch]) {
-    UIButton* animationEndButton = [_tabStripController modeToggleButton];
-    [_noTabsController installAnimationImageForButton:animationEndButton
-                                               inView:self.view
-                                                 show:NO];
-  }
-
-  [_noTabsController prepareForDismissAnimation];
-
-  // Pull the controller out of the scoped_nsobject so the animation blocks can
-  // retain it.
-  NoTabsController* noTabsController = _noTabsController.get();
-  [UIView animateWithDuration:kNoTabsAnimationDuration
-      animations:^{
-        [noTabsController dismissNoTabsUI];
-      }
-      completion:^(BOOL finished) {
-        // When the animation is finished, remove all of the No-Tabs UI and
-        // reshow the tabstrip, web toolbar, and web.
-        [noTabsController dismissAnimationDidFinish];
-        [[_toolbarController view] setHidden:NO];
-        [[_tabStripController view] setHidden:NO];
-      }];
-  // Nullify the instance variable. The controller is retained by the animation.
-  // Nullifying this variable prevents button press performed during the
-  // animation to be routed to the noTabController.
-  _noTabsController.reset();
-}
-
 #pragma mark - Showing popups
 
 - (void)showToolsMenuPopup {
   DCHECK(_browserState);
   DCHECK(self.visible || self.dismissingModal);
-  DCHECK(!_noTabsController);
 
   // Dismiss the omnibox (if open).
   [_toolbarController cancelOmniboxEdit];
@@ -3453,7 +3309,6 @@
 
 - (void)showTabHistoryPopupForBackwardHistory {
   DCHECK(self.visible || self.dismissingModal);
-  DCHECK(!_noTabsController);
 
   // Dismiss the omnibox (if open).
   [_toolbarController cancelOmniboxEdit];
@@ -3470,7 +3325,6 @@
 
 - (void)showTabHistoryPopupForForwardHistory {
   DCHECK(self.visible || self.dismissingModal);
-  DCHECK(!_noTabsController);
 
   // Dismiss the omnibox (if open).
   [_toolbarController cancelOmniboxEdit];
@@ -3683,7 +3537,7 @@
       [newHistory insertStateFromSessionController:oldHistory];
       [[newTab nativeAppNavigationController]
           copyStateFrom:[oldTab nativeAppNavigationController]];
-      [_model replaceTab:oldTab withTab:newTab keepOldTabOpen:NO];
+      [_model replaceTab:oldTab withTab:newTab];
 
       // Set isPrerenderTab to NO after replacing the tab. This will allow the
       // BrowserViewController to detect that a pre-rendered tab is switched in,
@@ -4027,15 +3881,7 @@
       [self enableDesktopUserAgent];
       break;
     case IDC_SHOW_TOOLS_MENU: {
-      // TODO(blundell): Change this if/else to
-      // |DCHECK(!_noTabsController)| if/when the no tabs controller
-      // becomes part of the responder chain.
-      // The no tabs controller's toolbar should open the menu when in the
-      // no-tabs UI.
-      if (_noTabsController.get())
-        [_noTabsController showToolsMenuPopup];
-      else
-        [self showToolsMenuPopup];
+      [self showToolsMenuPopup];
       break;
     }
     case IDC_SHOW_BOOKMARK_MANAGER: {
@@ -4136,14 +3982,8 @@
   if (tabIndex == NSNotFound)
     return;
 
-  // Take snapshot on iPad only if Tab switcher is enabled, if not just close
-  // the tab.
-  if (IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled()) {
-    [_model closeTabAtIndex:tabIndex];
-    return;
-  }
-
-  // Create image of tab for close animation.
+  // TODO(crbug.com/688003): Evaluate if a screenshot of the tab is needed on
+  // iPad.
   UIImageView* exitingPage = [self pageOpenCloseAnimationView];
   exitingPage.image =
       [currentTab updateSnapshotWithOverlay:YES visibleFrameOnly:YES];
@@ -4201,10 +4041,7 @@
 
   [_printController dismissAnimated:YES];
   _printController.reset();
-  if (_noTabsController.get())
-    [_noTabsController dismissToolsMenuPopup];
-  else
-    [_toolbarController dismissToolsMenuPopup];
+  [_toolbarController dismissToolsMenuPopup];
   [_contextMenuCoordinator stop];
   [self dismissRateThisAppDialog];
 
@@ -4606,26 +4443,7 @@
 // Called when the number of tabs changes. Update the toolbar accordingly.
 - (void)tabModelDidChangeTabCount:(TabModel*)model {
   DCHECK(model == _model);
-  if ([_model count] == 1 && _noTabsController.get()) {
-    [self dismissNoTabsUI];
-  }
-
   [_toolbarController setTabCount:[_model count]];
-  // If the iPad tab switcher feature is enabled, the tab switcher is shown
-  // instead of the no tabs UI. Showing the tab switcher in that case is
-  // done from the main controller.
-  // If the iPad tab switcher feature is disabled and the number of tabs is
-  // zero, ensure the no-tabs UI is visible (such as if the last tab was closed
-  // programmatically from JS).  This is done on a delay because the
-  // notification happens while the tab is going away and trying to trigger a
-  // change during teardown causes problems.
-  BOOL showNoTabsUIOnIPad =
-      IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled();
-  if (![_model count] && showNoTabsUIOnIPad && !_isOffTheRecord) {
-    [self performSelector:@selector(showNoTabsUI)
-               withObject:nil
-               afterDelay:0.01];
-  }
 }
 
 #pragma mark - Upgrade Detection
diff --git a/ios/chrome/browser/ui/browser_view_controller_egtest.mm b/ios/chrome/browser/ui/browser_view_controller_egtest.mm
index f5e27cc7..e39d500 100644
--- a/ios/chrome/browser/ui/browser_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_egtest.mm
@@ -21,6 +21,10 @@
 #include "ios/web/public/test/response_providers/html_response_provider.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 // This test suite only tests javascript in the omnibox. Nothing to do with BVC
 // really, the name is a bit misleading.
 @interface BrowserViewControllerTestCase : ChromeTestCase
diff --git a/ios/chrome/browser/ui/error_page_egtest.mm b/ios/chrome/browser/ui/error_page_egtest.mm
index 7619bfc..b7935cd 100644
--- a/ios/chrome/browser/ui/error_page_egtest.mm
+++ b/ios/chrome/browser/ui/error_page_egtest.mm
@@ -18,6 +18,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 using chrome_test_util::OmniboxText;
 using chrome_test_util::StaticHtmlViewContainingText;
 using chrome_test_util::TapWebViewElementWithId;
diff --git a/ios/chrome/browser/ui/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen_egtest.mm
index 4686bf1..a1ecf39 100644
--- a/ios/chrome/browser/ui/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen_egtest.mm
@@ -28,6 +28,10 @@
 #import "ios/web/public/test/web_view_interaction_test_util.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 // TODO(crbug.com/638674): Move this to a shared location as it is a duplicate
@@ -180,7 +184,7 @@
 
   __block bool finished = false;
   chrome_test_util::GetCurrentWebState()->ExecuteJavaScript(
-      base::UTF8ToUTF16(script), base::BindBlock(^(const base::Value*) {
+      base::UTF8ToUTF16(script), base::BindBlockArc(^(const base::Value*) {
         finished = true;
       }));
 
diff --git a/ios/chrome/browser/ui/keyboard_commands_egtest.mm b/ios/chrome/browser/ui/keyboard_commands_egtest.mm
index e0305e83..ae63e64 100644
--- a/ios/chrome/browser/ui/keyboard_commands_egtest.mm
+++ b/ios/chrome/browser/ui/keyboard_commands_egtest.mm
@@ -24,6 +24,10 @@
 #import "ios/web/public/test/http_server.h"
 #include "ios/web/public/test/http_server_util.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 const CGFloat kScrollDisplacement = 50.0;
 
 // Test cases to verify that keyboard commands are and are not registered when
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.h b/ios/chrome/browser/ui/main/browser_view_wrangler.h
index a18a777..5f887b4 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler.h
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler.h
@@ -57,10 +57,6 @@
 - (void)deleteIncognitoTabModelState:
     (BrowsingDataRemovalController*)removalController;
 
-// Updates the mode toggle buttons on tablet. The incognito tab strip always
-// shows the switcher icon.
-- (void)updateModeToggle;
-
 @end
 
 @interface BrowserViewWrangler (Testing)
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
index d0bc024..8f2ef97 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -212,16 +212,6 @@
   [self updateDeviceSharingManager];
 }
 
-// Called when the number of tabs changes. Updates the switcher button
-// visibility in the various modes on tablet.
-- (void)tabModelDidChangeTabCount:(TabModel*)notifiedTabModel {
-  // If in tablet, update the mode switcher icon based on the number of tabs
-  // in the incognito tab strip. Doing this all the time simplifies a lot
-  // of the state transition logic and setting the property to the same value
-  // incurs no re-layout penalty.
-  [self updateModeToggle];
-}
-
 #pragma mark - Other public methods
 
 - (void)updateDeviceSharingManager {
@@ -291,13 +281,6 @@
   }
 }
 
-- (void)updateModeToggle {
-  if (IsIPadIdiom()) {
-    self.mainBVC.hasModeToggleSwitch = self.otrTabModel.count ? YES : NO;
-    self.otrBVC.hasModeToggleSwitch = YES;
-  }
-}
-
 #pragma mark - Internal methods
 
 - (TabModel*)buildOtrTabModel:(BOOL)empty {
diff --git a/ios/chrome/browser/ui/no_tabs/BUILD.gn b/ios/chrome/browser/ui/no_tabs/BUILD.gn
deleted file mode 100644
index e243a5d..0000000
--- a/ios/chrome/browser/ui/no_tabs/BUILD.gn
+++ /dev/null
@@ -1,34 +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.
-
-source_set("no_tabs") {
-  sources = [
-    "no_tabs_controller.h",
-    "no_tabs_controller.mm",
-    "no_tabs_controller_testing.h",
-    "no_tabs_toolbar_controller.h",
-    "no_tabs_toolbar_controller.mm",
-  ]
-  deps = [
-    "//base",
-    "//ios/chrome/browser/ui",
-    "//ios/chrome/browser/ui/commands",
-    "//ios/chrome/browser/ui/toolbar",
-    "//ios/chrome/browser/ui/tools_menu",
-    "//ui/gfx",
-  ]
-  libs = [ "UIKit.framework" ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "no_tabs_controller_unittest.mm",
-  ]
-  deps = [
-    ":no_tabs",
-    "//base",
-    "//testing/gtest",
-  ]
-}
diff --git a/ios/chrome/browser/ui/no_tabs/OWNERS b/ios/chrome/browser/ui/no_tabs/OWNERS
deleted file mode 100644
index 40a68c7..0000000
--- a/ios/chrome/browser/ui/no_tabs/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/no_tabs/no_tabs_controller.h b/ios/chrome/browser/ui/no_tabs/no_tabs_controller.h
deleted file mode 100644
index f0374000..0000000
--- a/ios/chrome/browser/ui/no_tabs/no_tabs_controller.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 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 IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_CONTROLLER_H_
-
-#import <UIKit/UIKit.h>
-
-@class NoTabsToolbarController;
-
-@interface NoTabsController : NSObject
-
-// Desginated initializer. Installs the No-Tabs UI in the given |view|.
-- (id)initWithView:(UIView*)view;
-
-// Sets whether or not the No-Tabs UI displays a mode toggle switch.  Passes
-// through to the underlying NoTabsToolbarController.
-- (void)setHasModeToggleSwitch:(BOOL)hasModeToggle;
-
-// Sets up and installs an animation that will animate between the given
-// buttons.  If |show| is YES, the animation is set up as a show animation;
-// otherwise, it is set up as a dismiss animation.
-- (void)installAnimationImageForButton:(UIButton*)fromButton
-                                inView:(UIView*)view
-                                  show:(BOOL)show;
-
-// TODO(blundell): This method should be internalized if the NoTabsController
-// becomes part of the responder chain and can catch the command to show the
-// tools menu directly via |chromeExecuteCommand|.
-// Shows the tools menu popup.
-- (void)showToolsMenuPopup;
-
-// Dismisses the tools popup if it is open.
-- (void)dismissToolsMenuPopup;
-
-// Must be called before starting the show animation in order to move views into
-// their pre-animation positions.
-- (void)prepareForShowAnimation;
-
-// Shows the No-Tabs UI.  Can be called from within an animation block to
-// animate the show.
-- (void)showNoTabsUI;
-
-// Must be called after the show animation finishes to allow this controller to
-// clean up any animation-related state.
-- (void)showAnimationDidFinish;
-
-// Must be called before starting the dismiss animation in order to move views
-// into their pre-animation positions.
-- (void)prepareForDismissAnimation;
-
-// Dismisses the No-Tabs UI.  Can be called from within an animation block to
-// animate the dismiss.
-- (void)dismissNoTabsUI;
-
-// Must be called after the dismiss animation finishes to allow this controller
-// to clean up any animation-related state.
-- (void)dismissAnimationDidFinish;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/no_tabs/no_tabs_controller.mm b/ios/chrome/browser/ui/no_tabs/no_tabs_controller.mm
deleted file mode 100644
index 286fdf44..0000000
--- a/ios/chrome/browser/ui/no_tabs/no_tabs_controller.mm
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 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.
-
-#import "ios/chrome/browser/ui/no_tabs/no_tabs_controller.h"
-
-#include "base/logging.h"
-#include "base/mac/objc_property_releaser.h"
-#include "base/mac/scoped_nsobject.h"
-#import "ios/chrome/browser/ui/background_generator.h"
-#import "ios/chrome/browser/ui/no_tabs/no_tabs_controller_testing.h"
-#import "ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
-#import "ios/chrome/browser/ui/tools_menu/tools_menu_context.h"
-#include "ios/chrome/browser/ui/ui_util.h"
-
-@interface NoTabsController (PrivateMethods)
-// Creates and installs the toolbar for the No-Tabs UI.
-- (void)installNoTabsToolbarInView:(UIView*)view;
-// Creates and installs the background view for the No-Tabs UI.
-- (void)installNoTabsBackgroundInView:(UIView*)view;
-// Returns the frame of a button's image view.
-- (CGRect)imageFrameForButton:(UIButton*)button inView:(UIView*)view;
-// Creates and installs the UIImageView that is used to animate the mode toggle
-// button.
-- (void)installNoTabsAnimationToggleImageForButton:(UIButton*)button
-                                            inView:(UIView*)view;
-@end
-
-@implementation NoTabsController {
-  // The No-Tabs toolbar.
-  base::scoped_nsobject<NoTabsToolbarController> toolbarController_;
-
-  // The parent view of the No-Tabs UI. Must outlive this object.
-  UIView* parentView_;  // weak
-
-  // The background view behind the No-Tabs UI.
-  base::scoped_nsobject<UIView> backgroundView_;
-
-  // The image view used to animate the mode toggle button when entering or
-  // leaving the No-Tabs UI.
-  base::scoped_nsobject<UIImageView> modeToggleImageView_;
-
-  // The ending frame for the mode toggle button animation.  Equal to CGRectZero
-  // if the mode toggle button is not being animated.
-  CGRect toggleImageEndFrame_;
-
-  base::mac::ObjCPropertyReleaser propertyReleaser_NoTabsController_;
-}
-
-// Designated initializer.
-- (id)initWithView:(UIView*)view {
-  self = [super init];
-  if (self) {
-    propertyReleaser_NoTabsController_.Init(self, [NoTabsController class]);
-
-    parentView_ = view;
-    [self installNoTabsToolbarInView:view];
-    [self installNoTabsBackgroundInView:view];
-  }
-  return self;
-}
-
-// Passes the call through to the toolbar controller.
-- (void)setHasModeToggleSwitch:(BOOL)hasModeToggle {
-  [toolbarController_ setHasModeToggleSwitch:hasModeToggle];
-}
-
-// Prepares the given button for animation.
-- (void)installAnimationImageForButton:(UIButton*)button
-                                inView:(UIView*)view
-                                  show:(BOOL)show {
-  UIButton* fromButton = nil;
-  UIButton* toButton = nil;
-
-  if (show) {
-    fromButton = button;
-    toButton = [toolbarController_ modeToggleButton];
-  } else {
-    fromButton = [toolbarController_ modeToggleButton];
-    toButton = button;
-  }
-
-  [self installNoTabsAnimationToggleImageForButton:fromButton inView:view];
-  toggleImageEndFrame_ = [self imageFrameForButton:toButton inView:view];
-}
-
-- (void)showToolsMenuPopup {
-  base::scoped_nsobject<ToolsMenuContext> context(
-      [[ToolsMenuContext alloc] initWithDisplayView:parentView_]);
-  [context setNoOpenedTabs:YES];
-  [toolbarController_ showToolsMenuPopupWithContext:context];
-}
-
-- (void)dismissToolsMenuPopup {
-  [toolbarController_ dismissToolsMenuPopup];
-}
-
-- (void)prepareForShowAnimation {
-  CGFloat toolbarHeight = CGRectGetHeight([[toolbarController_ view] frame]);
-
-  // The toolbar icons start offscreen and animate in.
-  [toolbarController_
-      setControlsTransform:CGAffineTransformMakeTranslation(0, -toolbarHeight)];
-}
-
-- (void)showNoTabsUI {
-  [toolbarController_ setControlsTransform:CGAffineTransformIdentity];
-
-  if (modeToggleImageView_.get()) {
-    DCHECK(!CGRectEqualToRect(toggleImageEndFrame_, CGRectZero));
-    [modeToggleImageView_ setFrame:toggleImageEndFrame_];
-    toggleImageEndFrame_ = CGRectZero;
-  }
-}
-
-- (void)showAnimationDidFinish {
-  // When the animation is finished, remove the temporary toggle switch image.
-  [modeToggleImageView_ removeFromSuperview];
-  modeToggleImageView_.reset();
-}
-
-- (void)prepareForDismissAnimation {
-  // Hide the toolbar mode toggle button so that it does not visibly animate
-  // out.
-  [[toolbarController_ modeToggleButton] setHidden:YES];
-}
-
-- (void)dismissNoTabsUI {
-  CGFloat toolbarHeight = [[toolbarController_ view] frame].size.height;
-  [toolbarController_
-      setControlsTransform:CGAffineTransformMakeTranslation(0, -toolbarHeight)];
-
-  if (modeToggleImageView_.get()) {
-    DCHECK(!CGRectEqualToRect(toggleImageEndFrame_, CGRectZero));
-    [modeToggleImageView_ setFrame:toggleImageEndFrame_];
-    toggleImageEndFrame_ = CGRectZero;
-  }
-}
-
-- (void)dismissAnimationDidFinish {
-  [modeToggleImageView_ removeFromSuperview];
-  modeToggleImageView_.reset();
-  [backgroundView_ removeFromSuperview];
-  backgroundView_.reset();
-  [[toolbarController_ view] removeFromSuperview];
-  toolbarController_.reset();
-}
-
-// Creates and installs the toolbar for the No-Tabs UI.
-- (void)installNoTabsToolbarInView:(UIView*)view {
-  toolbarController_.reset([[NoTabsToolbarController alloc] initWithNoTabs]);
-  UIView* toolbarView = [toolbarController_ view];
-  CGFloat toolbarHeight = CGRectGetHeight(toolbarView.frame);
-
-  CGRect toolbarFrame = [view bounds];
-  toolbarFrame.origin.y = StatusBarHeight();
-  toolbarFrame.size.height = toolbarHeight;
-  toolbarView.frame = toolbarFrame;
-  [view addSubview:toolbarView];
-}
-
-// Creates and installs the background view for the No-Tabs UI.
-- (void)installNoTabsBackgroundInView:(UIView*)view {
-  DCHECK(toolbarController_);
-  UIView* toolbarView = [toolbarController_ view];
-
-  backgroundView_.reset([[UIView alloc] initWithFrame:view.bounds]);
-  [backgroundView_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth |
-                                        UIViewAutoresizingFlexibleHeight)];
-  InstallBackgroundInView(backgroundView_);
-  [view insertSubview:backgroundView_ belowSubview:toolbarView];
-}
-
-// Returns the frame of a button's image view.
-- (CGRect)imageFrameForButton:(UIButton*)button inView:(UIView*)view {
-  // Convert the existing button's bounds to the coordinate system of |view| and
-  // trim away any padding present in the button.
-  CGRect rect = UIEdgeInsetsInsetRect(button.bounds, button.imageEdgeInsets);
-  return [view convertRect:rect fromView:button];
-}
-
-// Installs the UIImageView that is used to animate the mode toggle switch while
-// the No-Tabs UI is shown or hidden.  This image view is initially set up to
-// exactly cover the image of an existing button.
-- (void)installNoTabsAnimationToggleImageForButton:(UIButton*)button
-                                            inView:(UIView*)view {
-  UIImage* image = [button imageForState:UIControlStateNormal];
-  modeToggleImageView_.reset([[UIImageView alloc] initWithImage:image]);
-  [modeToggleImageView_
-      setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin |
-                           UIViewAutoresizingFlexibleTopMargin)];
-  [modeToggleImageView_ setFrame:[self imageFrameForButton:button inView:view]];
-  [view addSubview:modeToggleImageView_];
-}
-
-@end
-
-#pragma mark - TestingAdditions
-
-@implementation NoTabsController (JustForTesting)
-- (UIButton*)modeToggleButton {
-  return [toolbarController_ modeToggleButton];
-}
-
-- (UIView*)toolbarView {
-  return [toolbarController_ view];
-}
-
-- (UIView*)backgroundView {
-  return backgroundView_.get();
-}
-@end
diff --git a/ios/chrome/browser/ui/no_tabs/no_tabs_controller_testing.h b/ios/chrome/browser/ui/no_tabs/no_tabs_controller_testing.h
deleted file mode 100644
index 699abda..0000000
--- a/ios/chrome/browser/ui/no_tabs/no_tabs_controller_testing.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 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 IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_CONTROLLER_TESTING_H_
-#define IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_CONTROLLER_TESTING_H_
-
-// Exposes necessary methods used for testing.
-@interface NoTabsController (TestingAdditions)
-- (UIButton*)modeToggleButton;
-- (UIView*)toolbarView;
-- (UIView*)backgroundView;
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_CONTROLLER_TESTING_H_
diff --git a/ios/chrome/browser/ui/no_tabs/no_tabs_controller_unittest.mm b/ios/chrome/browser/ui/no_tabs/no_tabs_controller_unittest.mm
deleted file mode 100644
index ad36c1f..0000000
--- a/ios/chrome/browser/ui/no_tabs/no_tabs_controller_unittest.mm
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 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.
-
-#import <Foundation/Foundation.h>
-
-#include "base/mac/scoped_nsobject.h"
-#import "ios/chrome/browser/ui/no_tabs/no_tabs_controller.h"
-#import "ios/chrome/browser/ui/no_tabs/no_tabs_controller_testing.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-class NoTabsControllerTest : public PlatformTest {
- protected:
-  void SetUp() override {
-    view_.reset([[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 240)]);
-    controller_.reset([[NoTabsController alloc] initWithView:view_]);
-  };
-
-  base::scoped_nsobject<UIView> view_;
-  base::scoped_nsobject<NoTabsController> controller_;
-};
-
-// Verifies that the mode toggle switch is properly shown and hidden.
-TEST_F(NoTabsControllerTest, ModeToggleSwitch) {
-  // The mode toggle button starts out hidden.
-  UIButton* button = [controller_ modeToggleButton];
-  ASSERT_TRUE([button isHidden]);
-
-  [controller_ setHasModeToggleSwitch:YES];
-  ASSERT_FALSE([button isHidden]);
-
-  [controller_ setHasModeToggleSwitch:NO];
-  ASSERT_TRUE([button isHidden]);
-}
-
-// Tests that creating a NoTabsController properly installs the No-Tabs UI into
-// the provided view.
-TEST_F(NoTabsControllerTest, Installation) {
-  // The toolbar view should be installed in |view_|, and it should take up the
-  // full width of |view_|.
-  UIView* toolbarView = [controller_ toolbarView];
-  EXPECT_EQ(view_, [toolbarView superview]);
-  EXPECT_EQ(CGRectGetWidth([view_ bounds]),
-            CGRectGetWidth([toolbarView frame]));
-
-  // The background view should fill |view_| completely. Note that its
-  // height/width might be larger than those of |view_|, as it has some padding
-  // to avoid visual flickering around the edges on device rotation.
-  UIView* backgroundView = [controller_ backgroundView];
-  EXPECT_EQ(view_, [backgroundView superview]);
-  EXPECT_LE([view_ bounds].size.width, [backgroundView frame].size.width);
-  EXPECT_LE([view_ bounds].size.height, [backgroundView frame].size.height);
-  EXPECT_TRUE(CGPointEqualToPoint([view_ center], [backgroundView center]));
-}
-
-// Tests that running through the show and hide methods does not crash.
-// TODO(rohitrao): This is a somewhat silly test.  Test something more
-// interesting.
-TEST_F(NoTabsControllerTest, ShowAndHideNoTabsUI) {
-  // Show the UI.
-  [controller_ prepareForShowAnimation];
-  [controller_ showNoTabsUI];
-  [controller_ showAnimationDidFinish];
-
-  // Hide the UI.
-  [controller_ prepareForDismissAnimation];
-  [controller_ dismissNoTabsUI];
-  [controller_ dismissAnimationDidFinish];
-}
-
-}  // namespace
diff --git a/ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.h b/ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.h
deleted file mode 100644
index 6cc189ac..0000000
--- a/ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 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 IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_TOOLBAR_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_TOOLBAR_CONTROLLER_H_
-
-#import <UIKit/UIKit.h>
-
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
-
-// Toolbar controller for the no tabs view, adding a new tab button and a mode
-// toggle button..
-@interface NoTabsToolbarController : ToolbarController
-
-// Designated initializer.
-- (instancetype)initWithNoTabs;
-
-// Applies the given |transform| to all of the controls in this toolbar.
-- (void)setControlsTransform:(CGAffineTransform)transform;
-
-// Sets whether or not this toolbar displays a mode toggle switch.
-- (void)setHasModeToggleSwitch:(BOOL)hasModeToggle;
-
-// Return the button for toggling between normal and incognito.
-- (UIButton*)modeToggleButton;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_NO_TABS_NO_TABS_TOOLBAR_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.mm b/ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.mm
deleted file mode 100644
index c4e6a57..0000000
--- a/ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.mm
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 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.
-
-#import "ios/chrome/browser/ui/no_tabs/no_tabs_toolbar_controller.h"
-
-#include "base/mac/scoped_nsobject.h"
-#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
-#include "ios/chrome/browser/ui/commands/ios_command_ids.h"
-#import "ios/chrome/browser/ui/rtl_geometry.h"
-#include "ios/chrome/browser/ui/toolbar/new_tab_button.h"
-#import "ios/chrome/browser/ui/uikit_ui_util.h"
-#import "ui/gfx/ios/uikit_util.h"
-
-namespace {
-
-const CGFloat kNewTabButtonLeading = 8;
-const CGFloat kModeToggleWidth = 34;
-const CGFloat kModeToggleHeight = 38;
-
-}  // end namespace
-
-@interface NoTabsToolbarController () {
-  // Top-level view for notabs-specific content.
-  base::scoped_nsobject<UIView> _noTabsToolbar;
-  base::scoped_nsobject<UIButton> _buttonNewTab;
-  base::scoped_nsobject<UIButton> _modeToggleButton;
-}
-
-@end
-
-@implementation NoTabsToolbarController
-
-- (instancetype)initWithNoTabs {
-  self = [super initWithStyle:ToolbarControllerStyleDarkMode];
-  if (self) {
-    _noTabsToolbar.reset([[UIView alloc] initWithFrame:self.view.bounds]);
-    [_noTabsToolbar setBackgroundColor:[UIColor clearColor]];
-    [_noTabsToolbar setAutoresizingMask:UIViewAutoresizingFlexibleWidth |
-                                        UIViewAutoresizingFlexibleBottomMargin];
-
-    // Resize the container to match the available area.
-    // Do this before the layouts of subviews are computed.
-    [_noTabsToolbar setFrame:[self specificControlsArea]];
-
-    CGFloat boundingHeight = [_noTabsToolbar bounds].size.height;
-    CGFloat boundingWidth = [_noTabsToolbar bounds].size.width;
-    LayoutRect newTabButtonLayout = LayoutRectMake(
-        kNewTabButtonLeading, boundingWidth, 0, boundingHeight, boundingHeight);
-    _buttonNewTab.reset([[NewTabButton alloc]
-        initWithFrame:LayoutRectGetRect(newTabButtonLayout)]);
-    [_buttonNewTab
-        setAutoresizingMask:UIViewAutoresizingFlexibleTrailingMargin()];
-
-    LayoutRect modeToggleButtonLayout = LayoutRectMake(
-        boundingWidth - kModeToggleWidth - boundingHeight, boundingWidth,
-        ui::AlignValueToUpperPixel((boundingHeight - kModeToggleHeight) / 2),
-        kModeToggleWidth, kModeToggleHeight);
-
-    _modeToggleButton.reset([[UIButton alloc]
-        initWithFrame:LayoutRectGetRect(modeToggleButtonLayout)]);
-    [_modeToggleButton setHidden:YES];
-    [_modeToggleButton
-        setAutoresizingMask:UIViewAutoresizingFlexibleLeadingMargin()];
-    [_modeToggleButton setImageEdgeInsets:UIEdgeInsetsMakeDirected(7, 5, 7, 5)];
-    [_modeToggleButton setImage:[UIImage imageNamed:@"tabstrip_switch"]
-                       forState:UIControlStateNormal];
-    [_modeToggleButton setTag:IDC_SWITCH_BROWSER_MODES];
-    [_modeToggleButton addTarget:self
-                          action:@selector(recordUserMetrics:)
-                forControlEvents:UIControlEventTouchUpInside];
-    [_modeToggleButton addTarget:_modeToggleButton
-                          action:@selector(chromeExecuteCommand:)
-                forControlEvents:UIControlEventTouchUpInside];
-
-    // The toolbar background is not supposed to show in the no-tabs UI.
-    [self.backgroundView setHidden:YES];
-
-    [self.view addSubview:_noTabsToolbar];
-    [_noTabsToolbar addSubview:_buttonNewTab];
-    [_noTabsToolbar addSubview:_modeToggleButton];
-
-    self.shadowView.hidden = YES;
-  }
-  return self;
-}
-
-// Applies the given transform to this toolbar's controls.
-- (void)setControlsTransform:(CGAffineTransform)transform {
-  [self setStandardControlsTransform:transform];
-  [_buttonNewTab setTransform:transform];
-  [_modeToggleButton setTransform:transform];
-}
-
-// Shows or hides the mode toggle switch.
-- (void)setHasModeToggleSwitch:(BOOL)hasModeToggle {
-  [_modeToggleButton setHidden:!hasModeToggle];
-}
-
-// Called when a button is pressed.
-- (void)recordUserMetrics:(id)sender {
-  if (sender == _buttonNewTab.get()) {
-    // TODO(rohitrao): Record metrics. http://crbug.com/437418
-  } else if (sender == _modeToggleButton.get()) {
-    // TODO(rohitrao): Record metrics. http://crbug.com/437418
-  } else {
-    [super recordUserMetrics:sender];
-  }
-}
-
-- (UIButton*)modeToggleButton {
-  return _modeToggleButton;
-}
-
-@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm b/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm
index 5dda34fc..e89e100c 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm
@@ -4,11 +4,12 @@
 
 #import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h"
 
+#include "base/logging.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h"
-#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+#import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -34,7 +35,7 @@
 const CGFloat kIconSize = 24;
 const CGFloat kLineHeight = 24;
 const CGFloat kPercentageFromTopForPosition = 0.4;
-const CGFloat kAlphaForCaret = 0.7;
+const CGFloat kAlphaForCaret = 0.4;
 
 }  // namespace
 
@@ -42,10 +43,12 @@
 
 // Attaches the icon named |iconName| to |instructionString| and a |caret|. The
 // icon is positionned using the |iconOffset| and with the |attributes| (mainly
-// the color).
+// the color). |spaceBeforeCaret| controls whether a space should be added
+// between the image and the caret.
 - (void)attachIconNamed:(NSString*)iconName
                toString:(NSMutableAttributedString*)instructionString
               withCaret:(NSMutableAttributedString*)caret
+       spaceBeforeCaret:(BOOL)spaceBeforeCaret
                  offset:(CGFloat)iconOffset
         imageAttributes:(NSDictionary*)attributes;
 // Sets the constraints for this view, positionning the |imageView| in the X
@@ -64,12 +67,12 @@
   if (self) {
     NSString* rawText =
         l10n_util::GetNSString(IDS_IOS_READING_LIST_EMPTY_MESSAGE);
-    // Add a space between Read Later and the preceding caret.
-    NSString* readLater = [@" "
+    // Add two spaces between Read Later and the preceding caret.
+    NSString* readLater = [@"  "
         stringByAppendingString:l10n_util::GetNSString(
                                     IDS_IOS_SHARE_MENU_READING_LIST_ACTION)];
 
-    id<MDCTypographyFontLoading> fontLoader = [MDCTypography fontLoader];
+    MDFRobotoFontLoader* fontLoader = [MDFRobotoFontLoader sharedInstance];
 
     UIColor* textColor = [[MDCPalette greyPalette] tint700];
     UIFont* textFont = [fontLoader regularFontOfSize:kFontSize];
@@ -77,7 +80,7 @@
         [[NSMutableParagraphStyle alloc] init];
     paragraphStyle.lineSpacing = kLineHeight - textFont.lineHeight;
 
-    NSDictionary* attributes = @{
+    NSDictionary* textAttributes = @{
       NSFontAttributeName : textFont,
       NSForegroundColorAttributeName : textColor,
       NSParagraphStyleAttributeName : paragraphStyle
@@ -87,7 +90,7 @@
     CGFloat iconOffset = (textFont.xHeight - kIconSize) / 2.0;
 
     UIColor* caretColor = [textColor colorWithAlphaComponent:kAlphaForCaret];
-    UIFont* instructionFont = [fontLoader mediumFontOfSize:kFontSize];
+    UIFont* instructionFont = [fontLoader boldFontOfSize:kFontSize];
     NSDictionary* caretAttributes = @{
       NSFontAttributeName : instructionFont,
       NSForegroundColorAttributeName : caretColor,
@@ -100,7 +103,7 @@
 
     NSMutableAttributedString* baseAttributedString =
         [[NSMutableAttributedString alloc] initWithString:rawText
-                                               attributes:attributes];
+                                               attributes:textAttributes];
 
     NSMutableAttributedString* caret =
         [[NSMutableAttributedString alloc] initWithString:[self caretString]
@@ -116,15 +119,23 @@
       [self attachIconNamed:kToolbarMenuIcon
                    toString:instructionString
                   withCaret:caret
+           spaceBeforeCaret:NO
                      offset:iconOffset
-            imageAttributes:attributes];
+            imageAttributes:textAttributes];
     }
 
+    // Add a space before the share icon.
+    [instructionString
+        appendAttributedString:[[NSAttributedString alloc]
+                                   initWithString:@" "
+                                       attributes:instructionAttributes]];
+
     [self attachIconNamed:kShareMenuIcon
                  toString:instructionString
                 withCaret:caret
+         spaceBeforeCaret:YES
                    offset:iconOffset
-          imageAttributes:attributes];
+          imageAttributes:textAttributes];
 
     // Add the "Read Later" string.
     NSAttributedString* shareMenuAction =
@@ -134,6 +145,7 @@
 
     NSRange iconRange =
         [[baseAttributedString string] rangeOfString:kOpenShareMarker];
+    DCHECK(iconRange.location != NSNotFound);
     [baseAttributedString replaceCharactersInRange:iconRange
                               withAttributedString:instructionString];
 
@@ -158,6 +170,7 @@
 - (void)attachIconNamed:(NSString*)iconName
                toString:(NSMutableAttributedString*)instructionString
               withCaret:(NSMutableAttributedString*)caret
+       spaceBeforeCaret:(BOOL)spaceBeforeCaret
                  offset:(CGFloat)iconOffset
         imageAttributes:(NSDictionary*)attributes {
   // Add a zero width space to set the attributes for the image.
@@ -172,6 +185,13 @@
   [instructionString
       appendAttributedString:[NSAttributedString
                                  attributedStringWithAttachment:toolbarIcon]];
+
+  if (spaceBeforeCaret) {
+    [instructionString appendAttributedString:[[NSAttributedString alloc]
+                                                  initWithString:@" "
+                                                      attributes:attributes]];
+  }
+
   [instructionString appendAttributedString:caret];
 }
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm
index 63a6bd8..554a28b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller_egtest.mm
@@ -6,7 +6,6 @@
 #import <UIKit/UIKit.h>
 #import <XCTest/XCTest.h>
 
-#include "base/test/scoped_command_line.h"
 #import "ios/chrome/app/main_controller_private.h"
 #include "ios/chrome/browser/chrome_switches.h"
 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
@@ -86,16 +85,7 @@
 @interface TabSwitcherControllerTestCase : ChromeTestCase
 @end
 
-@implementation TabSwitcherControllerTestCase {
-  std::unique_ptr<base::test::ScopedCommandLine> scoped_command_line_;
-}
-
-- (void)setUp {
-  [super setUp];
-  scoped_command_line_.reset(new base::test::ScopedCommandLine());
-  scoped_command_line_->GetProcessCommandLine()->AppendSwitch(
-      switches::kEnableTabSwitcher);
-}
+@implementation TabSwitcherControllerTestCase
 
 // Checks that the tab switcher is not presented.
 - (void)assertTabSwitcherIsInactive {
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn
index aa66479..059a759 100644
--- a/ios/chrome/browser/ui/tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -94,6 +94,7 @@
 }
 
 source_set("eg_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
     "tab_strip_egtest.mm",
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
index fd96524b..072c4e8 100644
--- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
+++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -122,6 +122,7 @@
   UIView* _view;
   TabStripView* _tabStripView;
   UIButton* _buttonNewTab;
+  // TODO(crbug.com/687132): Remove toggle button.
   UIButton* _modeToggleButton;         // weak, nil if not visible.
   UIButton* _tabSwitcherToggleButton;  // weak, nil if not visible.
 
@@ -1091,7 +1092,6 @@
   [_modeToggleButton addTarget:nil
                         action:@selector(chromeExecuteCommand:)
               forControlEvents:UIControlEventTouchUpInside];
-  [_modeToggleButton setTag:IDC_SWITCH_BROWSER_MODES];
   [_modeToggleButton addTarget:self
                         action:@selector(recordUserMetrics:)
               forControlEvents:UIControlEventTouchUpInside];
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_egtest.mm b/ios/chrome/browser/ui/tabs/tab_strip_egtest.mm
index e6cb58c4..8420edd1 100644
--- a/ios/chrome/browser/ui/tabs/tab_strip_egtest.mm
+++ b/ios/chrome/browser/ui/tabs/tab_strip_egtest.mm
@@ -14,6 +14,10 @@
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 // Tests for the tab strip shown on iPad.
 @interface TabStripTestCase : ChromeTestCase
 @end
@@ -55,50 +59,4 @@
   }
 }
 
-// Tests switching the mode using the mode toggle.
-- (void)testTabStripSwitchModes {
-  // The toggle button only exists on iPad, and when the Tablet Tab Switcher
-  // isn't enabled.
-  if (IsCompact() || experimental_flags::IsTabSwitcherEnabled()) {
-    return;
-  }
-
-  // Open two normal tabs.
-  [ChromeEarlGreyUI openNewTab];
-  [ChromeEarlGreyUI openNewTab];
-
-  // Open two incognito tabs.
-  [ChromeEarlGreyUI openNewIncognitoTab];
-  [ChromeEarlGreyUI openNewIncognitoTab];
-
-  // Switch back to normal mode.
-  [[EarlGrey selectElementWithMatcher:
-                 grey_accessibilityLabel(l10n_util::GetNSString(
-                     IDS_IOS_SWITCH_BROWSER_MODE_LEAVE_INCOGNITO))]
-      performAction:grey_tap()];
-  GREYAssertFalse(chrome_test_util::IsIncognitoMode(),
-                  @"Current tab is incognito.");
-
-  // Switch back to incognito mode.
-  [[EarlGrey selectElementWithMatcher:
-                 grey_accessibilityLabel(l10n_util::GetNSString(
-                     IDS_IOS_SWITCH_BROWSER_MODE_ENTER_INCOGNITO))]
-      performAction:grey_tap()];
-  GREYAssertTrue(chrome_test_util::IsIncognitoMode(),
-                 @"Current tab is not incognito.");
-
-  // Close both incognito tabs.
-  chrome_test_util::CloseAllTabsInCurrentMode();
-
-  // We should be in normal mode.
-  GREYAssertFalse(chrome_test_util::IsIncognitoMode(),
-                  @"Current tab is incognito.");
-
-  // There should be no incognito switch.
-  [[EarlGrey selectElementWithMatcher:
-                 grey_accessibilityID(l10n_util::GetNSString(
-                     IDS_IOS_SWITCH_BROWSER_MODE_ENTER_INCOGNITO))]
-      assertWithMatcher:grey_notVisible()];
-}
-
 @end
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm
index f05adfde..e6157e4 100644
--- a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm
+++ b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm
@@ -163,7 +163,7 @@
     return NO;
 
   if (item.title_id == IDS_IOS_TOOLBAR_SHOW_TABS) {
-    if (!IsIPadIdiom() || !experimental_flags::IsTabSwitcherEnabled()) {
+    if (!IsIPadIdiom()) {
       return NO;
     }
   }
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 9ae5c50..bc7618d 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -163,7 +163,6 @@
     "//ios/chrome/browser/ui/infobars:unit_tests",
     "//ios/chrome/browser/ui/keyboard:unit_tests",
     "//ios/chrome/browser/ui/main:unit_tests",
-    "//ios/chrome/browser/ui/no_tabs:unit_tests",
     "//ios/chrome/browser/ui/ntp:unit_tests",
     "//ios/chrome/browser/ui/omnibox:unit_tests",
     "//ios/chrome/browser/ui/promos:unit_tests",
diff --git a/ios/chrome/test/app/tab_test_util.mm b/ios/chrome/test/app/tab_test_util.mm
index b1fab0b..c75a4f2 100644
--- a/ios/chrome/test/app/tab_test_util.mm
+++ b/ios/chrome/test/app/tab_test_util.mm
@@ -160,7 +160,7 @@
   TabModel* tabModel = [[main_controller browserViewInformation] otrTabModel];
   DCHECK(tabModel);
   [tabModel closeAllTabs];
-  if (!IsIPadIdiom() || !experimental_flags::IsTabSwitcherEnabled()) {
+  if (!IsIPadIdiom()) {
     // If the OTR BVC is active, wait until it isn't (since all of the
     // tabs are now closed)
     testing::WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{
diff --git a/ios/features.gni b/ios/features.gni
new file mode 100644
index 0000000..050b0f81
--- /dev/null
+++ b/ios/features.gni
@@ -0,0 +1,10 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+  # Control whether cronet is build (this is usually set by the script
+  # components/cronet/tools/cr_cronet.py as cronet requires specific
+  # gn args to build correctly).
+  is_cronet_build = false
+}
diff --git a/ios/net/BUILD.gn b/ios/net/BUILD.gn
index 8a77282..7132276 100644
--- a/ios/net/BUILD.gn
+++ b/ios/net/BUILD.gn
@@ -2,10 +2,17 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
 import("//ios/build/config.gni")
+import("//ios/features.gni")
 import("//testing/test.gni")
 import("//url/features.gni")
 
+buildflag_header("ios_net_features") {
+  header = "ios_net_features.h"
+  flags = [ "CRONET_BUILD=$is_cronet_build" ]
+}
+
 group("all_tests") {
   testonly = true
   deps = [
@@ -15,6 +22,7 @@
 
 source_set("net") {
   deps = [
+    ":ios_net_features",
     "//base",
     "//net",
     "//url:url_features",
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index 9d5c944..68d11fe 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -28,6 +28,7 @@
 #include "ios/net/cookies/cookie_creation_time_manager.h"
 #include "ios/net/cookies/cookie_store_ios_client.h"
 #include "ios/net/cookies/system_cookie_util.h"
+#include "ios/net/ios_net_features.h"
 #import "net/base/mac/url_conversions.h"
 #include "net/cookies/cookie_util.h"
 #include "net/cookies/parsed_cookie.h"
@@ -175,11 +176,11 @@
   DCHECK(manager);
   base::Time created_a = manager->GetCreationTime(cookie_a);
   base::Time created_b = manager->GetCreationTime(cookie_b);
-#if !defined(CRNET)
+#if !BUILDFLAG(CRONET_BUILD)
   // CookieCreationTimeManager is returning creation times that are null.
-  // Since in CrNet, the cookie store is recreated on startup, let's suppress
+  // Since in Cronet, the cookie store is recreated on startup, let's suppress
   // this warning for now.
-  // TODO(huey): Instead of suppressing the warning, assign a creation time
+  // TODO(mef): Instead of suppressing the warning, assign a creation time
   // to cookies if one doesn't already exist.
   DLOG_IF(ERROR, created_a.is_null() || created_b.is_null())
       << "Cookie without creation date";
diff --git a/ios/web/navigation/navigation_manager_impl.mm b/ios/web/navigation/navigation_manager_impl.mm
index 0f5b9dcd..b246e7e1 100644
--- a/ios/web/navigation/navigation_manager_impl.mm
+++ b/ios/web/navigation/navigation_manager_impl.mm
@@ -32,10 +32,7 @@
   if (existing_url == new_url || !new_url.has_ref())
     return false;
 
-  url::Replacements<char> replacements;
-  replacements.ClearRef();
-  return existing_url.ReplaceComponents(replacements) ==
-         new_url.ReplaceComponents(replacements);
+  return existing_url.EqualsIgnoringRef(new_url);
 }
 
 }  // anonymous namespace
diff --git a/ios/web/payments/payment_request.cc b/ios/web/payments/payment_request.cc
index 383b2d0d..fdfdb56c 100644
--- a/ios/web/payments/payment_request.cc
+++ b/ios/web/payments/payment_request.cc
@@ -4,6 +4,7 @@
 
 #include "ios/web/public/payments/payment_request.h"
 
+#include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 
 namespace {
@@ -31,6 +32,7 @@
 static const char kMethodData[] = "methodData";
 static const char kMethodDataData[] = "data";
 static const char kMethodName[] = "methodName";
+static const char kPaymentCurrencyAmountCurrencySystem[] = "currencySystem";
 static const char kPaymentCurrencyAmountCurrency[] = "currency";
 static const char kPaymentCurrencyAmountValue[] = "value";
 static const char kPaymentDetails[] = "details";
@@ -146,7 +148,11 @@
   return true;
 }
 
-PaymentCurrencyAmount::PaymentCurrencyAmount() {}
+PaymentCurrencyAmount::PaymentCurrencyAmount()
+    // By default, the value is urn:iso:std:iso:4217 indicating that currency is
+    // defined by [ISO4217] (for example, USD for US Dollars).
+    : currency_system(base::ASCIIToUTF16("urn:iso:std:iso:4217")) {}
+
 PaymentCurrencyAmount::~PaymentCurrencyAmount() = default;
 
 bool PaymentCurrencyAmount::operator==(
@@ -161,8 +167,18 @@
 
 bool PaymentCurrencyAmount::FromDictionaryValue(
     const base::DictionaryValue& value) {
-  return value.GetString(kPaymentCurrencyAmountCurrency, &this->currency) &&
-         value.GetString(kPaymentCurrencyAmountValue, &this->value);
+  if (!value.GetString(kPaymentCurrencyAmountCurrency, &this->currency)) {
+    return false;
+  }
+
+  if (!value.GetString(kPaymentCurrencyAmountValue, &this->value)) {
+    return false;
+  }
+
+  // Currency_system is optional
+  value.GetString(kPaymentCurrencyAmountCurrencySystem, &this->currency_system);
+
+  return true;
 }
 
 PaymentItem::PaymentItem() : pending(false) {}
diff --git a/ios/web/payments/payment_request_unittest.cc b/ios/web/payments/payment_request_unittest.cc
index 2ac56c1..44962be 100644
--- a/ios/web/payments/payment_request_unittest.cc
+++ b/ios/web/payments/payment_request_unittest.cc
@@ -65,6 +65,11 @@
   EXPECT_TRUE(actual.FromDictionaryValue(amount_dict));
 
   EXPECT_EQ(expected, actual);
+
+  expected.currency_system = base::ASCIIToUTF16("urn:iso:std:iso:123456789");
+  amount_dict.SetString("currencySystem", "urn:iso:std:iso:123456789");
+  EXPECT_TRUE(actual.FromDictionaryValue(amount_dict));
+  EXPECT_EQ(expected, actual);
 }
 
 // Tests the failure case when populating a PaymentCurrencyAmount from a
diff --git a/ios/web/public/payments/payment_request.h b/ios/web/public/payments/payment_request.h
index 742c2d9e..c2a8baa 100644
--- a/ios/web/public/payments/payment_request.h
+++ b/ios/web/public/payments/payment_request.h
@@ -121,6 +121,10 @@
 
   // A string containing the decimal monetary value.
   base::string16 value;
+
+  // A URL that indicates the currency system that the currency identifier
+  // belongs to.
+  base::string16 currency_system;
 };
 
 // Information indicating what the payment request is for and the value asked
diff --git a/ios/web_view/internal/BUILD.gn b/ios/web_view/internal/BUILD.gn
index 496def8e..d5f4c6c 100644
--- a/ios/web_view/internal/BUILD.gn
+++ b/ios/web_view/internal/BUILD.gn
@@ -2,6 +2,26 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+source_set("internal_arc") {
+  visibility = [
+    "//ios/web_view",
+    "//ios/web_view/internal/*",
+  ]
+
+  sources = [
+    "criwv_web_view_configuration.mm",
+    "criwv_website_data_store.mm",
+    "criwv_website_data_store_internal.h",
+  ]
+
+  deps = [
+    "//ios/web/public/app",
+    "//ios/web_view/public",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
 source_set("internal") {
   visibility = [
     "//ios/web_view",
@@ -23,7 +43,6 @@
     "criwv_web_main_parts.h",
     "criwv_web_main_parts.mm",
     "criwv_web_view.mm",
-    "criwv_web_view_internal.h",
     "pref_names.cc",
     "pref_names.h",
   ]
@@ -44,5 +63,13 @@
     "//ui/base",
     "//url",
   ]
-  allow_circular_includes_from = [ "//ios/web_view/internal/translate" ]
+
+  public_deps = [
+    ":internal_arc",
+  ]
+
+  allow_circular_includes_from = [
+    ":internal_arc",
+    "//ios/web_view/internal/translate",
+  ]
 }
diff --git a/ios/web_view/internal/criwv.mm b/ios/web_view/internal/criwv.mm
index 0877ffbd..7906852 100644
--- a/ios/web_view/internal/criwv.mm
+++ b/ios/web_view/internal/criwv.mm
@@ -11,11 +11,11 @@
 #include "base/single_thread_task_runner.h"
 #include "ios/web/public/app/web_main.h"
 #include "ios/web/public/web_thread.h"
-#include "ios/web_view/internal/criwv_browser_state.h"
-#import "ios/web_view/internal/criwv_web_client.h"
 #import "ios/web_view/internal/criwv_web_main_delegate.h"
-#import "ios/web_view/internal/criwv_web_view_internal.h"
 #import "ios/web_view/public/criwv_delegate.h"
+#import "ios/web_view/public/criwv_web_view.h"
+#import "ios/web_view/public/criwv_web_view_configuration.h"
+#import "ios/web_view/public/criwv_website_data_store.h"
 
 namespace {
 CRIWV* g_criwv = nil;
@@ -28,7 +28,6 @@
 }
 
 - (instancetype)initWithDelegate:(id<CRIWVDelegate>)delegate;
-- (ios_web_view::CRIWVBrowserState*)browserState;
 @end
 
 @implementation CRIWV
@@ -43,9 +42,12 @@
 }
 
 + (CRIWVWebView*)webViewWithFrame:(CGRect)frame {
-  return
-      [[[CRIWVWebView alloc] initWithFrame:frame
-                              browserState:[g_criwv browserState]] autorelease];
+  CRIWVWebViewConfiguration* configuration =
+      [[CRIWVWebViewConfiguration alloc] init];
+  configuration.websiteDataStore = [CRIWVWebsiteDataStore defaultDataStore];
+
+  return [[[CRIWVWebView alloc] initWithFrame:frame configuration:configuration]
+      autorelease];
 }
 
 - (instancetype)initWithDelegate:(id<CRIWVDelegate>)delegate {
@@ -65,10 +67,4 @@
   [super dealloc];
 }
 
-- (ios_web_view::CRIWVBrowserState*)browserState {
-  ios_web_view::CRIWVWebClient* client =
-      static_cast<ios_web_view::CRIWVWebClient*>(web::GetWebClient());
-  return client->browser_state();
-}
-
 @end
diff --git a/ios/web_view/internal/criwv_browser_state.h b/ios/web_view/internal/criwv_browser_state.h
index 636a200e..9851667 100644
--- a/ios/web_view/internal/criwv_browser_state.h
+++ b/ios/web_view/internal/criwv_browser_state.h
@@ -24,7 +24,7 @@
 // CRIWV implementation of BrowserState.  Can only be called from the UI thread.
 class CRIWVBrowserState : public web::BrowserState {
  public:
-  CRIWVBrowserState();
+  explicit CRIWVBrowserState(bool off_the_record);
   ~CRIWVBrowserState() override;
 
   // web::BrowserState implementation.
@@ -45,6 +45,9 @@
   // The path associated with this BrowserState object.
   base::FilePath path_;
 
+  // Whether this BrowserState is incognito.
+  bool off_the_record_;
+
   // The request context getter for this BrowserState object.
   scoped_refptr<CRIWVURLRequestContextGetter> request_context_getter_;
 
diff --git a/ios/web_view/internal/criwv_browser_state.mm b/ios/web_view/internal/criwv_browser_state.mm
index 5833f99..4c4f16a 100644
--- a/ios/web_view/internal/criwv_browser_state.mm
+++ b/ios/web_view/internal/criwv_browser_state.mm
@@ -28,7 +28,8 @@
 
 namespace ios_web_view {
 
-CRIWVBrowserState::CRIWVBrowserState() : web::BrowserState() {
+CRIWVBrowserState::CRIWVBrowserState(bool off_the_record)
+    : web::BrowserState(), off_the_record_(off_the_record) {
   CHECK(PathService::Get(base::DIR_APP_DATA, &path_));
 
   request_context_getter_ = new CRIWVURLRequestContextGetter(
@@ -67,7 +68,7 @@
 }
 
 bool CRIWVBrowserState::IsOffTheRecord() const {
-  return false;
+  return off_the_record_;
 }
 
 base::FilePath CRIWVBrowserState::GetStatePath() const {
diff --git a/ios/web_view/internal/criwv_web_client.h b/ios/web_view/internal/criwv_web_client.h
index 9c325ce..5364405 100644
--- a/ios/web_view/internal/criwv_web_client.h
+++ b/ios/web_view/internal/criwv_web_client.h
@@ -27,9 +27,10 @@
   std::string GetProduct() const override;
   std::string GetUserAgent(bool desktop_user_agent) const override;
 
-  // TODO(crbug.com/679895): Find a better way to get a BrowserState object to
-  // AppDelegate.
+  // Normal browser state associated with the receiver.
   CRIWVBrowserState* browser_state() const;
+  // Off the record browser state  associated with the receiver.
+  CRIWVBrowserState* off_the_record_browser_state() const;
 
  private:
   // This object's delegate.
diff --git a/ios/web_view/internal/criwv_web_client.mm b/ios/web_view/internal/criwv_web_client.mm
index 18239dd..b2945e42 100644
--- a/ios/web_view/internal/criwv_web_client.mm
+++ b/ios/web_view/internal/criwv_web_client.mm
@@ -26,6 +26,10 @@
   return web_main_parts_->browser_state();
 }
 
+CRIWVBrowserState* CRIWVWebClient::off_the_record_browser_state() const {
+  return web_main_parts_->off_the_record_browser_state();
+}
+
 std::string CRIWVWebClient::GetProduct() const {
   return base::SysNSStringToUTF8([delegate_ partialUserAgent]);
 }
diff --git a/ios/web_view/internal/criwv_web_main_parts.h b/ios/web_view/internal/criwv_web_main_parts.h
index 67f946b..dc4871c 100644
--- a/ios/web_view/internal/criwv_web_main_parts.h
+++ b/ios/web_view/internal/criwv_web_main_parts.h
@@ -26,12 +26,20 @@
   // Returns the CRIWVBrowserState for this embedder.
   CRIWVBrowserState* browser_state() const { return browser_state_.get(); }
 
+  // Returns the off the record CRIWVBrowserState for this embedder.
+  CRIWVBrowserState* off_the_record_browser_state() const {
+    return off_the_record_browser_state_.get();
+  }
+
  private:
   // This object's delegate.
   id<CRIWVDelegate> delegate_;
 
   // The BrowserState for this embedder.
   std::unique_ptr<CRIWVBrowserState> browser_state_;
+
+  // The BrowserState for this embedder.
+  std::unique_ptr<CRIWVBrowserState> off_the_record_browser_state_;
 };
 
 }  // namespace ios_web_view
diff --git a/ios/web_view/internal/criwv_web_main_parts.mm b/ios/web_view/internal/criwv_web_main_parts.mm
index b1ec766e..dd491d1 100644
--- a/ios/web_view/internal/criwv_web_main_parts.mm
+++ b/ios/web_view/internal/criwv_web_main_parts.mm
@@ -32,7 +32,8 @@
   ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
       pak_file, ui::SCALE_FACTOR_NONE);
 
-  browser_state_ = base::MakeUnique<CRIWVBrowserState>();
+  browser_state_ = base::MakeUnique<CRIWVBrowserState>(false);
+  off_the_record_browser_state_ = base::MakeUnique<CRIWVBrowserState>(true);
 
   // Initialize translate.
   translate::TranslateDownloadManager* download_manager =
diff --git a/ios/web_view/internal/criwv_web_view.mm b/ios/web_view/internal/criwv_web_view.mm
index 1fa2839..2317387 100644
--- a/ios/web_view/internal/criwv_web_view.mm
+++ b/ios/web_view/internal/criwv_web_view.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web_view/internal/criwv_web_view_internal.h"
+#import "ios/web_view/public/criwv_web_view.h"
 
 #include <memory>
 #include <utility>
@@ -17,15 +17,18 @@
 #import "ios/web/public/web_state/web_state_delegate_bridge.h"
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 #include "ios/web_view/internal/criwv_browser_state.h"
+#import "ios/web_view/internal/criwv_website_data_store_internal.h"
 #import "ios/web_view/internal/translate/criwv_translate_client.h"
+#import "ios/web_view/public/criwv_web_view_configuration.h"
 #import "ios/web_view/public/criwv_web_view_delegate.h"
+#import "ios/web_view/public/criwv_website_data_store.h"
 #import "net/base/mac/url_conversions.h"
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 
 @interface CRIWVWebView ()<CRWWebStateDelegate, CRWWebStateObserver> {
   id<CRIWVWebViewDelegate> _delegate;
-  ios_web_view::CRIWVBrowserState* _browserState;
+  CRIWVWebViewConfiguration* _configuration;
   std::unique_ptr<web::WebState> _webState;
   std::unique_ptr<web::WebStateDelegateBridge> _webStateDelegate;
   std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
@@ -40,12 +43,13 @@
 @synthesize loadProgress = _loadProgress;
 
 - (instancetype)initWithFrame:(CGRect)frame
-                 browserState:(ios_web_view::CRIWVBrowserState*)browserState {
+                configuration:(CRIWVWebViewConfiguration*)configuration {
   self = [super initWithFrame:frame];
   if (self) {
-    _browserState = browserState;
+    _configuration = [configuration copy];
 
-    web::WebState::CreateParams webStateCreateParams(_browserState);
+    web::WebState::CreateParams webStateCreateParams(
+        [configuration.websiteDataStore browserState]);
     _webState = web::WebState::Create(webStateCreateParams);
     _webState->SetWebUsageEnabled(true);
 
diff --git a/ios/web_view/internal/criwv_web_view_configuration.mm b/ios/web_view/internal/criwv_web_view_configuration.mm
new file mode 100644
index 0000000..8e9ee21
--- /dev/null
+++ b/ios/web_view/internal/criwv_web_view_configuration.mm
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web_view/public/criwv_web_view_configuration.h"
+
+#import "ios/web_view/public/criwv_website_data_store.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface CRIWVWebViewConfiguration ()
+// Initialize configuration with specified data store.
+- (instancetype)initWithDataStore:(CRIWVWebsiteDataStore*)dataStore;
+@end
+
+@implementation CRIWVWebViewConfiguration
+
+@synthesize websiteDataStore = _websiteDataStore;
+
+- (instancetype)init {
+  return [self initWithDataStore:[CRIWVWebsiteDataStore defaultDataStore]];
+}
+
+- (instancetype)initWithDataStore:(CRIWVWebsiteDataStore*)dataStore {
+  self = [super init];
+  if (self) {
+    _websiteDataStore = dataStore;
+  }
+  return self;
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone {
+  return
+      [[[self class] allocWithZone:zone] initWithDataStore:_websiteDataStore];
+}
+
+@end
diff --git a/ios/web_view/internal/criwv_web_view_internal.h b/ios/web_view/internal/criwv_web_view_internal.h
deleted file mode 100644
index ae11a88..0000000
--- a/ios/web_view/internal/criwv_web_view_internal.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 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 IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_VIEW_INTERNAL_H_
-#define IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_VIEW_INTERNAL_H_
-
-#import "ios/web_view/public/criwv_web_view.h"
-
-namespace ios_web_view {
-class CRIWVBrowserState;
-}
-
-@interface CRIWVWebView ()
-
-// |browserState| cannot be nil.
-- (instancetype)initWithFrame:(CGRect)frame
-                 browserState:(ios_web_view::CRIWVBrowserState*)browserState
-    NS_DESIGNATED_INITIALIZER;
-
-@end
-
-#endif  // IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_VIEW_INTERNAL_H_
diff --git a/ios/web_view/internal/criwv_website_data_store.mm b/ios/web_view/internal/criwv_website_data_store.mm
new file mode 100644
index 0000000..af9f59f1
--- /dev/null
+++ b/ios/web_view/internal/criwv_website_data_store.mm
@@ -0,0 +1,53 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web_view/internal/criwv_website_data_store_internal.h"
+
+#include <memory.h>
+
+#include "ios/web_view/internal/criwv_browser_state.h"
+#import "ios/web_view/internal/criwv_web_client.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation CRIWVWebsiteDataStore
+// TODO(crbug.com/690182): CRIWVWebsiteDataStore should own _browserState.
+ios_web_view::CRIWVBrowserState* _browserState;
+
+- (BOOL)isPersistent {
+  return !_browserState->IsOffTheRecord();
+}
+
+- (ios_web_view::CRIWVBrowserState*)browserState {
+  return _browserState;
+}
+
+- (void)setBrowserState:
+    (ios_web_view::CRIWVBrowserState* _Nonnull)browserState {
+  _browserState = browserState;
+}
+
++ (instancetype)defaultDataStore {
+  CRIWVWebsiteDataStore* dataStore = [[CRIWVWebsiteDataStore alloc] init];
+
+  ios_web_view::CRIWVWebClient* client =
+      static_cast<ios_web_view::CRIWVWebClient*>(web::GetWebClient());
+  [dataStore setBrowserState:client->browser_state()];
+
+  return dataStore;
+}
+
++ (instancetype)nonPersistentDataStore {
+  CRIWVWebsiteDataStore* dataStore = [[CRIWVWebsiteDataStore alloc] init];
+
+  ios_web_view::CRIWVWebClient* client =
+      static_cast<ios_web_view::CRIWVWebClient*>(web::GetWebClient());
+  [dataStore setBrowserState:client->off_the_record_browser_state()];
+
+  return dataStore;
+}
+
+@end
diff --git a/ios/web_view/internal/criwv_website_data_store_internal.h b/ios/web_view/internal/criwv_website_data_store_internal.h
new file mode 100644
index 0000000..045b514
--- /dev/null
+++ b/ios/web_view/internal/criwv_website_data_store_internal.h
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_VIEW_INTERNAL_CRIWV_WEBSITE_DATA_STORE_INTERNAL_H_
+#define IOS_WEB_VIEW_INTERNAL_CRIWV_WEBSITE_DATA_STORE_INTERNAL_H_
+
+#import "ios/web_view/public/criwv_website_data_store.h"
+
+namespace ios_web_view {
+class CRIWVBrowserState;
+}  // namespace ios_web_view
+
+@interface CRIWVWebsiteDataStore ()
+
+// The browser state associated with this website data store.
+@property(nonatomic, readonly, nonnull)
+    ios_web_view::CRIWVBrowserState* browserState;
+
+@end
+
+#endif  // IOS_WEB_VIEW_INTERNAL_CRIWV_WEBSITE_DATA_STORE_INTERNAL_H_
diff --git a/ios/web_view/public/BUILD.gn b/ios/web_view/public/BUILD.gn
index 8b3eb9f..33fc8d9 100644
--- a/ios/web_view/public/BUILD.gn
+++ b/ios/web_view/public/BUILD.gn
@@ -14,7 +14,9 @@
     "criwv_translate_delegate.h",
     "criwv_translate_manager.h",
     "criwv_web_view.h",
+    "criwv_web_view_configuration.h",
     "criwv_web_view_delegate.h",
+    "criwv_website_data_store.h",
   ]
 
   libs = [ "UIKit.framework" ]
diff --git a/ios/web_view/public/criwv_web_view.h b/ios/web_view/public/criwv_web_view.h
index 9ead24c..e5b4934 100644
--- a/ios/web_view/public/criwv_web_view.h
+++ b/ios/web_view/public/criwv_web_view.h
@@ -6,6 +6,7 @@
 
 #import <UIKit/UIKit.h>
 
+@class CRIWVWebViewConfiguration;
 @protocol CRIWVWebViewDelegate;
 
 // A web view component (like WKWebView) which uses iOS Chromium's web view
@@ -40,6 +41,11 @@
 // undefined if the web view is not currently loading.
 @property(nonatomic, readonly) CGFloat loadProgress;
 
+// |configuration| must not be null
+- (instancetype)initWithFrame:(CGRect)frame
+                configuration:(CRIWVWebViewConfiguration*)configuration
+    NS_DESIGNATED_INITIALIZER;
+
 - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
 
diff --git a/ios/web_view/public/criwv_web_view_configuration.h b/ios/web_view/public/criwv_web_view_configuration.h
new file mode 100644
index 0000000..54a55b9
--- /dev/null
+++ b/ios/web_view/public/criwv_web_view_configuration.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_CONFIGURATION_H_
+#define IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_CONFIGURATION_H_
+
+#import <Foundation/Foundation.h>
+
+@class CRIWVWebsiteDataStore;
+
+// Configuration used for creation of a CRIWVWebView.
+@interface CRIWVWebViewConfiguration : NSObject<NSCopying>
+
+// Data store defining persistance of website data. Default is
+// [CRIWVWebsiteDataStore defaultDataStore].
+@property(nonatomic, strong, nonnull) CRIWVWebsiteDataStore* websiteDataStore;
+
+@end
+
+#endif  // IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_CONFIGURATION_H_
diff --git a/ios/web_view/public/criwv_website_data_store.h b/ios/web_view/public/criwv_website_data_store.h
new file mode 100644
index 0000000..7bb06dc
--- /dev/null
+++ b/ios/web_view/public/criwv_website_data_store.h
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_VIEW_PUBLIC_CRIWV_WEBSITE_DATA_STORE_H_
+#define IOS_WEB_VIEW_PUBLIC_CRIWV_WEBSITE_DATA_STORE_H_
+
+#import <Foundation/Foundation.h>
+
+// Controls persistence of website data such as cookies, caches, and local
+// storage.
+@interface CRIWVWebsiteDataStore : NSObject
+
+// Whether or not this data store persists data to disk.
+@property(readonly, getter=isPersistent) BOOL persistent;
+
+// Persistent data store which stores all data on disk.
++ (instancetype)defaultDataStore;
+// Ephemeral data store that never stores data on disk.
++ (instancetype)nonPersistentDataStore;
+
+@end
+
+#endif  // IOS_WEB_VIEW_PUBLIC_CRIWV_WEBSITE_DATA_STORE_H_
diff --git a/media/PRESUBMIT.py b/media/PRESUBMIT.py
index 830c3fc..993de38 100644
--- a/media/PRESUBMIT.py
+++ b/media/PRESUBMIT.py
@@ -172,7 +172,6 @@
   results.extend(_CheckForUseOfWrongClock(input_api, output_api))
   results.extend(_CheckPassByValue(input_api, output_api))
   results.extend(_CheckForHistogramOffByOne(input_api, output_api))
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
 
 
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 2952088..c5e6879 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -93,8 +93,6 @@
     "audio_power_monitor.cc",
     "audio_power_monitor.h",
     "audio_source_diverter.h",
-    "audio_streams_tracker.cc",
-    "audio_streams_tracker.h",
     "audio_system.h",
     "audio_system_impl.cc",
     "audio_system_impl.h",
@@ -311,7 +309,6 @@
     "audio_output_device_unittest.cc",
     "audio_output_proxy_unittest.cc",
     "audio_power_monitor_unittest.cc",
-    "audio_streams_tracker_unittest.cc",
     "audio_system_impl_unittest.cc",
     "fake_audio_worker_unittest.cc",
     "simple_sources_unittest.cc",
diff --git a/media/audio/audio_streams_tracker.cc b/media/audio/audio_streams_tracker.cc
deleted file mode 100644
index 5363796..0000000
--- a/media/audio/audio_streams_tracker.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 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 "media/audio/audio_streams_tracker.h"
-
-#include <limits>
-
-namespace media {
-
-AudioStreamsTracker::AudioStreamsTracker()
-    : current_stream_count_(0), max_stream_count_(0) {
-  thread_checker_.DetachFromThread();
-}
-
-AudioStreamsTracker::~AudioStreamsTracker() {
-  DCHECK_EQ(current_stream_count_, 0u);
-}
-
-void AudioStreamsTracker::IncreaseStreamCount() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_NE(current_stream_count_, std::numeric_limits<size_t>::max());
-  ++current_stream_count_;
-  if (current_stream_count_ > max_stream_count_)
-    max_stream_count_ = current_stream_count_;
-}
-
-void AudioStreamsTracker::DecreaseStreamCount(size_t count) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_GE(current_stream_count_, count);
-  current_stream_count_ -= count;
-}
-
-void AudioStreamsTracker::ResetMaxStreamCount() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  max_stream_count_ = current_stream_count_;
-}
-
-size_t AudioStreamsTracker::max_stream_count() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return max_stream_count_;
-}
-
-}  // namespace media
diff --git a/media/audio/audio_streams_tracker.h b/media/audio/audio_streams_tracker.h
deleted file mode 100644
index 1071fd7..0000000
--- a/media/audio/audio_streams_tracker.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 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 MEDIA_AUDIO_AUDIO_STREAMS_TRACKER_H_
-#define MEDIA_AUDIO_AUDIO_STREAMS_TRACKER_H_
-
-#include <stddef.h>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "media/base/media_export.h"
-
-namespace media {
-
-// Tracks the maximum number of simultaneous streams that was ever registered.
-// All functions must be called on the same thread.
-class MEDIA_EXPORT AudioStreamsTracker {
- public:
-  AudioStreamsTracker();
-  ~AudioStreamsTracker();
-
-  // Increases/decreases current stream count. Updates max stream count if
-  // current count is larger.
-  void IncreaseStreamCount();
-  void DecreaseStreamCount(size_t count = 1);
-
-  // Resets the max stream count, i.e. sets it to the current stream count.
-  void ResetMaxStreamCount();
-
-  size_t max_stream_count() const;
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(AudioStreamsTrackerTest, IncreaseAndDecreaseOnce);
-  FRIEND_TEST_ALL_PREFIXES(AudioStreamsTrackerTest,
-                           IncreaseAndDecreaseMultiple);
-
-  // Confirms single-threaded access.
-  base::ThreadChecker thread_checker_;
-
-  // Stores the current and maximum number of streams.
-  size_t current_stream_count_;
-  size_t max_stream_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(AudioStreamsTracker);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_AUDIO_AUDIO_STREAMS_TRACKER_H_
diff --git a/media/audio/audio_streams_tracker_unittest.cc b/media/audio/audio_streams_tracker_unittest.cc
deleted file mode 100644
index f42142be..0000000
--- a/media/audio/audio_streams_tracker_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2015 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 "media/audio/audio_streams_tracker.h"
-
-#include <stddef.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace media {
-
-TEST(AudioStreamsTrackerTest, IncreaseAndDecreaseOnce) {
-  AudioStreamsTracker audio_streams_tracker;
-  const size_t kNumberOfOperations = 5;
-
-  // Increase count.
-  for (size_t i = 1; i <= kNumberOfOperations; ++i) {
-    audio_streams_tracker.IncreaseStreamCount();
-    EXPECT_EQ(i, audio_streams_tracker.current_stream_count_);
-    EXPECT_EQ(i, audio_streams_tracker.max_stream_count());
-  }
-
-  // Reset and check max count.
-  audio_streams_tracker.ResetMaxStreamCount();
-  EXPECT_EQ(kNumberOfOperations, audio_streams_tracker.max_stream_count());
-
-  // Decrease count.
-  for (size_t i = 1; i <= kNumberOfOperations; ++i) {
-    audio_streams_tracker.DecreaseStreamCount();
-    EXPECT_EQ(kNumberOfOperations - i,
-              audio_streams_tracker.current_stream_count_);
-    EXPECT_EQ(kNumberOfOperations, audio_streams_tracker.max_stream_count());
-  }
-
-  // Reset and check max count.
-  audio_streams_tracker.ResetMaxStreamCount();
-  EXPECT_EQ(0u, audio_streams_tracker.max_stream_count());
-}
-
-TEST(AudioStreamsTrackerTest, IncreaseAndDecreaseMultiple) {
-  AudioStreamsTracker audio_streams_tracker;
-  const size_t kNumberOfOperations = 5;
-
-  // Increase 2N (N = kNumberOfOperations).
-  for (size_t i = 1; i <= 2 * kNumberOfOperations; ++i) {
-    audio_streams_tracker.IncreaseStreamCount();
-    EXPECT_EQ(i, audio_streams_tracker.current_stream_count_);
-    EXPECT_EQ(i, audio_streams_tracker.max_stream_count());
-  }
-
-  // Decrease N.
-  for (size_t i = 1; i <= kNumberOfOperations; ++i) {
-    audio_streams_tracker.DecreaseStreamCount();
-    EXPECT_EQ(2 * kNumberOfOperations - i,
-              audio_streams_tracker.current_stream_count_);
-    EXPECT_EQ(2 * kNumberOfOperations,
-              audio_streams_tracker.max_stream_count());
-  }
-
-  // Reset and check max count.
-  audio_streams_tracker.ResetMaxStreamCount();
-  EXPECT_EQ(kNumberOfOperations, audio_streams_tracker.max_stream_count());
-
-  // Increase 2N.
-  for (size_t i = 1; i <= 2 * kNumberOfOperations; ++i) {
-    audio_streams_tracker.IncreaseStreamCount();
-    EXPECT_EQ(kNumberOfOperations + i,
-              audio_streams_tracker.current_stream_count_);
-    EXPECT_EQ(kNumberOfOperations + i,
-              audio_streams_tracker.max_stream_count());
-  }
-
-  // Decrease N.
-  for (size_t i = 1; i <= kNumberOfOperations; ++i) {
-    audio_streams_tracker.DecreaseStreamCount();
-    EXPECT_EQ(3 * kNumberOfOperations - i,
-              audio_streams_tracker.current_stream_count_);
-    EXPECT_EQ(3 * kNumberOfOperations,
-              audio_streams_tracker.max_stream_count());
-  }
-
-  // Reset and check max count.
-  audio_streams_tracker.ResetMaxStreamCount();
-  EXPECT_EQ(2 * kNumberOfOperations, audio_streams_tracker.max_stream_count());
-
-  // Decrease 2N.
-  for (size_t i = 1; i <= 2 * kNumberOfOperations; ++i) {
-    audio_streams_tracker.DecreaseStreamCount();
-    EXPECT_EQ(2 * kNumberOfOperations - i,
-              audio_streams_tracker.current_stream_count_);
-    EXPECT_EQ(2 * kNumberOfOperations,
-              audio_streams_tracker.max_stream_count());
-  }
-
-  // Reset and check max count.
-  audio_streams_tracker.ResetMaxStreamCount();
-  EXPECT_EQ(0u, audio_streams_tracker.max_stream_count());
-}
-
-}  // namespace media
diff --git a/mojo/public/cpp/bindings/associated_binding_set.h b/mojo/public/cpp/bindings/associated_binding_set.h
index b150223..34ab88d6e 100644
--- a/mojo/public/cpp/bindings/associated_binding_set.h
+++ b/mojo/public/cpp/bindings/associated_binding_set.h
@@ -18,9 +18,9 @@
   using RequestType = AssociatedInterfaceRequest<Interface>;
 };
 
-template <typename Interface>
+template <typename Interface, typename ContextType = void>
 using AssociatedBindingSet =
-    BindingSet<Interface, AssociatedBinding<Interface>>;
+    BindingSetBase<Interface, AssociatedBinding<Interface>, ContextType>;
 
 }  // namespace mojo
 
diff --git a/mojo/public/cpp/bindings/binding_set.h b/mojo/public/cpp/bindings/binding_set.h
index 3c087c2..5156995 100644
--- a/mojo/public/cpp/bindings/binding_set.h
+++ b/mojo/public/cpp/bindings/binding_set.h
@@ -33,31 +33,42 @@
   }
 };
 
-enum class BindingSetDispatchMode {
-  WITHOUT_CONTEXT,
-  WITH_CONTEXT,
-};
-
 using BindingId = size_t;
 
-// Use this class to manage a set of bindings, which are automatically destroyed
-// and removed from the set when the pipe they are bound to is disconnected.
-template <typename Interface, typename BindingType = Binding<Interface>>
-class BindingSet {
+template <typename ContextType>
+struct BindingSetContextTraits {
+  using Type = ContextType;
+
+  static constexpr bool SupportsContext() { return true; }
+};
+
+template <>
+struct BindingSetContextTraits<void> {
+  // NOTE: This choice of Type only matters insofar as it affects the size of
+  // the |context_| field of a BindingSetBase::Entry with void context. The
+  // context value is never used in this case.
+  using Type = bool;
+
+  static constexpr bool SupportsContext() { return false; }
+};
+
+// Generic definition used for BindingSet and AssociatedBindingSet to own a
+// collection of bindings which point to the same implementation.
+//
+// If |ContextType| is non-void, then every added binding must include a context
+// value of that type, and |dispatch_context()| will return that value during
+// the extent of any message dispatch targeting that specific binding.
+template <typename Interface, typename BindingType, typename ContextType>
+class BindingSetBase {
  public:
-  using PreDispatchCallback = base::Callback<void(void*)>;
+  using ContextTraits = BindingSetContextTraits<ContextType>;
+  using Context = typename ContextTraits::Type;
+  using PreDispatchCallback = base::Callback<void(const Context&)>;
   using Traits = BindingSetTraits<BindingType>;
   using ProxyType = typename Traits::ProxyType;
   using RequestType = typename Traits::RequestType;
 
-  BindingSet() : BindingSet(BindingSetDispatchMode::WITHOUT_CONTEXT) {}
-
-  // Constructs a new BindingSet operating in |dispatch_mode|. If |WITH_CONTEXT|
-  // is used, AddBinding() supports a |context| argument, and dispatch_context()
-  // may be called during message or error dispatch to identify which specific
-  // binding received the message or error.
-  explicit BindingSet(BindingSetDispatchMode dispatch_mode)
-      : dispatch_mode_(dispatch_mode) {}
+  BindingSetBase() {}
 
   void set_connection_error_handler(const base::Closure& error_handler) {
     error_handler_ = error_handler;
@@ -72,29 +83,26 @@
 
   // Sets a callback to be invoked immediately before dispatching any message or
   // error received by any of the bindings in the set. This may only be used
-  // if the set was constructed with |BindingSetDispatchMode::WITH_CONTEXT|.
-  // |handler| is passed the context associated with the binding which received
-  // the message or event about to be dispatched.
+  // with a non-void |ContextType|.
   void set_pre_dispatch_handler(const PreDispatchCallback& handler) {
-    DCHECK(SupportsContext());
+    static_assert(ContextTraits::SupportsContext(),
+                  "Pre-dispatch handler usage requires non-void context type.");
     pre_dispatch_handler_ = handler;
   }
 
-  // Adds a new binding to the set which binds |request| to |impl|. If |context|
-  // is non-null, dispatch_context() will reflect this value during the extent
-  // of any message or error dispatch targeting this specific binding. Note that
-  // |context| may only be non-null if the BindingSet was constructed with
-  // |BindingSetDispatchMode::WITH_CONTEXT|.
-  BindingId AddBinding(Interface* impl,
-                     RequestType request,
-                     void* context = nullptr) {
-    DCHECK(!context || SupportsContext());
-    BindingId id = next_binding_id_++;
-    DCHECK_GE(next_binding_id_, 0u);
-    std::unique_ptr<Entry> entry =
-        base::MakeUnique<Entry>(impl, std::move(request), this, id, context);
-    bindings_.insert(std::make_pair(id, std::move(entry)));
-    return id;
+  // Adds a new binding to the set which binds |request| to |impl| with no
+  // additional context.
+  BindingId AddBinding(Interface* impl, RequestType request) {
+    static_assert(!ContextTraits::SupportsContext(),
+                  "Context value required for non-void context type.");
+    return AddBindingImpl(impl, std::move(request), false);
+  }
+
+  // Adds a new binding associated with |context|.
+  BindingId AddBinding(Interface* impl, RequestType request, Context context) {
+    static_assert(ContextTraits::SupportsContext(),
+                  "Context value unsupported for void context type.");
+    return AddBindingImpl(impl, std::move(request), std::move(context));
   }
 
   // Removes a binding from the set. Note that this is safe to call even if the
@@ -129,12 +137,11 @@
   // error. During the extent of message or error dispatch, this will return the
   // context associated with the specific binding which received the message or
   // error. Use AddBinding() to associated a context with a specific binding.
-  //
-  // Note that this may ONLY be called if the BindingSet was constructed with
-  // |BindingSetDispatchMode::WITH_CONTEXT|.
-  void* dispatch_context() const {
-    DCHECK(SupportsContext());
-    return dispatch_context_;
+  const Context& dispatch_context() const {
+    static_assert(ContextTraits::SupportsContext(),
+                  "dispatch_context() requires non-void context type.");
+    DCHECK(dispatch_context_);
+    return *dispatch_context_;
   }
 
   void FlushForTesting() {
@@ -149,14 +156,14 @@
    public:
     Entry(Interface* impl,
           RequestType request,
-          BindingSet* binding_set,
+          BindingSetBase* binding_set,
           BindingId binding_id,
-          void* context)
+          Context context)
         : binding_(impl, std::move(request)),
           binding_set_(binding_set),
           binding_id_(binding_id),
-          context_(context) {
-      if (binding_set->SupportsContext())
+          context_(std::move(context)) {
+      if (ContextTraits::SupportsContext())
         binding_.AddFilter(base::MakeUnique<DispatchFilter>(this));
       binding_.set_connection_error_with_reason_handler(
           base::Bind(&Entry::OnConnectionError, base::Unretained(this)));
@@ -183,34 +190,41 @@
     };
 
     void WillDispatch() {
-      DCHECK(binding_set_->SupportsContext());
-      binding_set_->SetDispatchContext(context_);
+      DCHECK(ContextTraits::SupportsContext());
+      binding_set_->SetDispatchContext(&context_);
     }
 
     void OnConnectionError(uint32_t custom_reason,
                            const std::string& description) {
-      if (binding_set_->SupportsContext())
+      if (ContextTraits::SupportsContext())
         WillDispatch();
       binding_set_->OnConnectionError(binding_id_, custom_reason, description);
     }
 
     BindingType binding_;
-    BindingSet* const binding_set_;
+    BindingSetBase* const binding_set_;
     const BindingId binding_id_;
-    void* const context_;
+    Context const context_;
 
     DISALLOW_COPY_AND_ASSIGN(Entry);
   };
 
-  void SetDispatchContext(void* context) {
-    DCHECK(SupportsContext());
+  void SetDispatchContext(const Context* context) {
+    DCHECK(ContextTraits::SupportsContext());
     dispatch_context_ = context;
     if (!pre_dispatch_handler_.is_null())
-      pre_dispatch_handler_.Run(context);
+      pre_dispatch_handler_.Run(*context);
   }
 
-  bool SupportsContext() const {
-    return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT;
+  BindingId AddBindingImpl(Interface* impl,
+                           RequestType request,
+                           Context context) {
+    BindingId id = next_binding_id_++;
+    DCHECK_GE(next_binding_id_, 0u);
+    auto entry = base::MakeUnique<Entry>(
+        impl, std::move(request), this, id, std::move(context));
+    bindings_.insert(std::make_pair(id, std::move(entry)));
+    return id;
   }
 
   void OnConnectionError(BindingId id,
@@ -218,6 +232,9 @@
                          const std::string& description) {
     auto it = bindings_.find(id);
     DCHECK(it != bindings_.end());
+
+    // We keep the Entry alive throughout error dispatch.
+    std::unique_ptr<Entry> entry = std::move(it->second);
     bindings_.erase(it);
 
     if (!error_handler_.is_null())
@@ -226,17 +243,19 @@
       error_with_reason_handler_.Run(custom_reason, description);
   }
 
-  BindingSetDispatchMode dispatch_mode_;
   base::Closure error_handler_;
   ConnectionErrorWithReasonCallback error_with_reason_handler_;
   PreDispatchCallback pre_dispatch_handler_;
   BindingId next_binding_id_ = 0;
   std::map<BindingId, std::unique_ptr<Entry>> bindings_;
-  void* dispatch_context_ = nullptr;
+  const Context* dispatch_context_ = nullptr;
 
-  DISALLOW_COPY_AND_ASSIGN(BindingSet);
+  DISALLOW_COPY_AND_ASSIGN(BindingSetBase);
 };
 
+template <typename Interface, typename ContextType = void>
+using BindingSet = BindingSetBase<Interface, Binding<Interface>, ContextType>;
+
 }  // namespace mojo
 
 #endif  // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
diff --git a/mojo/public/cpp/bindings/sync_call_restrictions.h b/mojo/public/cpp/bindings/sync_call_restrictions.h
index ee7f006d..39a77a85 100644
--- a/mojo/public/cpp/bindings/sync_call_restrictions.h
+++ b/mojo/public/cpp/bindings/sync_call_restrictions.h
@@ -15,6 +15,10 @@
 #define ENABLE_SYNC_CALL_RESTRICTIONS 0
 #endif
 
+namespace leveldb {
+class LevelDBMojoProxy;
+}
+
 namespace ui {
 class Gpu;
 }
@@ -52,6 +56,8 @@
   // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to mojo/OWNERS first.
   // BEGIN ALLOWED USAGE.
   friend class ui::Gpu;  // http://crbug.com/620058
+  // LevelDBMojoProxy makes same-process sync calls from the DB thread.
+  friend class leveldb::LevelDBMojoProxy;
   // END ALLOWED USAGE.
 
   // BEGIN USAGE THAT NEEDS TO BE FIXED.
diff --git a/mojo/public/cpp/bindings/tests/binding_set_unittest.cc b/mojo/public/cpp/bindings/tests/binding_set_unittest.cc
index b34c70b..790671a 100644
--- a/mojo/public/cpp/bindings/tests/binding_set_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/binding_set_unittest.cc
@@ -30,16 +30,18 @@
   DISALLOW_COPY_AND_ASSIGN(BindingSetTest);
 };
 
-template <typename BindingSetType>
-void ExpectContextHelper(BindingSetType* binding_set, void* expected_context) {
+template <typename BindingSetType, typename ContextType>
+void ExpectContextHelper(BindingSetType* binding_set,
+                         ContextType expected_context) {
   EXPECT_EQ(expected_context, binding_set->dispatch_context());
 }
 
-template <typename BindingSetType>
+template <typename BindingSetType, typename ContextType>
 base::Closure ExpectContext(BindingSetType* binding_set,
-                            void* expected_context) {
+                            ContextType expected_context) {
   return base::Bind(
-      &ExpectContextHelper<BindingSetType>, binding_set, expected_context);
+      &ExpectContextHelper<BindingSetType, ContextType>, binding_set,
+      expected_context);
 }
 
 base::Closure Sequence(const base::Closure& first,
@@ -74,23 +76,20 @@
 TEST_F(BindingSetTest, BindingSetContext) {
   PingImpl impl;
 
-  void* context_a = reinterpret_cast<void*>(1);
-  void* context_b = reinterpret_cast<void*>(2);
-
-  BindingSet<PingService> bindings_(BindingSetDispatchMode::WITH_CONTEXT);
+  BindingSet<PingService, int> bindings;
   PingServicePtr ping_a, ping_b;
-  bindings_.AddBinding(&impl, MakeRequest(&ping_a), context_a);
-  bindings_.AddBinding(&impl, MakeRequest(&ping_b), context_b);
+  bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
+  bindings.AddBinding(&impl, MakeRequest(&ping_b), 2);
 
   {
-    impl.set_ping_handler(ExpectContext(&bindings_, context_a));
+    impl.set_ping_handler(ExpectContext(&bindings, 1));
     base::RunLoop loop;
     ping_a->Ping(loop.QuitClosure());
     loop.Run();
   }
 
   {
-    impl.set_ping_handler(ExpectContext(&bindings_, context_b));
+    impl.set_ping_handler(ExpectContext(&bindings, 2));
     base::RunLoop loop;
     ping_b->Ping(loop.QuitClosure());
     loop.Run();
@@ -98,21 +97,21 @@
 
   {
     base::RunLoop loop;
-    bindings_.set_connection_error_handler(
-        Sequence(ExpectContext(&bindings_, context_a), loop.QuitClosure()));
+    bindings.set_connection_error_handler(
+        Sequence(ExpectContext(&bindings, 1), loop.QuitClosure()));
     ping_a.reset();
     loop.Run();
   }
 
   {
     base::RunLoop loop;
-    bindings_.set_connection_error_handler(
-        Sequence(ExpectContext(&bindings_, context_b), loop.QuitClosure()));
+    bindings.set_connection_error_handler(
+        Sequence(ExpectContext(&bindings, 2), loop.QuitClosure()));
     ping_b.reset();
     loop.Run();
   }
 
-  EXPECT_TRUE(bindings_.empty());
+  EXPECT_TRUE(bindings.empty());
 }
 
 TEST_F(BindingSetTest, BindingSetConnectionErrorWithReason) {
@@ -136,10 +135,10 @@
 
 class PingProviderImpl : public AssociatedPingProvider, public PingService {
  public:
-  PingProviderImpl() : ping_bindings_(BindingSetDispatchMode::WITH_CONTEXT) {}
+  PingProviderImpl() {}
   ~PingProviderImpl() override {}
 
-  void set_new_ping_context(void* context) { new_ping_context_ = context; }
+  void set_new_ping_context(int context) { new_ping_context_ = context; }
 
   void set_new_ping_handler(const base::Closure& handler) {
     new_ping_handler_ = handler;
@@ -149,7 +148,9 @@
     ping_handler_ = handler;
   }
 
-  AssociatedBindingSet<PingService>& ping_bindings() { return ping_bindings_; }
+  AssociatedBindingSet<PingService, int>& ping_bindings() {
+    return ping_bindings_;
+  }
 
  private:
   // AssociatedPingProvider:
@@ -166,8 +167,8 @@
     callback.Run();
   }
 
-  AssociatedBindingSet<PingService> ping_bindings_;
-  void* new_ping_context_ = nullptr;
+  AssociatedBindingSet<PingService, int> ping_bindings_;
+  int new_ping_context_ = -1;
   base::Closure ping_handler_;
   base::Closure new_ping_handler_;
 };
@@ -177,13 +178,10 @@
   PingProviderImpl impl;
   Binding<AssociatedPingProvider> binding(&impl, MakeRequest(&provider));
 
-  void* context_a = reinterpret_cast<void*>(1);
-  void* context_b = reinterpret_cast<void*>(2);
-
   PingServiceAssociatedPtr ping_a;
   {
     base::RunLoop loop;
-    impl.set_new_ping_context(context_a);
+    impl.set_new_ping_context(1);
     impl.set_new_ping_handler(loop.QuitClosure());
     provider->GetPing(MakeRequest(&ping_a, provider.associated_group()));
     loop.Run();
@@ -192,21 +190,21 @@
   PingServiceAssociatedPtr ping_b;
   {
     base::RunLoop loop;
-    impl.set_new_ping_context(context_b);
+    impl.set_new_ping_context(2);
     impl.set_new_ping_handler(loop.QuitClosure());
     provider->GetPing(MakeRequest(&ping_b, provider.associated_group()));
     loop.Run();
   }
 
   {
-    impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), context_a));
+    impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), 1));
     base::RunLoop loop;
     ping_a->Ping(loop.QuitClosure());
     loop.Run();
   }
 
   {
-    impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), context_b));
+    impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), 2));
     base::RunLoop loop;
     ping_b->Ping(loop.QuitClosure());
     loop.Run();
@@ -215,8 +213,7 @@
   {
     base::RunLoop loop;
     impl.ping_bindings().set_connection_error_handler(
-        Sequence(ExpectContext(&impl.ping_bindings(), context_a),
-                 loop.QuitClosure()));
+        Sequence(ExpectContext(&impl.ping_bindings(), 1), loop.QuitClosure()));
     ping_a.reset();
     loop.Run();
   }
@@ -224,8 +221,7 @@
   {
     base::RunLoop loop;
     impl.ping_bindings().set_connection_error_handler(
-        Sequence(ExpectContext(&impl.ping_bindings(), context_b),
-                 loop.QuitClosure()));
+        Sequence(ExpectContext(&impl.ping_bindings(), 2), loop.QuitClosure()));
     ping_b.reset();
     loop.Run();
   }
@@ -236,20 +232,16 @@
 TEST_F(BindingSetTest, MasterInterfaceBindingSetContext) {
   AssociatedPingProviderPtr provider_a, provider_b;
   PingProviderImpl impl;
-  BindingSet<AssociatedPingProvider> bindings(
-      BindingSetDispatchMode::WITH_CONTEXT);
+  BindingSet<AssociatedPingProvider, int> bindings;
 
-  void* context_a = reinterpret_cast<void*>(1);
-  void* context_b = reinterpret_cast<void*>(2);
-
-  bindings.AddBinding(&impl, MakeRequest(&provider_a), context_a);
-  bindings.AddBinding(&impl, MakeRequest(&provider_b), context_b);
+  bindings.AddBinding(&impl, MakeRequest(&provider_a), 1);
+  bindings.AddBinding(&impl, MakeRequest(&provider_b), 2);
 
   {
     PingServiceAssociatedPtr ping;
     base::RunLoop loop;
     impl.set_new_ping_handler(
-        Sequence(ExpectContext(&bindings, context_a), loop.QuitClosure()));
+        Sequence(ExpectContext(&bindings, 1), loop.QuitClosure()));
     provider_a->GetPing(MakeRequest(&ping, provider_a.associated_group()));
     loop.Run();
   }
@@ -258,7 +250,7 @@
     PingServiceAssociatedPtr ping;
     base::RunLoop loop;
     impl.set_new_ping_handler(
-        Sequence(ExpectContext(&bindings, context_b), loop.QuitClosure()));
+        Sequence(ExpectContext(&bindings, 2), loop.QuitClosure()));
     provider_b->GetPing(MakeRequest(&ping, provider_b.associated_group()));
     loop.Run();
   }
@@ -266,7 +258,7 @@
   {
     base::RunLoop loop;
     bindings.set_connection_error_handler(
-        Sequence(ExpectContext(&bindings, context_a), loop.QuitClosure()));
+        Sequence(ExpectContext(&bindings, 1), loop.QuitClosure()));
     provider_a.reset();
     loop.Run();
   }
@@ -274,7 +266,7 @@
   {
     base::RunLoop loop;
     bindings.set_connection_error_handler(
-        Sequence(ExpectContext(&bindings, context_b), loop.QuitClosure()));
+        Sequence(ExpectContext(&bindings, 2), loop.QuitClosure()));
     provider_b.reset();
     loop.Run();
   }
@@ -282,6 +274,57 @@
   EXPECT_TRUE(bindings.empty());
 }
 
+TEST_F(BindingSetTest, PreDispatchHandler) {
+  PingImpl impl;
+
+  BindingSet<PingService, int> bindings;
+  PingServicePtr ping_a, ping_b;
+  bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
+  bindings.AddBinding(&impl, MakeRequest(&ping_b), 2);
+
+  {
+    bindings.set_pre_dispatch_handler(base::Bind([] (const int& context) {
+      EXPECT_EQ(1, context);
+    }));
+    base::RunLoop loop;
+    ping_a->Ping(loop.QuitClosure());
+    loop.Run();
+  }
+
+  {
+    bindings.set_pre_dispatch_handler(base::Bind([] (const int& context) {
+      EXPECT_EQ(2, context);
+    }));
+    base::RunLoop loop;
+    ping_b->Ping(loop.QuitClosure());
+    loop.Run();
+  }
+
+  {
+    base::RunLoop loop;
+    bindings.set_pre_dispatch_handler(
+        base::Bind([](base::RunLoop* loop, const int& context) {
+          EXPECT_EQ(1, context);
+          loop->Quit();
+        }, &loop));
+    ping_a.reset();
+    loop.Run();
+  }
+
+  {
+    base::RunLoop loop;
+    bindings.set_pre_dispatch_handler(
+        base::Bind([](base::RunLoop* loop, const int& context) {
+          EXPECT_EQ(2, context);
+          loop->Quit();
+        }, &loop));
+    ping_b.reset();
+    loop.Run();
+  }
+
+  EXPECT_TRUE(bindings.empty());
+}
+
 TEST_F(BindingSetTest, AssociatedBindingSetConnectionErrorWithReason) {
   AssociatedPingProviderPtr master_ptr;
   PingProviderImpl master_impl;
diff --git a/net/PRESUBMIT.py b/net/PRESUBMIT.py
deleted file mode 100644
index 207cad0..0000000
--- a/net/PRESUBMIT.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2014 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.
-
-"""Top-level presubmit script for src/net.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index ffa7b261..fda084ea 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -482,22 +482,8 @@
   }
 }
 
-void HttpNetworkSession::OnMemoryStateChange(base::MemoryState state) {
-  // TODO(hajimehoshi): When the state changes, adjust the sizes of the caches
-  // to reduce the limits. HttpNetworkSession doesn't have the ability to limit
-  // at present.
-  switch (state) {
-    case base::MemoryState::NORMAL:
-      break;
-    case base::MemoryState::THROTTLED:
-      CloseIdleConnections();
-      break;
-    case base::MemoryState::SUSPENDED:
-    // Note: Not supported at present. Fall through.
-    case base::MemoryState::UNKNOWN:
-      NOTREACHED();
-      break;
-  }
+void HttpNetworkSession::OnPurgeMemory() {
+  CloseIdleConnections();
 }
 
 }  // namespace net
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 6f4e509..b0ed8c0 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -319,7 +319,7 @@
       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
 
   // base::MemoryCoordinatorClient implementation:
-  void OnMemoryStateChange(base::MemoryState state) override;
+  void OnPurgeMemory() override;
 
   NetLog* const net_log_;
   HttpServerProperties* const http_server_properties_;
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc
index 70f6d27a..18e6def 100644
--- a/net/http/http_request_headers.cc
+++ b/net/http/http_request_headers.cc
@@ -29,9 +29,11 @@
 const char HttpRequestHeaders::kContentType[] = "Content-Type";
 const char HttpRequestHeaders::kCookie[] = "Cookie";
 const char HttpRequestHeaders::kHost[] = "Host";
+const char HttpRequestHeaders::kIfMatch[] = "If-Match";
 const char HttpRequestHeaders::kIfModifiedSince[] = "If-Modified-Since";
 const char HttpRequestHeaders::kIfNoneMatch[] = "If-None-Match";
 const char HttpRequestHeaders::kIfRange[] = "If-Range";
+const char HttpRequestHeaders::kIfUnmodifiedSince[] = "If-Unmodified-Since";
 const char HttpRequestHeaders::kOrigin[] = "Origin";
 const char HttpRequestHeaders::kPragma[] = "Pragma";
 const char HttpRequestHeaders::kProxyAuthorization[] = "Proxy-Authorization";
diff --git a/net/http/http_request_headers.h b/net/http/http_request_headers.h
index 3a05102..a3591748 100644
--- a/net/http/http_request_headers.h
+++ b/net/http/http_request_headers.h
@@ -73,9 +73,11 @@
   static const char kCookie[];
   static const char kContentLength[];
   static const char kHost[];
+  static const char kIfMatch[];
   static const char kIfModifiedSince[];
   static const char kIfNoneMatch[];
   static const char kIfRange[];
+  static const char kIfUnmodifiedSince[];
   static const char kOrigin[];
   static const char kPragma[];
   static const char kProxyAuthorization[];
diff --git a/net/nqe/effective_connection_type.cc b/net/nqe/effective_connection_type.cc
index ea1fec4..811c725 100644
--- a/net/nqe/effective_connection_type.cc
+++ b/net/nqe/effective_connection_type.cc
@@ -41,7 +41,7 @@
 }
 
 bool GetEffectiveConnectionTypeForName(
-    const std::string& connection_type_name,
+    base::StringPiece connection_type_name,
     EffectiveConnectionType* effective_connection_type) {
   if (connection_type_name == kEffectiveConnectionTypeUnknown) {
     *effective_connection_type = EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
diff --git a/net/nqe/effective_connection_type.h b/net/nqe/effective_connection_type.h
index a40618bb..4b095ed 100644
--- a/net/nqe/effective_connection_type.h
+++ b/net/nqe/effective_connection_type.h
@@ -5,8 +5,7 @@
 #ifndef NET_NQE_EFFECTIVE_CONNECTION_TYPE_H_
 #define NET_NQE_EFFECTIVE_CONNECTION_TYPE_H_
 
-#include <string>
-
+#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 
 namespace net {
@@ -62,7 +61,7 @@
 // EFFECTIVE_CONNECTION_TYPE_UNKNOWN. |effective_connection_type| must be
 // non-null.
 NET_EXPORT bool GetEffectiveConnectionTypeForName(
-    const std::string& connection_type_name,
+    base::StringPiece connection_type_name,
     EffectiveConnectionType* effective_connection_type);
 
 }  // namespace net
diff --git a/net/quic/chromium/quic_http_stream.h b/net/quic/chromium/quic_http_stream.h
index 29365a4..3dd4982 100644
--- a/net/quic/chromium/quic_http_stream.h
+++ b/net/quic/chromium/quic_http_stream.h
@@ -170,9 +170,6 @@
 
   bool response_headers_received_;
 
-  // Serialized HTTP request.
-  std::string request_;
-
   // Number of bytes received by the headers stream on behalf of this stream.
   int64_t headers_bytes_received_;
   // Number of bytes sent by the headers stream on behalf of this stream.
diff --git a/net/quic/chromium/quic_server_info.cc b/net/quic/chromium/quic_server_info.cc
index 7259dbac..23f4cf8a 100644
--- a/net/quic/chromium/quic_server_info.cc
+++ b/net/quic/chromium/quic_server_info.cc
@@ -7,6 +7,7 @@
 #include <limits>
 
 #include "base/pickle.h"
+#include "base/stl_util.h"
 
 using std::string;
 
@@ -23,12 +24,12 @@
 QuicServerInfo::State::~State() {}
 
 void QuicServerInfo::State::Clear() {
-  server_config.clear();
-  source_address_token.clear();
-  cert_sct.clear();
-  chlo_hash.clear();
-  server_config_sig.clear();
-  certs.clear();
+  base::STLClearObject(&server_config);
+  base::STLClearObject(&source_address_token);
+  base::STLClearObject(&cert_sct);
+  base::STLClearObject(&chlo_hash);
+  base::STLClearObject(&server_config_sig);
+  base::STLClearObject(&certs);
 }
 
 QuicServerInfo::QuicServerInfo(const QuicServerId& server_id)
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 1280dd3a..f7eff116 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -6,8 +6,6 @@
 
 #include <memory>
 
-#include "crypto/openssl_util.h"
-#include "crypto/secure_hash.h"
 #include "net/quic/core/crypto/channel_id.h"
 #include "net/quic/core/crypto/common_cert_set.h"
 #include "net/quic/core/crypto/crypto_handshake.h"
@@ -33,7 +31,6 @@
 #include "third_party/boringssl/src/include/openssl/bn.h"
 #include "third_party/boringssl/src/include/openssl/ec.h"
 #include "third_party/boringssl/src/include/openssl/ecdsa.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
 #include "third_party/boringssl/src/include/openssl/obj_mac.h"
 #include "third_party/boringssl/src/include/openssl/sha.h"
 
@@ -42,6 +39,127 @@
 
 namespace net {
 namespace test {
+
+TestChannelIDKey::TestChannelIDKey(EVP_PKEY* ecdsa_key)
+    : ecdsa_key_(ecdsa_key) {}
+TestChannelIDKey::~TestChannelIDKey() {}
+
+bool TestChannelIDKey::Sign(StringPiece signed_data,
+                            string* out_signature) const {
+  bssl::ScopedEVP_MD_CTX md_ctx;
+  if (EVP_DigestSignInit(md_ctx.get(), nullptr, EVP_sha256(), nullptr,
+                         ecdsa_key_.get()) != 1) {
+    return false;
+  }
+
+  EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kContextStr,
+                   strlen(ChannelIDVerifier::kContextStr) + 1);
+  EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kClientToServerStr,
+                   strlen(ChannelIDVerifier::kClientToServerStr) + 1);
+  EVP_DigestUpdate(md_ctx.get(), signed_data.data(), signed_data.size());
+
+  size_t sig_len;
+  if (!EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len)) {
+    return false;
+  }
+
+  std::unique_ptr<uint8_t[]> der_sig(new uint8_t[sig_len]);
+  if (!EVP_DigestSignFinal(md_ctx.get(), der_sig.get(), &sig_len)) {
+    return false;
+  }
+
+  uint8_t* derp = der_sig.get();
+  bssl::UniquePtr<ECDSA_SIG> sig(
+      d2i_ECDSA_SIG(nullptr, const_cast<const uint8_t**>(&derp), sig_len));
+  if (sig.get() == nullptr) {
+    return false;
+  }
+
+  // The signature consists of a pair of 32-byte numbers.
+  static const size_t kSignatureLength = 32 * 2;
+  std::unique_ptr<uint8_t[]> signature(new uint8_t[kSignatureLength]);
+  if (!BN_bn2bin_padded(&signature[0], 32, sig->r) ||
+      !BN_bn2bin_padded(&signature[32], 32, sig->s)) {
+    return false;
+  }
+
+  *out_signature =
+      string(reinterpret_cast<char*>(signature.get()), kSignatureLength);
+
+  return true;
+}
+
+string TestChannelIDKey::SerializeKey() const {
+  // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256
+  // key, is 0x04 (meaning uncompressed) followed by the x and y field
+  // elements as 32-byte, big-endian numbers.
+  static const int kExpectedKeyLength = 65;
+
+  int len = i2d_PublicKey(ecdsa_key_.get(), nullptr);
+  if (len != kExpectedKeyLength) {
+    return "";
+  }
+
+  uint8_t buf[kExpectedKeyLength];
+  uint8_t* derp = buf;
+  i2d_PublicKey(ecdsa_key_.get(), &derp);
+
+  return string(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1);
+}
+
+TestChannelIDSource::~TestChannelIDSource() {}
+
+QuicAsyncStatus TestChannelIDSource::GetChannelIDKey(
+    const string& hostname,
+    std::unique_ptr<ChannelIDKey>* channel_id_key,
+    ChannelIDSourceCallback* /*callback*/) {
+  channel_id_key->reset(new TestChannelIDKey(HostnameToKey(hostname)));
+  return QUIC_SUCCESS;
+}
+
+// static
+EVP_PKEY* TestChannelIDSource::HostnameToKey(const string& hostname) {
+  // In order to generate a deterministic key for a given hostname the
+  // hostname is hashed with SHA-256 and the resulting digest is treated as a
+  // big-endian number. The most-significant bit is cleared to ensure that
+  // the resulting value is less than the order of the group and then it's
+  // taken as a private key. Given the private key, the public key is
+  // calculated with a group multiplication.
+  SHA256_CTX sha256;
+  SHA256_Init(&sha256);
+  SHA256_Update(&sha256, hostname.data(), hostname.size());
+
+  unsigned char digest[SHA256_DIGEST_LENGTH];
+  SHA256_Final(digest, &sha256);
+
+  // Ensure that the digest is less than the order of the P-256 group by
+  // clearing the most-significant bit.
+  digest[0] &= 0x7f;
+
+  bssl::UniquePtr<BIGNUM> k(BN_new());
+  CHECK(BN_bin2bn(digest, sizeof(digest), k.get()) != nullptr);
+
+  bssl::UniquePtr<EC_GROUP> p256(
+      EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+  CHECK(p256);
+
+  bssl::UniquePtr<EC_KEY> ecdsa_key(EC_KEY_new());
+  CHECK(ecdsa_key && EC_KEY_set_group(ecdsa_key.get(), p256.get()));
+
+  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
+  CHECK(EC_POINT_mul(p256.get(), point.get(), k.get(), nullptr, nullptr,
+                     nullptr));
+
+  EC_KEY_set_private_key(ecdsa_key.get(), k.get());
+  EC_KEY_set_public_key(ecdsa_key.get(), point.get());
+
+  bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
+  // EVP_PKEY_set1_EC_KEY takes a reference so no |release| here.
+  EVP_PKEY_set1_EC_KEY(pkey.get(), ecdsa_key.get());
+
+  return pkey.release();
+}
+
 namespace crypto_test_utils {
 
 namespace {
@@ -128,137 +246,6 @@
   std::unique_ptr<ChannelIDKey> channel_id_key_;
 };
 
-class TestChannelIDKey : public ChannelIDKey {
- public:
-  explicit TestChannelIDKey(EVP_PKEY* ecdsa_key) : ecdsa_key_(ecdsa_key) {}
-  ~TestChannelIDKey() override {}
-
-  // ChannelIDKey implementation.
-
-  bool Sign(StringPiece signed_data, string* out_signature) const override {
-    bssl::ScopedEVP_MD_CTX md_ctx;
-    if (EVP_DigestSignInit(md_ctx.get(), nullptr, EVP_sha256(), nullptr,
-                           ecdsa_key_.get()) != 1) {
-      return false;
-    }
-
-    EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kContextStr,
-                     strlen(ChannelIDVerifier::kContextStr) + 1);
-    EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kClientToServerStr,
-                     strlen(ChannelIDVerifier::kClientToServerStr) + 1);
-    EVP_DigestUpdate(md_ctx.get(), signed_data.data(), signed_data.size());
-
-    size_t sig_len;
-    if (!EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len)) {
-      return false;
-    }
-
-    std::unique_ptr<uint8_t[]> der_sig(new uint8_t[sig_len]);
-    if (!EVP_DigestSignFinal(md_ctx.get(), der_sig.get(), &sig_len)) {
-      return false;
-    }
-
-    uint8_t* derp = der_sig.get();
-    bssl::UniquePtr<ECDSA_SIG> sig(
-        d2i_ECDSA_SIG(nullptr, const_cast<const uint8_t**>(&derp), sig_len));
-    if (sig.get() == nullptr) {
-      return false;
-    }
-
-    // The signature consists of a pair of 32-byte numbers.
-    static const size_t kSignatureLength = 32 * 2;
-    std::unique_ptr<uint8_t[]> signature(new uint8_t[kSignatureLength]);
-    if (!BN_bn2bin_padded(&signature[0], 32, sig->r) ||
-        !BN_bn2bin_padded(&signature[32], 32, sig->s)) {
-      return false;
-    }
-
-    *out_signature =
-        string(reinterpret_cast<char*>(signature.get()), kSignatureLength);
-
-    return true;
-  }
-
-  string SerializeKey() const override {
-    // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256
-    // key, is 0x04 (meaning uncompressed) followed by the x and y field
-    // elements as 32-byte, big-endian numbers.
-    static const int kExpectedKeyLength = 65;
-
-    int len = i2d_PublicKey(ecdsa_key_.get(), nullptr);
-    if (len != kExpectedKeyLength) {
-      return "";
-    }
-
-    uint8_t buf[kExpectedKeyLength];
-    uint8_t* derp = buf;
-    i2d_PublicKey(ecdsa_key_.get(), &derp);
-
-    return string(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1);
-  }
-
- private:
-  bssl::UniquePtr<EVP_PKEY> ecdsa_key_;
-};
-
-class TestChannelIDSource : public ChannelIDSource {
- public:
-  ~TestChannelIDSource() override {}
-
-  // ChannelIDSource implementation.
-
-  QuicAsyncStatus GetChannelIDKey(
-      const string& hostname,
-      std::unique_ptr<ChannelIDKey>* channel_id_key,
-      ChannelIDSourceCallback* /*callback*/) override {
-    channel_id_key->reset(new TestChannelIDKey(HostnameToKey(hostname)));
-    return QUIC_SUCCESS;
-  }
-
- private:
-  static EVP_PKEY* HostnameToKey(const string& hostname) {
-    // In order to generate a deterministic key for a given hostname the
-    // hostname is hashed with SHA-256 and the resulting digest is treated as a
-    // big-endian number. The most-significant bit is cleared to ensure that
-    // the resulting value is less than the order of the group and then it's
-    // taken as a private key. Given the private key, the public key is
-    // calculated with a group multiplication.
-    SHA256_CTX sha256;
-    SHA256_Init(&sha256);
-    SHA256_Update(&sha256, hostname.data(), hostname.size());
-
-    unsigned char digest[SHA256_DIGEST_LENGTH];
-    SHA256_Final(digest, &sha256);
-
-    // Ensure that the digest is less than the order of the P-256 group by
-    // clearing the most-significant bit.
-    digest[0] &= 0x7f;
-
-    bssl::UniquePtr<BIGNUM> k(BN_new());
-    CHECK(BN_bin2bn(digest, sizeof(digest), k.get()) != nullptr);
-
-    bssl::UniquePtr<EC_GROUP> p256(
-        EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
-    CHECK(p256);
-
-    bssl::UniquePtr<EC_KEY> ecdsa_key(EC_KEY_new());
-    CHECK(ecdsa_key && EC_KEY_set_group(ecdsa_key.get(), p256.get()));
-
-    bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
-    CHECK(EC_POINT_mul(p256.get(), point.get(), k.get(), nullptr, nullptr,
-                       nullptr));
-
-    EC_KEY_set_private_key(ecdsa_key.get(), k.get());
-    EC_KEY_set_public_key(ecdsa_key.get(), point.get());
-
-    bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
-    // EVP_PKEY_set1_EC_KEY takes a reference so no |release| here.
-    EVP_PKEY_set1_EC_KEY(pkey.get(), ecdsa_key.get());
-
-    return pkey.release();
-  }
-};
-
 }  // anonymous namespace
 
 FakeServerOptions::FakeServerOptions() {}
@@ -950,22 +937,22 @@
 
 string GenerateClientNonceHex(const QuicClock* clock,
                               QuicCryptoServerConfig* crypto_config) {
-  net::QuicCryptoServerConfig::ConfigOptions old_config_options;
-  net::QuicCryptoServerConfig::ConfigOptions new_config_options;
+  QuicCryptoServerConfig::ConfigOptions old_config_options;
+  QuicCryptoServerConfig::ConfigOptions new_config_options;
   old_config_options.id = "old-config-id";
-  delete crypto_config->AddDefaultConfig(net::QuicRandom::GetInstance(), clock,
+  delete crypto_config->AddDefaultConfig(QuicRandom::GetInstance(), clock,
                                          old_config_options);
   std::unique_ptr<QuicServerConfigProtobuf> primary_config(
-      crypto_config->GenerateConfig(net::QuicRandom::GetInstance(), clock,
+      crypto_config->GenerateConfig(QuicRandom::GetInstance(), clock,
                                     new_config_options));
   primary_config->set_primary_time(clock->WallNow().ToUNIXSeconds());
-  std::unique_ptr<net::CryptoHandshakeMessage> msg(
+  std::unique_ptr<CryptoHandshakeMessage> msg(
       crypto_config->AddConfig(std::move(primary_config), clock->WallNow()));
   StringPiece orbit;
-  CHECK(msg->GetStringPiece(net::kORBT, &orbit));
+  CHECK(msg->GetStringPiece(kORBT, &orbit));
   string nonce;
-  net::CryptoUtils::GenerateNonce(
-      clock->WallNow(), net::QuicRandom::GetInstance(),
+  CryptoUtils::GenerateNonce(
+      clock->WallNow(), QuicRandom::GetInstance(),
       StringPiece(reinterpret_cast<const char*>(orbit.data()),
                   sizeof(orbit.size())),
       &nonce);
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index f8611cd5..0ed27ec 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -17,6 +17,7 @@
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/test_tools/quic_test_utils.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
 
 namespace net {
 
@@ -38,6 +39,39 @@
 
 class PacketSavingConnection;
 
+class TestChannelIDKey : public ChannelIDKey {
+ public:
+  explicit TestChannelIDKey(EVP_PKEY* ecdsa_key);
+  ~TestChannelIDKey() override;
+
+  // ChannelIDKey implementation.
+
+  bool Sign(base::StringPiece signed_data,
+            std::string* out_signature) const override;
+
+  std::string SerializeKey() const override;
+
+  const EVP_PKEY* get_evp_pkey() const { return ecdsa_key_.get(); }
+
+ private:
+  bssl::UniquePtr<EVP_PKEY> ecdsa_key_;
+};
+
+class TestChannelIDSource : public ChannelIDSource {
+ public:
+  ~TestChannelIDSource() override;
+
+  // ChannelIDSource implementation.
+
+  QuicAsyncStatus GetChannelIDKey(
+      const std::string& hostname,
+      std::unique_ptr<ChannelIDKey>* channel_id_key,
+      ChannelIDSourceCallback* /*callback*/) override;
+
+ private:
+  static EVP_PKEY* HostnameToKey(const std::string& hostname);
+};
+
 namespace crypto_test_utils {
 
 // An interface for a source of callbacks. This is used for invoking
diff --git a/net/quic/test_tools/delayed_verify_strike_register_client.h b/net/quic/test_tools/delayed_verify_strike_register_client.h
index cb87f2fc..c67aedb 100644
--- a/net/quic/test_tools/delayed_verify_strike_register_client.h
+++ b/net/quic/test_tools/delayed_verify_strike_register_client.h
@@ -5,8 +5,7 @@
 #ifndef NET_QUIC_TEST_TOOLS_DELAYED_VERIFY_STRIKE_REGISTER_CLIENT_H_
 #define NET_QUIC_TEST_TOOLS_DELAYED_VERIFY_STRIKE_REGISTER_CLIENT_H_
 
-#include <stdint.h>
-
+#include <cstdint>
 #include <string>
 #include <vector>
 
diff --git a/net/quic/test_tools/fake_proof_source.cc b/net/quic/test_tools/fake_proof_source.cc
index 0eea145..296384e 100644
--- a/net/quic/test_tools/fake_proof_source.cc
+++ b/net/quic/test_tools/fake_proof_source.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/quic/platform/api/quic_logging.h"
 #include "net/quic/test_tools/fake_proof_source.h"
+
+#include "net/quic/platform/api/quic_logging.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
 
 using std::string;
@@ -17,10 +18,10 @@
 FakeProofSource::~FakeProofSource() {}
 
 FakeProofSource::Params::Params(const QuicSocketAddress& server_addr,
-                                std::string hostname,
-                                std::string server_config,
+                                string hostname,
+                                string server_config,
                                 QuicVersion quic_version,
-                                std::string chlo_hash,
+                                string chlo_hash,
                                 const QuicTagVector& connection_options,
                                 std::unique_ptr<ProofSource::Callback> callback)
     : server_address(server_addr),
diff --git a/net/quic/test_tools/mock_quic_spdy_client_stream.cc b/net/quic/test_tools/mock_quic_spdy_client_stream.cc
index 874f89f6..6da6fd0 100644
--- a/net/quic/test_tools/mock_quic_spdy_client_stream.cc
+++ b/net/quic/test_tools/mock_quic_spdy_client_stream.cc
@@ -4,8 +4,6 @@
 
 #include "net/quic/test_tools/mock_quic_spdy_client_stream.h"
 
-using net::QuicClientSession;
-
 namespace net {
 namespace test {
 
diff --git a/net/quic/test_tools/mock_quic_spdy_client_stream.h b/net/quic/test_tools/mock_quic_spdy_client_stream.h
index 5522cb6..e4ca6007 100644
--- a/net/quic/test_tools/mock_quic_spdy_client_stream.h
+++ b/net/quic/test_tools/mock_quic_spdy_client_stream.h
@@ -10,14 +10,13 @@
 #include "net/quic/core/quic_packets.h"
 #include "net/tools/quic/quic_spdy_client_stream.h"
 #include "testing/gmock/include/gmock/gmock.h"
-// #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
 namespace test {
 
-class MockQuicSpdyClientStream : public net::QuicSpdyClientStream {
+class MockQuicSpdyClientStream : public QuicSpdyClientStream {
  public:
-  MockQuicSpdyClientStream(QuicStreamId id, net::QuicClientSession* session);
+  MockQuicSpdyClientStream(QuicStreamId id, QuicClientSession* session);
   ~MockQuicSpdyClientStream() override;
 
   MOCK_METHOD1(OnStreamFrame, void(const QuicStreamFrame& frame));
diff --git a/net/quic/test_tools/mock_random.h b/net/quic/test_tools/mock_random.h
index a3ed228..43765d29 100644
--- a/net/quic/test_tools/mock_random.h
+++ b/net/quic/test_tools/mock_random.h
@@ -5,9 +5,6 @@
 #ifndef NET_QUIC_TEST_TOOLS_MOCK_RANDOM_H_
 #define NET_QUIC_TEST_TOOLS_MOCK_RANDOM_H_
 
-#include <stddef.h>
-#include <stdint.h>
-
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "net/quic/core/crypto/quic_random.h"
diff --git a/net/quic/test_tools/quic_config_peer.cc b/net/quic/test_tools/quic_config_peer.cc
index 45cf4250..d22304b 100644
--- a/net/quic/test_tools/quic_config_peer.cc
+++ b/net/quic/test_tools/quic_config_peer.cc
@@ -69,11 +69,5 @@
   config->force_hol_blocking_.SetReceivedValue(1);
 }
 
-// static
-void QuicConfigPeer::SetReceivedAlternateServerAddress(QuicConfig* config,
-                                                       QuicSocketAddress addr) {
-  config->alternate_server_address_.SetReceivedValue(addr);
-}
-
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/quic_config_peer.h b/net/quic/test_tools/quic_config_peer.h
index 20c8f08d..7c6691dd 100644
--- a/net/quic/test_tools/quic_config_peer.h
+++ b/net/quic/test_tools/quic_config_peer.h
@@ -5,8 +5,6 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_CONFIG_PEER_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_CONFIG_PEER_H_
 
-#include <stdint.h>
-
 #include "base/macros.h"
 #include "net/quic/core/quic_config.h"
 #include "net/quic/core/quic_packets.h"
@@ -33,6 +31,7 @@
 
   static void SetReceivedBytesForConnectionId(QuicConfig* config,
                                               uint32_t bytes);
+
   static void SetReceivedDisableConnectionMigration(QuicConfig* config);
 
   static void SetReceivedMaxIncomingDynamicStreams(QuicConfig* config,
@@ -43,9 +42,6 @@
 
   static void SetReceivedForceHolBlocking(QuicConfig* config);
 
-  static void SetReceivedAlternateServerAddress(QuicConfig* config,
-                                                QuicSocketAddress addr);
-
  private:
   DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer);
 };
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index 84cd402..8c2e195 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -4,7 +4,6 @@
 
 #include "net/quic/test_tools/quic_connection_peer.h"
 
-#include "base/stl_util.h"
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
 #include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_packet_writer.h"
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 0a5c529..64e0685 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -6,7 +6,6 @@
 #define NET_QUIC_TEST_TOOLS_QUIC_CONNECTION_PEER_H_
 
 #include "base/macros.h"
-#include "net/base/ip_endpoint.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_connection_stats.h"
 #include "net/quic/core/quic_packets.h"
diff --git a/net/quic/test_tools/quic_crypto_server_config_peer.cc b/net/quic/test_tools/quic_crypto_server_config_peer.cc
index fa2b30c..1be6ffc7 100644
--- a/net/quic/test_tools/quic_crypto_server_config_peer.cc
+++ b/net/quic/test_tools/quic_crypto_server_config_peer.cc
@@ -4,8 +4,6 @@
 
 #include "net/quic/test_tools/quic_crypto_server_config_peer.h"
 
-#include <cstdarg>
-
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/mock_random.h"
 #include "net/quic/test_tools/quic_test_utils.h"
diff --git a/net/quic/test_tools/quic_crypto_server_config_peer.h b/net/quic/test_tools/quic_crypto_server_config_peer.h
index facde4ef..2b4bc05 100644
--- a/net/quic/test_tools/quic_crypto_server_config_peer.h
+++ b/net/quic/test_tools/quic_crypto_server_config_peer.h
@@ -77,7 +77,8 @@
 
   // ConfigsDebug returns a string that contains debugging information about
   // the set of Configs loaded in |server_config_| and their status.
-  std::string ConfigsDebug();
+  std::string ConfigsDebug()
+      SHARED_LOCKS_REQUIRED(server_config_->configs_lock_);
 
   void SelectNewPrimaryConfig(int seconds);
 
diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h
index 1cdb91b5d..481050f 100644
--- a/net/quic/test_tools/quic_packet_creator_peer.h
+++ b/net/quic/test_tools/quic_packet_creator_peer.h
@@ -5,8 +5,6 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_PACKET_CREATOR_PEER_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_PACKET_CREATOR_PEER_H_
 
-#include <stddef.h>
-
 #include "base/macros.h"
 #include "net/quic/core/quic_iovector.h"
 #include "net/quic/core/quic_packets.h"
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
index d3039726..c963260 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -4,10 +4,8 @@
 
 #include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
 
-#include "base/stl_util.h"
 #include "net/quic/core/congestion_control/loss_detection_interface.h"
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
 
@@ -90,8 +88,8 @@
     QuicPacketNumber packet_number) {
   DCHECK(sent_packet_manager->unacked_packets_.IsUnacked(packet_number));
 
-  return sent_packet_manager->unacked_packets_.GetTransmissionInfo(
-                                                  packet_number)
+  return sent_packet_manager->unacked_packets_
+      .GetTransmissionInfo(packet_number)
       .sent_time;
 }
 
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.h b/net/quic/test_tools/quic_sent_packet_manager_peer.h
index 0ffbafc..93c62e5 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -5,8 +5,6 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_SENT_PACKET_MANAGER_PEER_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_SENT_PACKET_MANAGER_PEER_H_
 
-#include <stddef.h>
-
 #include "base/macros.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h
index 8874c7ac..a5915e8 100644
--- a/net/quic/test_tools/quic_session_peer.h
+++ b/net/quic/test_tools/quic_session_peer.h
@@ -5,8 +5,7 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_SESSION_PEER_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_SESSION_PEER_H_
 
-#include <stdint.h>
-
+#include <cstdint>
 #include <map>
 #include <memory>
 
diff --git a/net/quic/test_tools/quic_stream_peer.h b/net/quic/test_tools/quic_stream_peer.h
index aa634c5..2c2bb912e 100644
--- a/net/quic/test_tools/quic_stream_peer.h
+++ b/net/quic/test_tools/quic_stream_peer.h
@@ -5,7 +5,7 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_STREAM_PEER_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_STREAM_PEER_H_
 
-#include <stdint.h>
+#include <cstdint>
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
@@ -53,6 +53,7 @@
 };
 
 }  // namespace test
+
 }  // namespace net
 
 #endif  // NET_QUIC_TEST_TOOLS_QUIC_STREAM_PEER_H_
diff --git a/net/quic/test_tools/quic_stream_sequencer_buffer_peer.h b/net/quic/test_tools/quic_stream_sequencer_buffer_peer.h
index 68944f52dc..0989843 100644
--- a/net/quic/test_tools/quic_stream_sequencer_buffer_peer.h
+++ b/net/quic/test_tools/quic_stream_sequencer_buffer_peer.h
@@ -13,8 +13,7 @@
 
 class QuicStreamSequencerBufferPeer {
  public:
-  explicit QuicStreamSequencerBufferPeer(
-      net::QuicStreamSequencerBuffer* buffer);
+  explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer);
 
   // Read from this buffer_ into the given destination buffer_ up to the
   // size of the destination. Returns the number of bytes read. Reading from
@@ -33,27 +32,27 @@
 
   size_t GetInBlockOffset(QuicStreamOffset offset);
 
-  net::QuicStreamSequencerBuffer::BufferBlock* GetBlock(size_t index);
+  QuicStreamSequencerBuffer::BufferBlock* GetBlock(size_t index);
 
   int GapSize();
 
-  std::list<net::QuicStreamSequencerBuffer::Gap> GetGaps();
+  std::list<QuicStreamSequencerBuffer::Gap> GetGaps();
 
   size_t max_buffer_capacity();
 
   size_t ReadableBytes();
 
-  std::map<QuicStreamOffset, net::QuicStreamSequencerBuffer::FrameInfo>*
+  std::map<QuicStreamOffset, QuicStreamSequencerBuffer::FrameInfo>*
   frame_arrival_time_map();
 
   void set_total_bytes_read(QuicStreamOffset total_bytes_read);
 
-  void set_gaps(const std::list<net::QuicStreamSequencerBuffer::Gap>& gaps);
+  void set_gaps(const std::list<QuicStreamSequencerBuffer::Gap>& gaps);
 
   bool IsBufferAllocated();
 
  private:
-  net::QuicStreamSequencerBuffer* buffer_;
+  QuicStreamSequencerBuffer* buffer_;
   DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerBufferPeer);
 };
 
diff --git a/net/quic/test_tools/quic_stream_sequencer_peer.h b/net/quic/test_tools/quic_stream_sequencer_peer.h
index cc63e711..9982e73 100644
--- a/net/quic/test_tools/quic_stream_sequencer_peer.h
+++ b/net/quic/test_tools/quic_stream_sequencer_peer.h
@@ -5,8 +5,6 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_STREAM_SEQUENCER_PEER_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_STREAM_SEQUENCER_PEER_H_
 
-#include <stddef.h>
-
 #include "base/macros.h"
 #include "net/quic/core/quic_packets.h"
 
diff --git a/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h b/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
index 5dbb4e3..594344e 100644
--- a/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
+++ b/net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
@@ -5,7 +5,7 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_SUSTAINED_BANDWIDTH_RECORDER_PEER_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_SUSTAINED_BANDWIDTH_RECORDER_PEER_H_
 
-#include <stdint.h>
+#include <cstdint>
 
 #include "base/macros.h"
 #include "net/quic/core/quic_packets.h"
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 9b30937..cdee5cb 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -13,6 +13,7 @@
 #include "net/quic/core/crypto/quic_decrypter.h"
 #include "net/quic/core/crypto/quic_encrypter.h"
 #include "net/quic/core/quic_data_writer.h"
+#include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packet_creator.h"
 #include "net/quic/core/quic_utils.h"
@@ -21,16 +22,16 @@
 #include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/quic/test_tools/quic_connection_peer.h"
 #include "net/spdy/spdy_frame_builder.h"
-#include "net/tools/quic/quic_per_connection_packet_writer.h"
 #include "third_party/boringssl/src/include/openssl/sha.h"
 
 using base::StringPiece;
+using std::max;
+using std::min;
 using std::string;
-using testing::Invoke;
 using testing::_;
+using testing::Invoke;
 
 namespace net {
-
 namespace test {
 
 QuicAckFrame MakeAckFrame(QuicPacketNumber largest_observed) {
@@ -252,10 +253,9 @@
     QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
     QuicConnectionArena* arena) {
   if (arena != nullptr) {
-    return arena->New<MockAlarmFactory::TestAlarm>(std::move(delegate));
+    return arena->New<TestAlarm>(std::move(delegate));
   } else {
-    return QuicArenaScopedPtr<MockAlarmFactory::TestAlarm>(
-        new TestAlarm(std::move(delegate)));
+    return QuicArenaScopedPtr<TestAlarm>(new TestAlarm(std::move(delegate)));
   }
 }
 
@@ -438,22 +438,6 @@
       QuicServerSessionBase::GetCryptoStream());
 }
 
-TestPushPromiseDelegate::TestPushPromiseDelegate(bool match)
-    : match_(match), rendezvous_fired_(false), rendezvous_stream_(nullptr) {}
-
-bool TestPushPromiseDelegate::CheckVary(
-    const SpdyHeaderBlock& client_request,
-    const SpdyHeaderBlock& promise_request,
-    const SpdyHeaderBlock& promise_response) {
-  QUIC_DVLOG(1) << "match " << match_;
-  return match_;
-}
-
-void TestPushPromiseDelegate::OnRendezvousResult(QuicSpdyStream* stream) {
-  rendezvous_fired_ = true;
-  rendezvous_stream_ = stream;
-}
-
 TestQuicSpdyClientSession::TestQuicSpdyClientSession(
     QuicConnection* connection,
     const QuicConfig& config,
@@ -476,6 +460,22 @@
   return crypto_stream_.get();
 }
 
+TestPushPromiseDelegate::TestPushPromiseDelegate(bool match)
+    : match_(match), rendezvous_fired_(false), rendezvous_stream_(nullptr) {}
+
+bool TestPushPromiseDelegate::CheckVary(
+    const SpdyHeaderBlock& client_request,
+    const SpdyHeaderBlock& promise_request,
+    const SpdyHeaderBlock& promise_response) {
+  QUIC_DVLOG(1) << "match " << match_;
+  return match_;
+}
+
+void TestPushPromiseDelegate::OnRendezvousResult(QuicSpdyStream* stream) {
+  rendezvous_fired_ = true;
+  rendezvous_stream_ = stream;
+}
+
 MockPacketWriter::MockPacketWriter() {
   ON_CALL(*this, GetMaxPacketSize(_))
       .WillByDefault(testing::Return(kMaxPacketSize));
@@ -511,8 +511,8 @@
   const int kSizeLimit = 1024;
   if (length > kSizeLimit || mark_length > kSizeLimit) {
     QUIC_LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
-    length = std::min(length, kSizeLimit);
-    mark_length = std::min(mark_length, kSizeLimit);
+    length = min(length, kSizeLimit);
+    mark_length = min(mark_length, kSizeLimit);
   }
 
   string hex;
@@ -555,18 +555,6 @@
   return AllSupportedVersions().back();
 }
 
-IPAddress Loopback4() {
-  return IPAddress::IPv4Localhost();
-}
-
-IPAddress Loopback6() {
-  return IPAddress::IPv6Localhost();
-}
-
-IPAddress Any4() {
-  return IPAddress::IPv4AllZeros();
-}
-
 QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
                                               bool version_flag,
                                               bool multipath_flag,
@@ -710,8 +698,8 @@
                                    const char* expected,
                                    const int expected_len) {
   EXPECT_EQ(actual_len, expected_len);
-  const int min_len = std::min(actual_len, expected_len);
-  const int max_len = std::max(actual_len, expected_len);
+  const int min_len = min(actual_len, expected_len);
+  const int max_len = max(actual_len, expected_len);
   std::unique_ptr<bool[]> marks(new bool[max_len]);
   bool identical = (actual_len == expected_len);
   for (int i = 0; i < min_len; ++i) {
@@ -735,38 +723,6 @@
                 << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
 }
 
-static QuicPacket* ConstructPacketFromHandshakeMessage(
-    QuicConnectionId connection_id,
-    const CryptoHandshakeMessage& message,
-    bool should_include_version) {
-  CryptoFramer crypto_framer;
-  std::unique_ptr<QuicData> data(
-      crypto_framer.ConstructHandshakeMessage(message));
-  QuicFramer quic_framer(AllSupportedVersions(), QuicTime::Zero(),
-                         Perspective::IS_CLIENT);
-
-  QuicPacketHeader header;
-  header.public_header.connection_id = connection_id;
-  header.public_header.reset_flag = false;
-  header.public_header.version_flag = should_include_version;
-  header.packet_number = 1;
-
-  QuicStreamFrame stream_frame(kCryptoStreamId, false, 0,
-                               data->AsStringPiece());
-
-  QuicFrame frame(&stream_frame);
-  QuicFrames frames;
-  frames.push_back(frame);
-  return BuildUnsizedDataPacket(&quic_framer, header, frames);
-}
-
-QuicPacket* ConstructHandshakePacket(QuicConnectionId connection_id,
-                                     QuicTag tag) {
-  CryptoHandshakeMessage message;
-  message.set_tag(tag);
-  return ConstructPacketFromHandshakeMessage(connection_id, message, false);
-}
-
 size_t GetPacketLengthForOneStream(QuicVersion version,
                                    bool include_version,
                                    bool include_path_id,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 082c5e32..0508831 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -7,9 +7,6 @@
 #ifndef NET_QUIC_TEST_TOOLS_QUIC_TEST_UTILS_H_
 #define NET_QUIC_TEST_TOOLS_QUIC_TEST_UTILS_H_
 
-#include <stddef.h>
-#include <stdint.h>
-
 #include <cstdint>
 #include <memory>
 #include <string>
@@ -18,7 +15,6 @@
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
-#include "net/base/ip_address.h"
 #include "net/quic/core/congestion_control/loss_detection_interface.h"
 #include "net/quic/core/congestion_control/send_algorithm_interface.h"
 #include "net/quic/core/quic_client_push_promise_index.h"
@@ -26,16 +22,12 @@
 #include "net/quic/core/quic_connection_close_delegate_interface.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_iovector.h"
-#include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_sent_packet_manager.h"
 #include "net/quic/core/quic_server_session_base.h"
-#include "net/quic/core/quic_session.h"
 #include "net/quic/core/quic_simple_buffer_allocator.h"
 #include "net/quic/test_tools/mock_clock.h"
 #include "net/quic/test_tools/mock_random.h"
-#include "net/spdy/spdy_framer.h"
 #include "net/test/gtest_util.h"
-#include "net/tools/quic/quic_dispatcher.h"
 #include "net/tools/quic/quic_per_connection_packet_writer.h"
 #include "net/tools/quic/test_tools/mock_quic_session_visitor.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -73,15 +65,6 @@
 // Lower limit on versions we support.
 QuicVersion QuicVersionMin();
 
-// Returns an address for 127.0.0.1.
-IPAddress Loopback4();
-
-// Returns an address for ::1.
-IPAddress Loopback6();
-
-// Returns an address for 0.0.0.0.
-IPAddress Any4();
-
 // Create an encrypted packet for testing.
 // If versions == nullptr, uses &AllSupportedVersions().
 // Note that the packet is encrypted with NullEncrypter, so to decrypt the
@@ -672,8 +655,11 @@
   DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyServerSession);
 };
 
+// A test implementation of QuicClientPushPromiseIndex::Delegate.
 class TestPushPromiseDelegate : public QuicClientPushPromiseIndex::Delegate {
  public:
+  // |match| sets the validation result for checking whether designated header
+  // fields match for promise request and client request.
   explicit TestPushPromiseDelegate(bool match);
 
   bool CheckVary(const SpdyHeaderBlock& client_request,
diff --git a/net/quic/test_tools/simple_quic_framer.h b/net/quic/test_tools/simple_quic_framer.h
index d019f29..ba9e988d 100644
--- a/net/quic/test_tools/simple_quic_framer.h
+++ b/net/quic/test_tools/simple_quic_framer.h
@@ -5,13 +5,10 @@
 #ifndef NET_QUIC_TEST_TOOLS_SIMPLE_QUIC_FRAMER_H_
 #define NET_QUIC_TEST_TOOLS_SIMPLE_QUIC_FRAMER_H_
 
-#include <stddef.h>
-
 #include <memory>
 #include <vector>
 
 #include "base/macros.h"
-#include "base/strings/string_piece.h"
 #include "net/quic/core/quic_framer.h"
 #include "net/quic/core/quic_packets.h"
 
diff --git a/net/sdch/sdch_owner.cc b/net/sdch/sdch_owner.cc
index 047e666..2e17afa0 100644
--- a/net/sdch/sdch_owner.cc
+++ b/net/sdch/sdch_owner.cc
@@ -680,22 +680,8 @@
   ClearData();
 }
 
-void SdchOwner::OnMemoryStateChange(base::MemoryState state) {
-  // TODO(hajimehoshi): When the state changes, adjust the sizes of the caches
-  // to reduce the limits. SdchOwner doesn't have the ability to limit at
-  // present.
-  switch (state) {
-    case base::MemoryState::NORMAL:
-      break;
-    case base::MemoryState::THROTTLED:
-      ClearData();
-      break;
-    case base::MemoryState::SUSPENDED:
-    // Note: Not supported at present. Fall through.
-    case base::MemoryState::UNKNOWN:
-      NOTREACHED();
-      break;
-  }
+void SdchOwner::OnPurgeMemory() {
+  ClearData();
 }
 
 void SdchOwner::ClearData() {
diff --git a/net/sdch/sdch_owner.h b/net/sdch/sdch_owner.h
index bf208f6..35260a7 100644
--- a/net/sdch/sdch_owner.h
+++ b/net/sdch/sdch_owner.h
@@ -161,7 +161,7 @@
   };
 
   // base::MemoryCoordinatorClient implementation:
-  void OnMemoryStateChange(base::MemoryState state) override;
+  void OnPurgeMemory() override;
 
   void OnMemoryPressure(
       base::MemoryPressureListener::MemoryPressureLevel level);
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc
index b0fbb96..2ca4b24 100644
--- a/net/spdy/buffered_spdy_framer.cc
+++ b/net/spdy/buffered_spdy_framer.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 
 namespace net {
@@ -235,97 +236,70 @@
 
 // TODO(jgraettinger): Eliminate uses of this method (prefer
 // SpdyRstStreamIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreateRstStream(
+std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateRstStream(
     SpdyStreamId stream_id,
     SpdyErrorCode error_code) const {
   SpdyRstStreamIR rst_ir(stream_id, error_code);
-  return new SpdySerializedFrame(spdy_framer_.SerializeRstStream(rst_ir));
+  return base::MakeUnique<SpdySerializedFrame>(
+      spdy_framer_.SerializeRstStream(rst_ir));
 }
 
 // TODO(jgraettinger): Eliminate uses of this method (prefer
 // SpdySettingsIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreateSettings(
+std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateSettings(
     const SettingsMap& values) const {
   SpdySettingsIR settings_ir;
   for (SettingsMap::const_iterator it = values.begin(); it != values.end();
        ++it) {
     settings_ir.AddSetting(it->first, it->second);
   }
-  return new SpdySerializedFrame(spdy_framer_.SerializeSettings(settings_ir));
+  return base::MakeUnique<SpdySerializedFrame>(
+      spdy_framer_.SerializeSettings(settings_ir));
 }
 
 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPingIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreatePingFrame(SpdyPingId unique_id,
-                                                         bool is_ack) const {
+std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreatePingFrame(
+    SpdyPingId unique_id,
+    bool is_ack) const {
   SpdyPingIR ping_ir(unique_id);
   ping_ir.set_is_ack(is_ack);
-  return new SpdySerializedFrame(spdy_framer_.SerializePing(ping_ir));
-}
-
-// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyGoAwayIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreateGoAway(
-    SpdyStreamId last_accepted_stream_id,
-    SpdyErrorCode error_code,
-    base::StringPiece debug_data) const {
-  SpdyGoAwayIR go_ir(last_accepted_stream_id, error_code, debug_data);
-  return new SpdySerializedFrame(spdy_framer_.SerializeGoAway(go_ir));
-}
-
-// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyHeadersIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreateHeaders(
-    SpdyStreamId stream_id,
-    SpdyControlFlags flags,
-    int weight,
-    SpdyHeaderBlock headers) {
-  SpdyHeadersIR headers_ir(stream_id, std::move(headers));
-  headers_ir.set_fin((flags & CONTROL_FLAG_FIN) != 0);
-  if (flags & HEADERS_FLAG_PRIORITY) {
-    headers_ir.set_has_priority(true);
-    headers_ir.set_weight(weight);
-  }
-  return new SpdySerializedFrame(spdy_framer_.SerializeHeaders(headers_ir));
+  return base::MakeUnique<SpdySerializedFrame>(
+      spdy_framer_.SerializePing(ping_ir));
 }
 
 // TODO(jgraettinger): Eliminate uses of this method (prefer
 // SpdyWindowUpdateIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreateWindowUpdate(
+std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateWindowUpdate(
     SpdyStreamId stream_id,
     uint32_t delta_window_size) const {
   SpdyWindowUpdateIR update_ir(stream_id, delta_window_size);
-  return new SpdySerializedFrame(spdy_framer_.SerializeWindowUpdate(update_ir));
+  return base::MakeUnique<SpdySerializedFrame>(
+      spdy_framer_.SerializeWindowUpdate(update_ir));
 }
 
 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyDataIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
-                                                         const char* data,
-                                                         uint32_t len,
-                                                         SpdyDataFlags flags) {
+std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateDataFrame(
+    SpdyStreamId stream_id,
+    const char* data,
+    uint32_t len,
+    SpdyDataFlags flags) {
   SpdyDataIR data_ir(stream_id,
                      base::StringPiece(data, len));
   data_ir.set_fin((flags & DATA_FLAG_FIN) != 0);
-  return new SpdySerializedFrame(spdy_framer_.SerializeData(data_ir));
-}
-
-// TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPushPromiseIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreatePushPromise(
-    SpdyStreamId stream_id,
-    SpdyStreamId promised_stream_id,
-    SpdyHeaderBlock headers) {
-  SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id,
-                                    std::move(headers));
-  return new SpdySerializedFrame(
-      spdy_framer_.SerializePushPromise(push_promise_ir));
+  return base::MakeUnique<SpdySerializedFrame>(
+      spdy_framer_.SerializeData(data_ir));
 }
 
 // TODO(jgraettinger): Eliminate uses of this method (prefer
 // SpdyPriorityIR).
-SpdySerializedFrame* BufferedSpdyFramer::CreatePriority(
+std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreatePriority(
     SpdyStreamId stream_id,
     SpdyStreamId dependency_id,
     int weight,
     bool exclusive) const {
   SpdyPriorityIR priority_ir(stream_id, dependency_id, weight, exclusive);
-  return new SpdySerializedFrame(spdy_framer_.SerializePriority(priority_ir));
+  return base::MakeUnique<SpdySerializedFrame>(
+      spdy_framer_.SerializePriority(priority_ir));
 }
 
 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
diff --git a/net/spdy/buffered_spdy_framer.h b/net/spdy/buffered_spdy_framer.h
index 3c75122..7ab4fa3 100644
--- a/net/spdy/buffered_spdy_framer.h
+++ b/net/spdy/buffered_spdy_framer.h
@@ -181,30 +181,25 @@
   SpdyFramer::SpdyState state() const;
   bool MessageFullyRead();
   bool HasError();
-  SpdySerializedFrame* CreateRstStream(SpdyStreamId stream_id,
-                                       SpdyErrorCode error_code) const;
-  SpdySerializedFrame* CreateSettings(const SettingsMap& values) const;
-  SpdySerializedFrame* CreatePingFrame(SpdyPingId unique_id, bool is_ack) const;
-  SpdySerializedFrame* CreateGoAway(SpdyStreamId last_accepted_stream_id,
-                                    SpdyErrorCode error_code,
-                                    base::StringPiece debug_data) const;
-  SpdySerializedFrame* CreateHeaders(SpdyStreamId stream_id,
-                                     SpdyControlFlags flags,
-                                     int weight,
-                                     SpdyHeaderBlock headers);
-  SpdySerializedFrame* CreateWindowUpdate(SpdyStreamId stream_id,
-                                          uint32_t delta_window_size) const;
-  SpdySerializedFrame* CreateDataFrame(SpdyStreamId stream_id,
-                                       const char* data,
-                                       uint32_t len,
-                                       SpdyDataFlags flags);
-  SpdySerializedFrame* CreatePushPromise(SpdyStreamId stream_id,
-                                         SpdyStreamId promised_stream_id,
-                                         SpdyHeaderBlock headers);
-  SpdySerializedFrame* CreatePriority(SpdyStreamId stream_id,
-                                      SpdyStreamId dependency_id,
-                                      int weight,
-                                      bool exclusive) const;
+  std::unique_ptr<SpdySerializedFrame> CreateRstStream(
+      SpdyStreamId stream_id,
+      SpdyErrorCode error_code) const;
+  std::unique_ptr<SpdySerializedFrame> CreateSettings(
+      const SettingsMap& values) const;
+  std::unique_ptr<SpdySerializedFrame> CreatePingFrame(SpdyPingId unique_id,
+                                                       bool is_ack) const;
+  std::unique_ptr<SpdySerializedFrame> CreateWindowUpdate(
+      SpdyStreamId stream_id,
+      uint32_t delta_window_size) const;
+  std::unique_ptr<SpdySerializedFrame> CreateDataFrame(SpdyStreamId stream_id,
+                                                       const char* data,
+                                                       uint32_t len,
+                                                       SpdyDataFlags flags);
+  std::unique_ptr<SpdySerializedFrame> CreatePriority(
+      SpdyStreamId stream_id,
+      SpdyStreamId dependency_id,
+      int weight,
+      bool exclusive) const;
 
   // Serialize a frame of unknown type.
   SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame) {
diff --git a/net/spdy/buffered_spdy_framer_unittest.cc b/net/spdy/buffered_spdy_framer_unittest.cc
index e0a6414..d5752c7 100644
--- a/net/spdy/buffered_spdy_framer_unittest.cc
+++ b/net/spdy/buffered_spdy_framer_unittest.cc
@@ -196,16 +196,13 @@
   SpdyHeaderBlock headers;
   std::string long_header_value(256 * 1024, 'x');
   headers["foo"] = long_header_value;
+  SpdyHeadersIR headers_ir(/*stream_id=*/1, std::move(headers));
+
   BufferedSpdyFramer framer;
-  std::unique_ptr<SpdySerializedFrame> control_frame(
-      framer.CreateHeaders(1,  // stream_id
-                           CONTROL_FLAG_NONE,
-                           255,  // weight
-                           std::move(headers)));
-  EXPECT_TRUE(control_frame);
+  SpdySerializedFrame control_frame = framer.SerializeFrame(headers_ir);
 
   TestBufferedSpdyVisitor visitor;
-  visitor.SimulateInFramer(*control_frame);
+  visitor.SimulateInFramer(control_frame);
 
   EXPECT_EQ(1, visitor.error_count_);
   EXPECT_EQ(0, visitor.headers_frame_count_);
@@ -240,16 +237,13 @@
   SpdyHeaderBlock headers;
   headers["alpha"] = "beta";
   headers["gamma"] = "delta";
+  SpdyHeadersIR headers_ir(/*stream_id=*/1, headers.Clone());
+
   BufferedSpdyFramer framer;
-  std::unique_ptr<SpdySerializedFrame> control_frame(
-      framer.CreateHeaders(1,  // stream_id
-                           CONTROL_FLAG_NONE,
-                           255,  // weight
-                           headers.Clone()));
-  EXPECT_TRUE(control_frame.get() != NULL);
+  SpdySerializedFrame control_frame = framer.SerializeFrame(headers_ir);
 
   TestBufferedSpdyVisitor visitor;
-  visitor.SimulateInFramer(*control_frame);
+  visitor.SimulateInFramer(control_frame);
   EXPECT_EQ(0, visitor.error_count_);
   EXPECT_EQ(1, visitor.headers_frame_count_);
   EXPECT_EQ(0, visitor.push_promise_frame_count_);
@@ -261,12 +255,12 @@
   headers["alpha"] = "beta";
   headers["gamma"] = "delta";
   BufferedSpdyFramer framer;
-  std::unique_ptr<SpdySerializedFrame> control_frame(
-      framer.CreatePushPromise(1, 2, headers.Clone()));
-  EXPECT_TRUE(control_frame.get() != NULL);
+  SpdyPushPromiseIR push_promise_ir(/*stream_id=*/1, /*promised_stream_id=*/2,
+                                    headers.Clone());
+  SpdySerializedFrame control_frame = framer.SerializeFrame(push_promise_ir);
 
   TestBufferedSpdyVisitor visitor;
-  visitor.SimulateInFramer(*control_frame);
+  visitor.SimulateInFramer(control_frame);
   EXPECT_EQ(0, visitor.error_count_);
   EXPECT_EQ(0, visitor.headers_frame_count_);
   EXPECT_EQ(1, visitor.push_promise_frame_count_);
@@ -276,12 +270,13 @@
 }
 
 TEST_F(BufferedSpdyFramerTest, GoAwayDebugData) {
+  SpdyGoAwayIR go_ir(/*last_accepted_stream_id=*/2, ERROR_CODE_FRAME_SIZE_ERROR,
+                     "foo");
   BufferedSpdyFramer framer;
-  std::unique_ptr<SpdySerializedFrame> goaway_frame(
-      framer.CreateGoAway(2u, ERROR_CODE_FRAME_SIZE_ERROR, "foo"));
+  SpdySerializedFrame goaway_frame = framer.SerializeFrame(go_ir);
 
   TestBufferedSpdyVisitor visitor;
-  visitor.SimulateInFramer(*goaway_frame);
+  visitor.SimulateInFramer(goaway_frame);
   EXPECT_EQ(0, visitor.error_count_);
   EXPECT_EQ(1, visitor.goaway_count_);
   EXPECT_EQ(2u, visitor.goaway_last_accepted_stream_id_);
diff --git a/net/ssl/ssl_client_session_cache.cc b/net/ssl/ssl_client_session_cache.cc
index 4cb6c9ae..b007469 100644
--- a/net/ssl/ssl_client_session_cache.cc
+++ b/net/ssl/ssl_client_session_cache.cc
@@ -177,22 +177,8 @@
   }
 }
 
-void SSLClientSessionCache::OnMemoryStateChange(base::MemoryState state) {
-  // TODO(hajimehoshi): When the state changes, adjust the sizes of the caches
-  // to reduce the limits. SSLClientSessionCache doesn't have the ability to
-  // limit at present.
-  switch (state) {
-    case base::MemoryState::NORMAL:
-      break;
-    case base::MemoryState::THROTTLED:
-      Flush();
-      break;
-    case base::MemoryState::SUSPENDED:
-    // Note: Not supported at present. Fall through.
-    case base::MemoryState::UNKNOWN:
-      NOTREACHED();
-      break;
-  }
+void SSLClientSessionCache::OnPurgeMemory() {
+  Flush();
 }
 
 }  // namespace net
diff --git a/net/ssl/ssl_client_session_cache.h b/net/ssl/ssl_client_session_cache.h
index 0cfefc31..009c980b 100644
--- a/net/ssl/ssl_client_session_cache.h
+++ b/net/ssl/ssl_client_session_cache.h
@@ -80,7 +80,7 @@
   };
 
   // base::MemoryCoordinatorClient implementation:
-  void OnMemoryStateChange(base::MemoryState state) override;
+  void OnPurgeMemory() override;
 
   // Returns true if |entry| is expired as of |now|.
   bool IsExpired(SSL_SESSION* session, time_t now);
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/Contents.json
new file mode 100644
index 0000000..76e6b85
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_keyboard_arrow_left_white_1x_ios_36dp.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_keyboard_arrow_left_white_2x_ios_36dp.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_keyboard_arrow_left_white_3x_ios_36dp.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_1x_ios_36dp.png b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_1x_ios_36dp.png
new file mode 100644
index 0000000..e9a1ed9
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_1x_ios_36dp.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_2x_ios_36dp.png b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_2x_ios_36dp.png
new file mode 100644
index 0000000..d8af01c8
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_2x_ios_36dp.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_3x_ios_36dp.png b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_3x_ios_36dp.png
new file mode 100644
index 0000000..3b1cf4ae
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Back.imageset/ic_keyboard_arrow_left_white_3x_ios_36dp.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164c
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/Contents.json
new file mode 100644
index 0000000..6b283d8
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_settings_white_1x_ios_24dp.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_settings_white_2x_ios_24dp.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_settings_white_3x_ios_24dp.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_1x_ios_24dp.png b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_1x_ios_24dp.png
new file mode 100644
index 0000000..8909c35
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_1x_ios_24dp.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_2x_ios_24dp.png b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_2x_ios_24dp.png
new file mode 100644
index 0000000..5caedc8e
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_2x_ios_24dp.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_3x_ios_24dp.png b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_3x_ios_24dp.png
new file mode 100644
index 0000000..eabb0a2b
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/Settings.imageset/ic_settings_white_3x_ios_24dp.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/Contents.json
new file mode 100644
index 0000000..78dd22b11
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_desktop.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_desktop@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_desktop@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop.png
new file mode 100644
index 0000000..bf893aad
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop@2x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop@2x.png
new file mode 100644
index 0000000..bd811e6
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop@2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop@3x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop@3x.png
new file mode 100644
index 0000000..fbcec23
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop.imageset/ic_desktop@3x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/Contents.json
new file mode 100644
index 0000000..e9c4c8b
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_desktop_windows.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_desktop_windows@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_desktop_windows@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows.png
new file mode 100644
index 0000000..72a21bb
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@2x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@2x.png
new file mode 100644
index 0000000..a6cd393
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@3x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@3x.png
new file mode 100644
index 0000000..0567bf3
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@3x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/Contents.json
new file mode 100644
index 0000000..4a68ae8
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_fullscreen.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_fullscreen@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_fullscreen@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen.png
new file mode 100644
index 0000000..3553d6a
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@2x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@2x.png
new file mode 100644
index 0000000..917e418a
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@3x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@3x.png
new file mode 100644
index 0000000..66a373c
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@3x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/Contents.json
new file mode 100644
index 0000000..93f5d79
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_fullscreen_exit.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_fullscreen_exit@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_fullscreen_exit@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit.png
new file mode 100644
index 0000000..c839448
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@2x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@2x.png
new file mode 100644
index 0000000..5fc3166a
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@3x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@3x.png
new file mode 100644
index 0000000..5691b55
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@3x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/Contents.json
new file mode 100644
index 0000000..5596401b
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "ic_mouse.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_mouse@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "ic_mouse@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse.png
new file mode 100644
index 0000000..5e06433f
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse@2x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse@2x.png
new file mode 100644
index 0000000..aff1d9c
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse@2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse@3x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse@3x.png
new file mode 100644
index 0000000..deac754
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_mouse.imageset/ic_mouse@3x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/Contents.json b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/Contents.json
new file mode 100644
index 0000000..577dee7
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/Contents.json
@@ -0,0 +1,24 @@
+{
+    "images": [
+        {
+            "filename": "ic_touch_app.png",
+            "idiom": "universal",
+            "scale": "1x"
+        },
+        {
+            "filename": "ic_touch_app_2x.png",
+            "idiom": "universal",
+            "scale": "2x"
+        },
+        {
+            "filename": "ic_touch_app_3x.png",
+            "idiom": "universal",
+            "scale": "3x"
+        }
+    ],
+    "info": {
+        "author": "xcode",
+        "template-rendering-intent": "template",
+        "version": 1
+    }
+}
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app.png
new file mode 100644
index 0000000..37b6c67
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app_2x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app_2x.png
new file mode 100644
index 0000000..e697790
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app_2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app_3x.png b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app_3x.png
new file mode 100644
index 0000000..850daa3
--- /dev/null
+++ b/remoting/client/ios/app/resources/Assets.xcassets/ic_touch_app.imageset/ic_touch_app_3x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/BUILD.gn b/remoting/client/ios/app/resources/BUILD.gn
new file mode 100644
index 0000000..5f15eb3
--- /dev/null
+++ b/remoting/client/ios/app/resources/BUILD.gn
@@ -0,0 +1,74 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/chrome_build.gni")
+import("//build/config/ios/rules.gni")
+import("//remoting/build/config/remoting_build.gni")
+
+bundle_data("assets") {
+  sources = [
+    "Assets.xcassets/ic_desktop.imageset/Contents.json",
+    "Assets.xcassets/ic_desktop.imageset/ic_desktop.png",
+    "Assets.xcassets/ic_desktop.imageset/ic_desktop@2x.png",
+    "Assets.xcassets/ic_desktop.imageset/ic_desktop@3x.png",
+    "Assets.xcassets/ic_desktop_windows.imageset/Contents.json",
+    "Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows.png",
+    "Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@2x.png",
+    "Assets.xcassets/ic_desktop_windows.imageset/ic_desktop_windows@3x.png",
+    "Assets.xcassets/ic_fullscreen.imageset/Contents.json",
+    "Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen.png",
+    "Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@2x.png",
+    "Assets.xcassets/ic_fullscreen.imageset/ic_fullscreen@3x.png",
+    "Assets.xcassets/ic_fullscreen_exit.imageset/Contents.json",
+    "Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit.png",
+    "Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@2x.png",
+    "Assets.xcassets/ic_fullscreen_exit.imageset/ic_fullscreen_exit@3x.png",
+    "Assets.xcassets/ic_mouse.imageset/Contents.json",
+    "Assets.xcassets/ic_mouse.imageset/ic_mouse.png",
+    "Assets.xcassets/ic_mouse.imageset/ic_mouse@2x.png",
+    "Assets.xcassets/ic_mouse.imageset/ic_mouse@3x.png",
+    "Assets.xcassets/ic_touch_app.imageset/Contents.json",
+    "Assets.xcassets/ic_touch_app.imageset/ic_touch_app.png",
+    "Assets.xcassets/ic_touch_app.imageset/ic_touch_app_2x.png",
+    "Assets.xcassets/ic_touch_app.imageset/ic_touch_app_3x.png",
+  ]
+  outputs = [
+    "{{bundle_resources_dir}}/{{source_file_part}}",
+  ]
+}
+
+bundle_data("launchscreen_assets") {
+  sources = [
+    "launchscreen_images.xcassets/Contents.json",
+    "launchscreen_images.xcassets/launchscreen_app_logo.imageset/Contents.json",
+    "launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo.png",
+    "launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@2x.png",
+    "launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@3x.png",
+    "launchscreen_images.xcassets/launchscreen_brand_name.imageset/Contents.json",
+    "launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name.png",
+    "launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@2x.png",
+    "launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@3x.png",
+  ]
+  outputs = [
+    "{{bundle_resources_dir}}/{{source_file_part}}",
+  ]
+}
+
+bundle_data("remoting_icons") {
+  sources = [
+    "chromium/Icon-120.png",
+    "chromium/Icon-152.png",
+    "chromium/Icon-167.png",
+    "chromium/Icon-180.png",
+    "chromium/Icon-29.png",
+    "chromium/Icon-40.png",
+    "chromium/Icon-58.png",
+    "chromium/Icon-76.png",
+    "chromium/Icon-80.png",
+    "chromium/Icon-87.png",
+  ]
+  outputs = [
+    "{{bundle_resources_dir}}/{{source_file_part}}",
+  ]
+}
diff --git a/remoting/client/ios/app/resources/Info.plist b/remoting/client/ios/app/resources/Info.plist
index 4033728f..094e8bd 100644
--- a/remoting/client/ios/app/resources/Info.plist
+++ b/remoting/client/ios/app/resources/Info.plist
@@ -22,6 +22,38 @@
 	<string>????</string>
 	<key>CFBundleVersion</key>
 	<string>${VERSION_FULL}</string>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+  <key>CFBundleIcons</key>
+		<dict>
+			<key>CFBundlePrimaryIcon</key>
+			<dict>
+				<key>CFBundleIconFiles</key>
+				<array>
+					<string>Icon-120.png</string>
+					<string>Icon-152.png</string>
+					<string>Icon-167.png</string>
+					<string>Icon-180.png</string>
+					<string>Icon-29.png</string>
+					<string>Icon-40.png</string>
+					<string>Icon-58.png</string>
+					<string>Icon-76.png</string>
+					<string>Icon-80.png</string>
+					<string>Icon-87.png</string>
+				</array>
+				<key>UIPrerenderedIcon</key>
+				<true/>
+			</dict>
+		</dict>
+	<key>CFBundleURLTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleURLSchemes</key>
+			<array>
+				<string>crd</string>
+			</array>
+		</dict>
+	</array>
 	<key>LSRequiresIPhoneOS</key>
 	<true/>
 	<key>MinimumOSVersion</key>
diff --git a/remoting/client/ios/app/resources/LaunchScreen.storyboard b/remoting/client/ios/app/resources/LaunchScreen.storyboard
new file mode 100644
index 0000000..6ecb008c
--- /dev/null
+++ b/remoting/client/ios/app/resources/LaunchScreen.storyboard
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CDr-2c-Hcj" image="launchscreen_app_logo">
+                                <rect key="frame" x="127" y="274" width="120" height="120"/>
+                                <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
+                            </imageView>
+                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gJ9-5V-g0g" image="launchscreen_brand_name">
+                                <rect key="frame" x="127" y="575" width="120" height="60"/>
+                                <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES"/>
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="52" y="374.66266866566718"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/remoting/client/ios/app/resources/chromium/Icon-120.png b/remoting/client/ios/app/resources/chromium/Icon-120.png
new file mode 100644
index 0000000..5a07aa8
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-120.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-152.png b/remoting/client/ios/app/resources/chromium/Icon-152.png
new file mode 100644
index 0000000..0955ae50
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-152.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-167.png b/remoting/client/ios/app/resources/chromium/Icon-167.png
new file mode 100644
index 0000000..aed5d75
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-167.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-180.png b/remoting/client/ios/app/resources/chromium/Icon-180.png
new file mode 100644
index 0000000..5a178305
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-180.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-29.png b/remoting/client/ios/app/resources/chromium/Icon-29.png
new file mode 100644
index 0000000..cf7fc7c
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-29.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-40.png b/remoting/client/ios/app/resources/chromium/Icon-40.png
new file mode 100644
index 0000000..c8e93ee
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-40.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-58.png b/remoting/client/ios/app/resources/chromium/Icon-58.png
new file mode 100644
index 0000000..23aa346
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-58.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-76.png b/remoting/client/ios/app/resources/chromium/Icon-76.png
new file mode 100644
index 0000000..8374ca9
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-76.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-80.png b/remoting/client/ios/app/resources/chromium/Icon-80.png
new file mode 100644
index 0000000..0423d66
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-80.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/chromium/Icon-87.png b/remoting/client/ios/app/resources/chromium/Icon-87.png
new file mode 100644
index 0000000..87cf01829
--- /dev/null
+++ b/remoting/client/ios/app/resources/chromium/Icon-87.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/Contents.json b/remoting/client/ios/app/resources/launchscreen_images.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164c
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/Contents.json b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/Contents.json
new file mode 100644
index 0000000..5829c45
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "launchscreen_app_logo.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "launchscreen_app_logo@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "launchscreen_app_logo@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo.png b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo.png
new file mode 100644
index 0000000..2e7cac0f
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@2x.png b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@2x.png
new file mode 100644
index 0000000..5a07aa8
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@3x.png b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@3x.png
new file mode 100644
index 0000000..bac238a
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_app_logo.imageset/launchscreen_app_logo@3x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/Contents.json b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/Contents.json
new file mode 100644
index 0000000..e7ef874
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "launchscreen_brand_name.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "launchscreen_brand_name@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "launchscreen_brand_name@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name.png b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name.png
new file mode 100644
index 0000000..5d986db
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@2x.png b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@2x.png
new file mode 100644
index 0000000..5ee4779
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@2x.png
Binary files differ
diff --git a/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@3x.png b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@3x.png
new file mode 100644
index 0000000..38941e3
--- /dev/null
+++ b/remoting/client/ios/app/resources/launchscreen_images.xcassets/launchscreen_brand_name.imageset/launchscreen_brand_name@3x.png
Binary files differ
diff --git a/remoting/client/ios/app_runtime.cc b/remoting/client/ios/app_runtime.cc
index 5e0ad6b82..36b75d3 100644
--- a/remoting/client/ios/app_runtime.cc
+++ b/remoting/client/ios/app_runtime.cc
@@ -31,7 +31,7 @@
 AppRuntime::AppRuntime() {
   // TODO(sergeyu): Consider adding separate pools for different task classes.
   const int kMaxBackgroundThreads = 5;
-  if (TaskScheduler::GetInstance()) {
+  if (!TaskScheduler::GetInstance()) {
     // Make sure TaskScheduler is initialized.
     base::TaskScheduler::CreateAndSetSimpleTaskScheduler(kMaxBackgroundThreads);
   }
diff --git a/remoting/client/jni/chromoting_jni_runtime.cc b/remoting/client/jni/chromoting_jni_runtime.cc
index c581653..201683e 100644
--- a/remoting/client/jni/chromoting_jni_runtime.cc
+++ b/remoting/client/jni/chromoting_jni_runtime.cc
@@ -111,6 +111,10 @@
       FROM_HERE, base::Bind(&ChromotingJniRuntime::DetachFromVmAndSignal,
                             base::Unretained(this), &done_event));
   done_event.Wait();
+
+  // Block until tasks blocking shutdown have completed their execution.
+  base::TaskScheduler::GetInstance()->Shutdown();
+
   base::android::LibraryLoaderExitHook();
   base::android::DetachFromVM();
 }
diff --git a/remoting/host/it2me/it2me_native_messaging_host_main.cc b/remoting/host/it2me/it2me_native_messaging_host_main.cc
index b6451df..0bf0eef 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_main.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_main.cc
@@ -200,6 +200,9 @@
   // Run the loop until channel is alive.
   run_loop.Run();
 
+  // Block until tasks blocking shutdown have completed their execution.
+  base::TaskScheduler::GetInstance()->Shutdown();
+
   return kSuccessExitCode;
 }
 
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index 66d1a43..d4851ad 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -1670,6 +1670,9 @@
   // Run the main (also UI) message loop until the host no longer needs it.
   base::RunLoop().Run();
 
+  // Block until tasks blocking shutdown have completed their execution.
+  base::TaskScheduler::GetInstance()->Shutdown();
+
   return exit_code;
 }
 
diff --git a/remoting/host/setup/me2me_native_messaging_host_main.cc b/remoting/host/setup/me2me_native_messaging_host_main.cc
index 70eaa02..f94b2c5 100644
--- a/remoting/host/setup/me2me_native_messaging_host_main.cc
+++ b/remoting/host/setup/me2me_native_messaging_host_main.cc
@@ -269,6 +269,10 @@
 
   // Run the loop until channel is alive.
   run_loop.Run();
+
+  // Block until tasks blocking shutdown have completed their execution.
+  base::TaskScheduler::GetInstance()->Shutdown();
+
   return kSuccessExitCode;
 }
 
diff --git a/sandbox/mac/BUILD.gn b/sandbox/mac/BUILD.gn
index fd53131..5174b54 100644
--- a/sandbox/mac/BUILD.gn
+++ b/sandbox/mac/BUILD.gn
@@ -35,6 +35,8 @@
 
 component("seatbelt") {
   sources = [
+    "sandbox_compiler.cc",
+    "sandbox_compiler.h",
     "seatbelt.cc",
     "seatbelt.h",
     "seatbelt_export.h",
@@ -47,6 +49,8 @@
   sources = [
     "bootstrap_sandbox_unittest.mm",
     "policy_unittest.cc",
+    "sandbox_mac_compiler_unittest.mm",
+    "sandbox_mac_compiler_v2_unittest.mm",
     "xpc_message_server_unittest.cc",
   ]
 
@@ -57,6 +61,7 @@
 
   deps = [
     ":sandbox",
+    ":seatbelt",
     "//base",
     "//base/test:run_all_unittests",
     "//testing/gtest",
diff --git a/sandbox/mac/sandbox_compiler.cc b/sandbox/mac/sandbox_compiler.cc
new file mode 100644
index 0000000..e524aa7
--- /dev/null
+++ b/sandbox/mac/sandbox_compiler.cc
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/mac/sandbox_compiler.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "sandbox/mac/seatbelt.h"
+
+namespace sandbox {
+
+SandboxCompiler::SandboxCompiler(const std::string& profile_str)
+    : params_map_(), profile_str_(profile_str) {}
+
+SandboxCompiler::~SandboxCompiler() {}
+
+bool SandboxCompiler::InsertBooleanParam(const std::string& key, bool value) {
+  return params_map_.insert(std::make_pair(key, value ? "TRUE" : "FALSE"))
+      .second;
+}
+
+bool SandboxCompiler::InsertStringParam(const std::string& key,
+                                        const std::string& value) {
+  return params_map_.insert(std::make_pair(key, value)).second;
+}
+
+bool SandboxCompiler::CompileAndApplyProfile(std::string* error) {
+  char* error_internal = nullptr;
+  std::vector<const char*> params;
+
+  for (const auto& kv : params_map_) {
+    params.push_back(kv.first.c_str());
+    params.push_back(kv.second.c_str());
+  }
+  // The parameters array must be null terminated.
+  params.push_back(static_cast<const char*>(0));
+
+  if (sandbox::Seatbelt::InitWithParams(profile_str_.c_str(), 0, params.data(),
+                                        &error_internal)) {
+    error->assign(error_internal);
+    sandbox::Seatbelt::FreeError(error_internal);
+    return false;
+  }
+  return true;
+}
+
+}  // namespace sandbox
diff --git a/sandbox/mac/sandbox_compiler.h b/sandbox/mac/sandbox_compiler.h
new file mode 100644
index 0000000..826dc8e
--- /dev/null
+++ b/sandbox/mac/sandbox_compiler.h
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_MAC_SANDBOX_COMPILER_H_
+#define SANDBOX_MAC_SANDBOX_COMPILER_H_
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "sandbox/mac/seatbelt_export.h"
+
+namespace sandbox {
+
+// This class wraps the C-style sandbox APIs in a class to ensure proper
+// initialization and cleanup.
+class SEATBELT_EXPORT SandboxCompiler {
+ public:
+  explicit SandboxCompiler(const std::string& profile_str);
+
+  ~SandboxCompiler();
+
+  // Inserts a boolean into the parameters key/value map. A duplicate key is not
+  // allowed, and will cause the function to return false. The value is not
+  // inserted in this case.
+  bool InsertBooleanParam(const std::string& key, bool value);
+
+  // Inserts a string into the parameters key/value map. A duplicate key is not
+  // allowed, and will cause the function to return false. The value is not
+  // inserted in this case.
+  bool InsertStringParam(const std::string& key, const std::string& value);
+
+  // Compiles and applies the profile; returns true on success.
+  bool CompileAndApplyProfile(std::string* error);
+
+ private:
+  // Storage of the key/value pairs of strings that are used in the sandbox
+  // profile.
+  std::map<std::string, std::string> params_map_;
+
+  // The sandbox profile source code.
+  const std::string profile_str_;
+
+  DISALLOW_COPY_AND_ASSIGN(SandboxCompiler);
+};
+
+}  // namespace sandbox
+
+#endif  // SANDBOX_MAC_SANDBOX_COMPILER_H_
diff --git a/content/common/sandbox_mac_compiler_unittest.mm b/sandbox/mac/sandbox_mac_compiler_unittest.mm
similarity index 97%
rename from content/common/sandbox_mac_compiler_unittest.mm
rename to sandbox/mac/sandbox_mac_compiler_unittest.mm
index 34684dd..404bf4bb 100644
--- a/content/common/sandbox_mac_compiler_unittest.mm
+++ b/sandbox/mac/sandbox_mac_compiler_unittest.mm
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/common/sandbox_mac.h"
-
 #include <fcntl.h>
 #include <stdint.h>
 #include <sys/stat.h>
@@ -12,10 +10,11 @@
 #include "base/process/kill.h"
 #include "base/test/multiprocess_test.h"
 #include "base/test/test_timeouts.h"
+#include "sandbox/mac/sandbox_compiler.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/multiprocess_func_list.h"
 
-namespace content {
+namespace sandbox {
 
 class SandboxMacCompilerTest : public base::MultiProcessTest {};
 
@@ -158,4 +157,4 @@
   EXPECT_EQ(exit_code, 0);
 }
 
-}  // namespace content
+}  // namespace sandbox
diff --git a/sandbox/mac/sandbox_mac_compiler_v2_unittest.mm b/sandbox/mac/sandbox_mac_compiler_v2_unittest.mm
new file mode 100644
index 0000000..aba42ed
--- /dev/null
+++ b/sandbox/mac/sandbox_mac_compiler_v2_unittest.mm
@@ -0,0 +1,137 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+#import <IOSurface/IOSurface.h>
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <unistd.h>
+
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/mac/mac_util.h"
+#include "base/process/kill.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
+#include "sandbox/mac/sandbox_compiler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
+
+namespace sandbox {
+
+// These tests are designed to begin testing the V2 style sandbox rules on the
+// bots, rendering the earliest possible test results on how the rules perform
+// consistently across all test bots and supported OS versions.
+class SandboxMacCompilerV2Test : public base::MultiProcessTest {};
+
+MULTIPROCESS_TEST_MAIN(V2ProfileProcess) {
+  // Note: newlines are not necessary in the profile, but do make it easier to
+  // print the profile out for debugging purposes.
+  std::string profile =
+      "(version 1)\n"
+      "(deny default)\n"
+      "(define allowed-dir \"ALLOWED_READ_DIR\")\n"
+      "(define temp-file \"ALLOWED_TEMP_FILE\")\n"
+      "(define is-pre-10_10 \"IS_PRE_10_10\")\n"
+      "; Make it easier to drop (literal) once we stop supporting 10.9\n"
+      "(define (path x) (literal x))\n"
+      "(allow file-read-metadata (subpath \"/Applications\"))\n"
+      "(allow file-read* (subpath (param allowed-dir)))\n"
+      "(allow file-read-data (path \"/usr/share/zoneinfo/zone.tab\"))\n"
+      "(allow file-write* (path (param temp-file)))\n"
+      "(allow ipc-posix-shm-read-data (ipc-posix-name "
+      "\"apple.shm.notification_center\"))\n"
+      "(allow mach-lookup (global-name \"com.apple.logd\"))\n"
+      "(if (string=? (param is-pre-10_10) \"TRUE\") (allow sysctl-read))\n"
+      "(if (string=? (param is-pre-10_10) \"FALSE\") (allow sysctl-read "
+      "(sysctl-name \"hw.activecpu\")))\n";
+
+  std::string temp_file_path = "/private/tmp/sf234234wfsfsdfdsf";
+  SandboxCompiler compiler(profile);
+  CHECK(compiler.InsertStringParam("ALLOWED_READ_DIR", "/usr/lib"));
+  CHECK(compiler.InsertStringParam("ALLOWED_TEMP_FILE", temp_file_path));
+  CHECK(compiler.InsertBooleanParam("IS_PRE_10_10",
+                                    !base::mac::IsAtLeastOS10_10()));
+
+  std::string error;
+  bool result = compiler.CompileAndApplyProfile(&error);
+  CHECK(result) << error;
+
+  // Now attempt the appropriate resource access.
+  base::FilePath path("/usr/lib/libsandbox.dylib");
+  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  CHECK(file.IsValid());
+
+  char buf[4096];
+  EXPECT_EQ(static_cast<int>(sizeof(buf)),
+            file.Read(/*offset=*/0, buf, sizeof(buf)));
+  file.Close();  // Protect again other checks accidentally using this file.
+
+  struct stat sb;
+  EXPECT_EQ(0, stat("/Applications/TextEdit.app", &sb));
+
+  base::FilePath zone_path("/usr/share/zoneinfo/zone.tab");
+  base::File zone_file(zone_path,
+                       base::File::FLAG_OPEN | base::File::FLAG_READ);
+  CHECK(zone_file.IsValid());
+
+  char zone_buf[2];
+  EXPECT_EQ(static_cast<int>(sizeof(zone_buf)),
+            zone_file.Read(/*offset=*/0, zone_buf, sizeof(zone_buf)));
+  zone_file.Close();
+
+  // Make sure we cannot read any files in zoneinfo.
+  base::FilePath zone_dir_path("/usr/share/zoneinfo");
+  base::File zoneinfo(zone_dir_path,
+                      base::File::FLAG_OPEN | base::File::FLAG_READ);
+  EXPECT_FALSE(zoneinfo.IsValid());
+
+  base::FilePath temp_path(temp_file_path);
+  base::File temp_file(temp_path,
+                       base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE);
+  CHECK(temp_file.IsValid());
+
+  const char msg[] = "I can write this file.";
+  EXPECT_EQ(static_cast<int>(sizeof(msg)),
+            temp_file.WriteAtCurrentPos(msg, sizeof(msg)));
+  temp_file.Close();
+
+  int shm_fd = shm_open("apple.shm.notification_center", O_RDONLY, 0644);
+  EXPECT_GE(shm_fd, 0);
+
+  NSPort* mach = [[NSMachBootstrapServer sharedInstance]
+      servicePortWithName:@"com.apple.logd"];
+  EXPECT_NE(nil, mach);
+
+  NSPort* forbidden_mach = [[NSMachBootstrapServer sharedInstance]
+      servicePortWithName:@"com.apple.fonts."];
+  EXPECT_EQ(nil, forbidden_mach);
+
+  size_t oldp_len;
+  EXPECT_EQ(0, sysctlbyname("hw.activecpu", NULL, &oldp_len, NULL, 0));
+
+  char oldp[oldp_len];
+  EXPECT_EQ(0, sysctlbyname("hw.activecpu", oldp, &oldp_len, NULL, 0));
+
+  size_t ncpu_len;
+  EXPECT_NE(0, sysctlbyname("hw.ncpu", NULL, &ncpu_len, NULL, 0));
+
+  return 0;
+}
+
+TEST_F(SandboxMacCompilerV2Test, V2ProfileTest) {
+  base::Process process = SpawnChild("V2ProfileProcess");
+  ASSERT_TRUE(process.IsValid());
+  int exit_code = 42;
+  EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
+                                             &exit_code));
+  EXPECT_EQ(exit_code, 0);
+}
+
+}  // namespace sandbox
diff --git a/services/BUILD.gn b/services/BUILD.gn
index 39efe0d..38f150c 100644
--- a/services/BUILD.gn
+++ b/services/BUILD.gn
@@ -15,6 +15,7 @@
 # entries in the "service_unittests_catalog" target below.
 service_test("service_unittests") {
   deps = [
+    "//services/device:tests",
     "//services/image_decoder:tests",
     "//services/memory_instrumentation:tests",
   ]
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn
index c327365..44681f24 100644
--- a/services/device/BUILD.gn
+++ b/services/device/BUILD.gn
@@ -13,8 +13,8 @@
 
   deps = [
     "//base",
-    "//device/power_monitor",
     "//device/time_zone_monitor",
+    "//services/device/power_monitor",
     "//services/service_manager/public/cpp",
   ]
 
@@ -26,6 +26,24 @@
   ]
 }
 
+source_set("tests") {
+  testonly = true
+
+  sources = [
+    "power_monitor/power_monitor_message_broadcaster_unittest.cc",
+    "public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc",
+  ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//mojo/public/cpp/bindings",
+    "//services/device/power_monitor",
+    "//services/device/public/cpp/power_monitor",
+    "//testing/gtest",
+  ]
+}
+
 service_manifest("manifest") {
   name = "device"
   source = "manifest.json"
diff --git a/services/device/device_service.cc b/services/device/device_service.cc
index 229695f..4cf73987 100644
--- a/services/device/device_service.cc
+++ b/services/device/device_service.cc
@@ -8,8 +8,8 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "device/power_monitor/power_monitor_message_broadcaster.h"
 #include "device/time_zone_monitor/time_zone_monitor.h"
+#include "services/device/power_monitor/power_monitor_message_broadcaster.h"
 #include "services/service_manager/public/cpp/connection.h"
 #include "services/service_manager/public/cpp/interface_registry.h"
 
diff --git a/services/device/device_service.h b/services/device/device_service.h
index e08b632..bb5fe94 100644
--- a/services/device/device_service.h
+++ b/services/device/device_service.h
@@ -6,9 +6,9 @@
 #define SERVICES_DEVICE_DEVICE_SERVICE_H_
 
 #include "base/memory/ref_counted.h"
-#include "device/power_monitor/public/interfaces/power_monitor.mojom.h"
 #include "device/time_zone_monitor/public/interfaces/time_zone_monitor.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/device/public/interfaces/power_monitor.mojom.h"
 #include "services/service_manager/public/cpp/interface_factory.h"
 #include "services/service_manager/public/cpp/service.h"
 
diff --git a/device/power_monitor/BUILD.gn b/services/device/power_monitor/BUILD.gn
similarity index 71%
rename from device/power_monitor/BUILD.gn
rename to services/device/power_monitor/BUILD.gn
index a799e01..5515623d 100644
--- a/device/power_monitor/BUILD.gn
+++ b/services/device/power_monitor/BUILD.gn
@@ -4,21 +4,20 @@
 
 import("//build/config/features.gni")
 
-component("power_monitor") {
+source_set("power_monitor") {
+  visibility = [ "//services/device:*" ]
+
   sources = [
-    "power_monitor_export.h",
     "power_monitor_message_broadcaster.cc",
     "power_monitor_message_broadcaster.h",
   ]
 
-  defines = [ "DEVICE_POWER_MONITOR_IMPLEMENTATION" ]
-
   deps = [
     "//base",
     "//mojo/public/cpp/bindings",
   ]
 
   public_deps = [
-    "//device/power_monitor/public/interfaces",
+    "//services/device/public/interfaces",
   ]
 }
diff --git a/device/power_monitor/OWNERS b/services/device/power_monitor/OWNERS
similarity index 100%
rename from device/power_monitor/OWNERS
rename to services/device/power_monitor/OWNERS
diff --git a/device/power_monitor/power_monitor_message_broadcaster.cc b/services/device/power_monitor/power_monitor_message_broadcaster.cc
similarity index 95%
rename from device/power_monitor/power_monitor_message_broadcaster.cc
rename to services/device/power_monitor/power_monitor_message_broadcaster.cc
index e8f1b1b..8361caea 100644
--- a/device/power_monitor/power_monitor_message_broadcaster.cc
+++ b/services/device/power_monitor/power_monitor_message_broadcaster.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 "device/power_monitor/power_monitor_message_broadcaster.h"
+#include "services/device/power_monitor/power_monitor_message_broadcaster.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/power_monitor/power_monitor.h"
diff --git a/device/power_monitor/power_monitor_message_broadcaster.h b/services/device/power_monitor/power_monitor_message_broadcaster.h
similarity index 66%
rename from device/power_monitor/power_monitor_message_broadcaster.h
rename to services/device/power_monitor/power_monitor_message_broadcaster.h
index f6e1928..41ea658e 100644
--- a/device/power_monitor/power_monitor_message_broadcaster.h
+++ b/services/device/power_monitor/power_monitor_message_broadcaster.h
@@ -2,21 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
-#define DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
+#ifndef SERVICES_DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
+#define SERVICES_DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
 
 #include "base/macros.h"
 #include "base/power_monitor/power_observer.h"
-#include "device/power_monitor/power_monitor_export.h"
-#include "device/power_monitor/public/interfaces/power_monitor.mojom.h"
+#include "services/device/public/interfaces/power_monitor.mojom.h"
 
 namespace device {
 
 // A class used to monitor the power state change and communicate it to child
 // processes via IPC.
-class DEVICE_POWER_MONITOR_EXPORT PowerMonitorMessageBroadcaster
-    : public base::PowerObserver,
-      NON_EXPORTED_BASE(public device::mojom::PowerMonitor) {
+class PowerMonitorMessageBroadcaster : public base::PowerObserver,
+                                       public device::mojom::PowerMonitor {
  public:
   explicit PowerMonitorMessageBroadcaster();
   ~PowerMonitorMessageBroadcaster() override;
@@ -40,4 +38,4 @@
 
 }  // namespace device
 
-#endif  // DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
+#endif  // SERVICES_DEVICE_POWER_MONITOR_POWER_MONITOR_MESSAGE_BROADCASTER_H_
diff --git a/device/power_monitor/power_monitor_message_broadcaster_unittest.cc b/services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc
similarity index 97%
rename from device/power_monitor/power_monitor_message_broadcaster_unittest.cc
rename to services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc
index 4356a0df..bde8cc3 100644
--- a/device/power_monitor/power_monitor_message_broadcaster_unittest.cc
+++ b/services/device/power_monitor/power_monitor_message_broadcaster_unittest.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "services/device/power_monitor/power_monitor_message_broadcaster.h"
+
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/power_monitor_test_base.h"
-#include "device/power_monitor/power_monitor_message_broadcaster.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/device/power_monitor/public/cpp/BUILD.gn b/services/device/public/cpp/power_monitor/BUILD.gn
similarity index 85%
rename from device/power_monitor/public/cpp/BUILD.gn
rename to services/device/public/cpp/power_monitor/BUILD.gn
index d586540..4613af6 100644
--- a/device/power_monitor/public/cpp/BUILD.gn
+++ b/services/device/public/cpp/power_monitor/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//build/config/features.gni")
 
-source_set("cpp") {
+source_set("power_monitor") {
   sources = [
     "power_monitor_broadcast_source.cc",
     "power_monitor_broadcast_source.h",
@@ -17,6 +17,6 @@
   ]
 
   public_deps = [
-    "//device/power_monitor/public/interfaces",
+    "//services/device/public/interfaces",
   ]
 }
diff --git a/device/power_monitor/OWNERS b/services/device/public/cpp/power_monitor/OWNERS
similarity index 100%
copy from device/power_monitor/OWNERS
copy to services/device/public/cpp/power_monitor/OWNERS
diff --git a/device/power_monitor/public/cpp/power_monitor_broadcast_source.cc b/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.cc
similarity index 93%
rename from device/power_monitor/public/cpp/power_monitor_broadcast_source.cc
rename to services/device/public/cpp/power_monitor/power_monitor_broadcast_source.cc
index 100b89b2..d2b06d50 100644
--- a/device/power_monitor/public/cpp/power_monitor_broadcast_source.cc
+++ b/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.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 "device/power_monitor/public/cpp/power_monitor_broadcast_source.h"
+#include "services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h"
 
 #include "base/location.h"
 #include "base/macros.h"
diff --git a/device/power_monitor/public/cpp/power_monitor_broadcast_source.h b/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h
similarity index 78%
rename from device/power_monitor/public/cpp/power_monitor_broadcast_source.h
rename to services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h
index 2a4c94a0..5f8f06e 100644
--- a/device/power_monitor/public/cpp/power_monitor_broadcast_source.h
+++ b/services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_POWER_MONITOR_POWER_MONITOR_BROADCAST_SOURCE_H_
-#define DEVICE_POWER_MONITOR_POWER_MONITOR_BROADCAST_SOURCE_H_
+#ifndef SERVICES_DEVICE_PUBLIC_CPP_POWER_MONITOR_POWER_MONITOR_BROADCAST_SOURCE_H_
+#define SERVICES_DEVICE_PUBLIC_CPP_POWER_MONITOR_POWER_MONITOR_BROADCAST_SOURCE_H_
 
 #include "base/macros.h"
 #include "base/power_monitor/power_monitor_source.h"
-#include "device/power_monitor/public/interfaces/power_monitor.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/device/public/interfaces/power_monitor.mojom.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 
 namespace device {
@@ -36,4 +36,4 @@
 
 }  // namespace device
 
-#endif  // DEVICE_POWER_MONITOR_POWER_MONITOR_BROADCAST_SOURCE_H_
+#endif  // SERVICES_DEVICE_PUBLIC_CPP_POWER_MONITOR_POWER_MONITOR_BROADCAST_SOURCE_H_
diff --git a/device/power_monitor/public/cpp/power_monitor_broadcast_source_unittest.cc b/services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc
similarity index 96%
rename from device/power_monitor/public/cpp/power_monitor_broadcast_source_unittest.cc
rename to services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc
index dddd7187e..6ea784b2 100644
--- a/device/power_monitor/public/cpp/power_monitor_broadcast_source_unittest.cc
+++ b/services/device/public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h"
+
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/power_monitor_test_base.h"
-#include "device/power_monitor/public/cpp/power_monitor_broadcast_source.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
diff --git a/services/device/public/interfaces/BUILD.gn b/services/device/public/interfaces/BUILD.gn
index dec07695..f207c69 100644
--- a/services/device/public/interfaces/BUILD.gn
+++ b/services/device/public/interfaces/BUILD.gn
@@ -6,6 +6,16 @@
 
 mojom("interfaces") {
   sources = [
+    "power_monitor.mojom",
+  ]
+
+  public_deps = [
+    ":constants",
+  ]
+}
+
+mojom("constants") {
+  sources = [
     "constants.mojom",
   ]
 }
diff --git a/device/power_monitor/public/interfaces/power_monitor.mojom b/services/device/public/interfaces/power_monitor.mojom
similarity index 100%
rename from device/power_monitor/public/interfaces/power_monitor.mojom
rename to services/device/public/interfaces/power_monitor.mojom
diff --git a/services/ui/display/BUILD.gn b/services/ui/display/BUILD.gn
index cda9627f..c0bd6e73 100644
--- a/services/ui/display/BUILD.gn
+++ b/services/ui/display/BUILD.gn
@@ -23,8 +23,8 @@
 
   if (use_ozone && is_chromeos) {
     sources += [
-      "screen_manager_ozone.cc",
-      "screen_manager_ozone.h",
+      "screen_manager_ozone_internal.cc",
+      "screen_manager_ozone_internal.h",
     ]
 
     deps += [
@@ -36,8 +36,8 @@
     ]
   } else {
     sources += [
-      "screen_manager_stub.cc",
-      "screen_manager_stub.h",
+      "screen_manager_stub_internal.cc",
+      "screen_manager_stub_internal.h",
     ]
   }
 }
@@ -46,7 +46,7 @@
   test("display_service_unittests") {
     sources = [
       "run_all_unittests.cc",
-      "screen_manager_ozone_unittests.cc",
+      "screen_manager_ozone_internal_unittests.cc",
     ]
 
     deps = [
diff --git a/services/ui/display/screen_manager_ozone.cc b/services/ui/display/screen_manager_ozone_internal.cc
similarity index 84%
rename from services/ui/display/screen_manager_ozone.cc
rename to services/ui/display/screen_manager_ozone_internal.cc
index 772ee11..0e67d053 100644
--- a/services/ui/display/screen_manager_ozone.cc
+++ b/services/ui/display/screen_manager_ozone_internal.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 "services/ui/display/screen_manager_ozone.h"
+#include "services/ui/display/screen_manager_ozone_internal.h"
 
 #include <string>
 #include <utility>
@@ -55,12 +55,12 @@
 
 // static
 std::unique_ptr<ScreenManager> ScreenManager::Create() {
-  return base::MakeUnique<ScreenManagerOzone>();
+  return base::MakeUnique<ScreenManagerOzoneInternal>();
 }
 
-ScreenManagerOzone::ScreenManagerOzone() {}
+ScreenManagerOzoneInternal::ScreenManagerOzoneInternal() {}
 
-ScreenManagerOzone::~ScreenManagerOzone() {
+ScreenManagerOzoneInternal::~ScreenManagerOzoneInternal() {
   // We are shutting down and don't want to make anymore display changes.
   fake_display_controller_ = nullptr;
 
@@ -78,7 +78,7 @@
     display_manager_.reset();
 }
 
-void ScreenManagerOzone::SetPrimaryDisplayId(int64_t display_id) {
+void ScreenManagerOzoneInternal::SetPrimaryDisplayId(int64_t display_id) {
   DCHECK_NE(kInvalidDisplayId, display_id);
   if (primary_display_id_ == display_id)
     return;
@@ -132,13 +132,13 @@
   delegate_->OnPrimaryDisplayChanged(primary_display_id_);
 }
 
-void ScreenManagerOzone::AddInterfaces(
+void ScreenManagerOzoneInternal::AddInterfaces(
     service_manager::InterfaceRegistry* registry) {
   registry->AddInterface<mojom::DisplayController>(this);
   registry->AddInterface<mojom::TestDisplayController>(this);
 }
 
-void ScreenManagerOzone::Init(ScreenManagerDelegate* delegate) {
+void ScreenManagerOzoneInternal::Init(ScreenManagerDelegate* delegate) {
   DCHECK(delegate);
   delegate_ = delegate;
 
@@ -188,7 +188,7 @@
       &display_configurator_, display_manager_.get());
 }
 
-void ScreenManagerOzone::RequestCloseDisplay(int64_t display_id) {
+void ScreenManagerOzoneInternal::RequestCloseDisplay(int64_t display_id) {
   if (!fake_display_controller_)
     return;
 
@@ -197,11 +197,11 @@
   fake_display_controller_->RemoveDisplay(display_id);
 }
 
-int64_t ScreenManagerOzone::GetPrimaryDisplayId() const {
+int64_t ScreenManagerOzoneInternal::GetPrimaryDisplayId() const {
   return primary_display_id_;
 }
 
-void ScreenManagerOzone::ToggleAddRemoveDisplay() {
+void ScreenManagerOzoneInternal::ToggleAddRemoveDisplay() {
   if (!fake_display_controller_)
     return;
   DVLOG(1) << "ToggleAddRemoveDisplay";
@@ -219,7 +219,7 @@
   }
 }
 
-void ScreenManagerOzone::ToggleDisplayResolution() {
+void ScreenManagerOzoneInternal::ToggleDisplayResolution() {
   if (primary_display_id_ == kInvalidDisplayId)
     return;
 
@@ -244,26 +244,26 @@
     display_manager_->SetDisplayMode(primary_display_id_, mode);
 }
 
-void ScreenManagerOzone::IncreaseInternalDisplayZoom() {
+void ScreenManagerOzoneInternal::IncreaseInternalDisplayZoom() {
   if (Display::HasInternalDisplay())
     display_manager_->ZoomInternalDisplay(false);
 }
 
-void ScreenManagerOzone::DecreaseInternalDisplayZoom() {
+void ScreenManagerOzoneInternal::DecreaseInternalDisplayZoom() {
   if (Display::HasInternalDisplay())
     display_manager_->ZoomInternalDisplay(true);
 }
 
-void ScreenManagerOzone::ResetInternalDisplayZoom() {
+void ScreenManagerOzoneInternal::ResetInternalDisplayZoom() {
   if (Display::HasInternalDisplay())
     display_manager_->ResetInternalDisplayZoom();
 }
 
-void ScreenManagerOzone::RotateCurrentDisplayCW() {
+void ScreenManagerOzoneInternal::RotateCurrentDisplayCW() {
   NOTIMPLEMENTED();
 }
 
-void ScreenManagerOzone::SwapPrimaryDisplay() {
+void ScreenManagerOzoneInternal::SwapPrimaryDisplay() {
   // Can't swap if there is only 1 display and swapping isn't supported for 3 or
   // more displays.
   if (display_manager_->GetNumDisplays() != 2)
@@ -280,28 +280,28 @@
     SetPrimaryDisplayId(display_ids[0]);
 }
 
-void ScreenManagerOzone::ToggleMirrorMode() {
+void ScreenManagerOzoneInternal::ToggleMirrorMode() {
   NOTIMPLEMENTED();
 }
 
-void ScreenManagerOzone::SetDisplayWorkArea(int64_t display_id,
-                                            const gfx::Size& size,
-                                            const gfx::Insets& insets) {
+void ScreenManagerOzoneInternal::SetDisplayWorkArea(int64_t display_id,
+                                                    const gfx::Size& size,
+                                                    const gfx::Insets& insets) {
   // TODO(kylechar): Check the size of the display matches the current size.
   display_manager_->UpdateWorkAreaOfDisplay(display_id, insets);
 }
 
-void ScreenManagerOzone::TakeDisplayControl(
+void ScreenManagerOzoneInternal::TakeDisplayControl(
     const TakeDisplayControlCallback& callback) {
   display_configurator_.TakeControl(callback);
 }
 
-void ScreenManagerOzone::RelinquishDisplayControl(
+void ScreenManagerOzoneInternal::RelinquishDisplayControl(
     const RelinquishDisplayControlCallback& callback) {
   display_configurator_.RelinquishControl(callback);
 }
 
-void ScreenManagerOzone::OnDisplayAdded(const Display& display) {
+void ScreenManagerOzoneInternal::OnDisplayAdded(const Display& display) {
   ViewportMetrics metrics = GetViewportMetricsForDisplay(display);
   DVLOG(1) << "OnDisplayAdded: " << display.ToString() << "\n  "
            << metrics.ToString();
@@ -309,7 +309,7 @@
   delegate_->OnDisplayAdded(display.id(), metrics);
 }
 
-void ScreenManagerOzone::OnDisplayRemoved(const Display& display) {
+void ScreenManagerOzoneInternal::OnDisplayRemoved(const Display& display) {
   // TODO(kylechar): If we're removing the primary display we need to first set
   // a new primary display. This will crash until then.
 
@@ -318,8 +318,9 @@
   delegate_->OnDisplayRemoved(display.id());
 }
 
-void ScreenManagerOzone::OnDisplayMetricsChanged(const Display& display,
-                                                 uint32_t changed_metrics) {
+void ScreenManagerOzoneInternal::OnDisplayMetricsChanged(
+    const Display& display,
+    uint32_t changed_metrics) {
   ViewportMetrics metrics = GetViewportMetricsForDisplay(display);
   DVLOG(1) << "OnDisplayModified: " << display.ToString() << "\n  "
            << metrics.ToString();
@@ -327,7 +328,7 @@
   delegate_->OnDisplayModified(display.id(), metrics);
 }
 
-ViewportMetrics ScreenManagerOzone::GetViewportMetricsForDisplay(
+ViewportMetrics ScreenManagerOzoneInternal::GetViewportMetricsForDisplay(
     const Display& display) {
   const ManagedDisplayInfo& managed_info =
       display_manager_->GetDisplayInfo(display.id());
@@ -344,20 +345,21 @@
   return metrics;
 }
 
-void ScreenManagerOzone::CreateOrUpdateMirroringDisplay(
+void ScreenManagerOzoneInternal::CreateOrUpdateMirroringDisplay(
     const DisplayInfoList& display_info_list) {
   NOTIMPLEMENTED();
 }
 
-void ScreenManagerOzone::CloseMirroringDisplayIfNotNecessary() {
+void ScreenManagerOzoneInternal::CloseMirroringDisplayIfNotNecessary() {
   NOTIMPLEMENTED();
 }
 
-void ScreenManagerOzone::PreDisplayConfigurationChange(bool clear_focus) {
+void ScreenManagerOzoneInternal::PreDisplayConfigurationChange(
+    bool clear_focus) {
   DVLOG(1) << "PreDisplayConfigurationChange";
 }
 
-void ScreenManagerOzone::PostDisplayConfigurationChange(
+void ScreenManagerOzoneInternal::PostDisplayConfigurationChange(
     bool must_clear_window) {
   // Set primary display if not set yet.
   if (primary_display_id_ == kInvalidDisplayId) {
@@ -377,17 +379,17 @@
   DVLOG(1) << "PostDisplayConfigurationChange";
 }
 
-DisplayConfigurator* ScreenManagerOzone::display_configurator() {
+DisplayConfigurator* ScreenManagerOzoneInternal::display_configurator() {
   return &display_configurator_;
 }
 
-void ScreenManagerOzone::Create(
+void ScreenManagerOzoneInternal::Create(
     const service_manager::Identity& remote_identity,
     mojom::DisplayControllerRequest request) {
   controller_bindings_.AddBinding(this, std::move(request));
 }
 
-void ScreenManagerOzone::Create(
+void ScreenManagerOzoneInternal::Create(
     const service_manager::Identity& remote_identity,
     mojom::TestDisplayControllerRequest request) {
   test_bindings_.AddBinding(this, std::move(request));
diff --git a/services/ui/display/screen_manager_ozone.h b/services/ui/display/screen_manager_ozone_internal.h
similarity index 87%
rename from services/ui/display/screen_manager_ozone.h
rename to services/ui/display/screen_manager_ozone_internal.h
index 01360767..239ad78a 100644
--- a/services/ui/display/screen_manager_ozone.h
+++ b/services/ui/display/screen_manager_ozone_internal.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 SERVICES_UI_DISPLAY_SCREEN_MANAGER_OZONE_H_
-#define SERVICES_UI_DISPLAY_SCREEN_MANAGER_OZONE_H_
+#ifndef SERVICES_UI_DISPLAY_SCREEN_MANAGER_OZONE_INTERNAL_H_
+#define SERVICES_UI_DISPLAY_SCREEN_MANAGER_OZONE_INTERNAL_H_
 
 #include <stdint.h>
 
@@ -30,9 +30,10 @@
 class ScreenBase;
 class TouchTransformController;
 
-// ScreenManagerOzone provides the necessary functionality to configure all
-// attached physical displays on the ozone platform.
-class ScreenManagerOzone
+// ScreenManagerOzoneInternal provides the necessary functionality to configure
+// all attached physical displays on the the ozone platform when operating in
+// internal window mode.
+class ScreenManagerOzoneInternal
     : public ScreenManager,
       public mojom::TestDisplayController,
       public mojom::DisplayController,
@@ -41,8 +42,8 @@
       public service_manager::InterfaceFactory<mojom::DisplayController>,
       public service_manager::InterfaceFactory<mojom::TestDisplayController> {
  public:
-  ScreenManagerOzone();
-  ~ScreenManagerOzone() override;
+  ScreenManagerOzoneInternal();
+  ~ScreenManagerOzoneInternal() override;
 
   void SetPrimaryDisplayId(int64_t display_id);
 
@@ -71,7 +72,7 @@
       const RelinquishDisplayControlCallback& callback) override;
 
  private:
-  friend class ScreenManagerOzoneTest;
+  friend class ScreenManagerOzoneInternalTest;
 
   ViewportMetrics GetViewportMetricsForDisplay(const Display& display);
 
@@ -116,9 +117,9 @@
   mojo::BindingSet<mojom::DisplayController> controller_bindings_;
   mojo::BindingSet<mojom::TestDisplayController> test_bindings_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScreenManagerOzone);
+  DISALLOW_COPY_AND_ASSIGN(ScreenManagerOzoneInternal);
 };
 
 }  // namespace display
 
-#endif  // SERVICES_UI_DISPLAY_SCREEN_MANAGER_OZONE_H_
+#endif  // SERVICES_UI_DISPLAY_SCREEN_MANAGER_OZONE_INTERNAL_H_
diff --git a/services/ui/display/screen_manager_ozone_unittests.cc b/services/ui/display/screen_manager_ozone_internal_unittests.cc
similarity index 91%
rename from services/ui/display/screen_manager_ozone_unittests.cc
rename to services/ui/display/screen_manager_ozone_internal_unittests.cc
index 16307a0..7b93494 100644
--- a/services/ui/display/screen_manager_ozone_unittests.cc
+++ b/services/ui/display/screen_manager_ozone_internal_unittests.cc
@@ -10,7 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "services/ui/common/task_runner_test_base.h"
-#include "services/ui/display/screen_manager_ozone.h"
+#include "services/ui/display/screen_manager_ozone_internal.h"
 #include "services/ui/display/viewport_metrics.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -112,13 +112,13 @@
 }  // namespace
 
 // Test fixture with helpers to act like DisplayConfigurator and send
-// OnDisplayModeChanged() to ScreenManagerOzone.
-class ScreenManagerOzoneTest : public ui::TaskRunnerTestBase {
+// OnDisplayModeChanged() to ScreenManagerOzoneInternal.
+class ScreenManagerOzoneInternalTest : public ui::TaskRunnerTestBase {
  public:
-  ScreenManagerOzoneTest() {}
-  ~ScreenManagerOzoneTest() override {}
+  ScreenManagerOzoneInternalTest() {}
+  ~ScreenManagerOzoneInternalTest() override {}
 
-  ScreenManagerOzone* screen_manager() { return screen_manager_.get(); }
+  ScreenManagerOzoneInternal* screen_manager() { return screen_manager_.get(); }
   TestScreenManagerDelegate* delegate() { return &delegate_; }
 
   // Adds a display snapshot with specified ID and default size.
@@ -152,7 +152,7 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitchNative(
         switches::kScreenConfig, "none");
 
-    screen_manager_ = base::MakeUnique<ScreenManagerOzone>();
+    screen_manager_ = base::MakeUnique<ScreenManagerOzoneInternal>();
 
     // Create NDD for FakeDisplayController.
     std::unique_ptr<NativeDisplayDelegate> ndd =
@@ -187,10 +187,10 @@
 
   FakeDisplayController* fake_display_controller_ = nullptr;
   TestScreenManagerDelegate delegate_;
-  std::unique_ptr<ScreenManagerOzone> screen_manager_;
+  std::unique_ptr<ScreenManagerOzoneInternal> screen_manager_;
 };
 
-TEST_F(ScreenManagerOzoneTest, AddDisplay) {
+TEST_F(ScreenManagerOzoneInternalTest, AddDisplay) {
   AddDisplay(FakeDisplaySnapshot::Builder()
                  .SetId(2)
                  .SetNativeMode(gfx::Size(1600, 900))
@@ -202,7 +202,7 @@
   EXPECT_THAT(delegate()->added()[0], DisplayBoundsIs("1024,0 1600x900"));
 }
 
-TEST_F(ScreenManagerOzoneTest, RemoveDisplay) {
+TEST_F(ScreenManagerOzoneInternalTest, RemoveDisplay) {
   AddDisplay(2);
   delegate()->Reset();
 
@@ -212,7 +212,7 @@
   EXPECT_EQ("Removed(2)", delegate()->changes());
 }
 
-TEST_F(ScreenManagerOzoneTest, DISABLED_RemovePrimaryDisplay) {
+TEST_F(ScreenManagerOzoneInternalTest, DISABLED_RemovePrimaryDisplay) {
   AddDisplay(2);
   delegate()->Reset();
 
@@ -226,7 +226,7 @@
   EXPECT_THAT(delegate()->modified()[0], DisplayBoundsIs("0,0 1024x768"));
 }
 
-TEST_F(ScreenManagerOzoneTest, AddRemoveMultipleDisplay) {
+TEST_F(ScreenManagerOzoneInternalTest, AddRemoveMultipleDisplay) {
   AddDisplay(2);
   AddDisplay(3);
   EXPECT_EQ("Added(2);Added(3)", delegate()->changes());
@@ -245,7 +245,7 @@
   EXPECT_EQ("Removed(3)", delegate()->changes());
 }
 
-TEST_F(ScreenManagerOzoneTest, AddDisplay4k) {
+TEST_F(ScreenManagerOzoneInternalTest, AddDisplay4k) {
   AddDisplay(FakeDisplaySnapshot::Builder()
                  .SetId(2)
                  .SetNativeMode(gfx::Size(4096, 2160))
@@ -259,7 +259,7 @@
   EXPECT_THAT(delegate()->added()[0], DisplayPixelSizeIs("4096x2160"));
 }
 
-TEST_F(ScreenManagerOzoneTest, SwapPrimaryDisplay) {
+TEST_F(ScreenManagerOzoneInternalTest, SwapPrimaryDisplay) {
   AddDisplay(2);
   delegate()->Reset();
 
diff --git a/services/ui/display/screen_manager_stub.cc b/services/ui/display/screen_manager_stub_internal.cc
similarity index 69%
rename from services/ui/display/screen_manager_stub.cc
rename to services/ui/display/screen_manager_stub_internal.cc
index c664c84..471c08f 100644
--- a/services/ui/display/screen_manager_stub.cc
+++ b/services/ui/display/screen_manager_stub_internal.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 "services/ui/display/screen_manager_stub.h"
+#include "services/ui/display/screen_manager_stub_internal.h"
 
 #include <memory>
 
@@ -40,30 +40,32 @@
 
 // static
 std::unique_ptr<ScreenManager> ScreenManager::Create() {
-  return base::MakeUnique<ScreenManagerStub>();
+  return base::MakeUnique<ScreenManagerStubInternal>();
 }
 
-ScreenManagerStub::ScreenManagerStub() : weak_ptr_factory_(this) {}
+ScreenManagerStubInternal::ScreenManagerStubInternal()
+    : weak_ptr_factory_(this) {}
 
-ScreenManagerStub::~ScreenManagerStub() {}
+ScreenManagerStubInternal::~ScreenManagerStubInternal() {}
 
-void ScreenManagerStub::FixedSizeScreenConfiguration() {
+void ScreenManagerStubInternal::FixedSizeScreenConfiguration() {
   delegate_->OnDisplayAdded(display_id_, display_metrics_);
 }
 
-void ScreenManagerStub::AddInterfaces(
+void ScreenManagerStubInternal::AddInterfaces(
     service_manager::InterfaceRegistry* registry) {}
 
-void ScreenManagerStub::Init(ScreenManagerDelegate* delegate) {
+void ScreenManagerStubInternal::Init(ScreenManagerDelegate* delegate) {
   DCHECK(delegate);
   delegate_ = delegate;
   display_metrics_ = DefaultViewportMetrics();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&ScreenManagerStub::FixedSizeScreenConfiguration,
-                            weak_ptr_factory_.GetWeakPtr()));
+      FROM_HERE,
+      base::Bind(&ScreenManagerStubInternal::FixedSizeScreenConfiguration,
+                 weak_ptr_factory_.GetWeakPtr()));
 }
 
-void ScreenManagerStub::RequestCloseDisplay(int64_t display_id) {
+void ScreenManagerStubInternal::RequestCloseDisplay(int64_t display_id) {
   if (display_id == display_id_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::Bind(&ScreenManagerDelegate::OnDisplayRemoved,
@@ -71,7 +73,7 @@
   }
 }
 
-int64_t ScreenManagerStub::GetPrimaryDisplayId() const {
+int64_t ScreenManagerStubInternal::GetPrimaryDisplayId() const {
   return display_id_;
 }
 
diff --git a/services/ui/display/screen_manager_stub.h b/services/ui/display/screen_manager_stub_internal.h
similarity index 63%
rename from services/ui/display/screen_manager_stub.h
rename to services/ui/display/screen_manager_stub_internal.h
index b780bb4d..bda52eb8 100644
--- a/services/ui/display/screen_manager_stub.h
+++ b/services/ui/display/screen_manager_stub_internal.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 SERVICES_UI_DISPLAY_SCREEN_MANAGER_STUB_H_
-#define SERVICES_UI_DISPLAY_SCREEN_MANAGER_STUB_H_
+#ifndef SERVICES_UI_DISPLAY_SCREEN_MANAGER_STUB_INTERNAL_H_
+#define SERVICES_UI_DISPLAY_SCREEN_MANAGER_STUB_INTERNAL_H_
 
 #include <stdint.h>
 
@@ -13,12 +13,13 @@
 
 namespace display {
 
-// ScreenManagerStub provides the necessary functionality to configure a fixed
+// ScreenManagerStubInternal provides the necessary functionality to configure a
+// fixed
 // 1024x768 display for non-ozone platforms.
-class ScreenManagerStub : public ScreenManager {
+class ScreenManagerStubInternal : public ScreenManager {
  public:
-  ScreenManagerStub();
-  ~ScreenManagerStub() override;
+  ScreenManagerStubInternal();
+  ~ScreenManagerStubInternal() override;
 
  private:
   // Fake creation of a single 1024x768 display.
@@ -36,11 +37,11 @@
 
   ScreenManagerDelegate* delegate_ = nullptr;
 
-  base::WeakPtrFactory<ScreenManagerStub> weak_ptr_factory_;
+  base::WeakPtrFactory<ScreenManagerStubInternal> weak_ptr_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScreenManagerStub);
+  DISALLOW_COPY_AND_ASSIGN(ScreenManagerStubInternal);
 };
 
 }  // namespace display
 
-#endif  // SERVICES_UI_DISPLAY_SCREEN_MANAGER_STUB_H_
+#endif  // SERVICES_UI_DISPLAY_SCREEN_MANAGER_STUB_INTERNAL_H_
diff --git a/services/ui/gpu/gpu_main.cc b/services/ui/gpu/gpu_main.cc
index a87c7cbe..fe89372 100644
--- a/services/ui/gpu/gpu_main.cc
+++ b/services/ui/gpu/gpu_main.cc
@@ -14,6 +14,10 @@
 #include "services/ui/common/server_gpu_memory_buffer_manager.h"
 #include "services/ui/gpu/gpu_service.h"
 
+#if defined(USE_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
+#endif
+
 #if defined(OS_MACOSX)
 #include "base/message_loop/message_pump_mac.h"
 #endif
@@ -51,7 +55,10 @@
 #elif defined(USE_X11)
   thread_options.message_pump_factory = base::Bind(&CreateMessagePumpX11);
 #elif defined(USE_OZONE)
-  thread_options.message_loop_type = base::MessageLoop::TYPE_UI;
+  // The MessageLoop type required depends on the Ozone platform selected at
+  // runtime.
+  thread_options.message_loop_type =
+      ui::OzonePlatform::EnsureInstance()->GetMessageLoopTypeForGpu();
 #elif defined(OS_LINUX)
   thread_options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
 #elif defined(OS_MACOSX)
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 9935a09..fea2de5 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -258,9 +258,6 @@
 // Updating to a correct SkPMColor lerp will require layout test rebaselines.
 #define SK_SUPPORT_LEGACY_BROKEN_LERP
 
-// Enabling the screenspace AA tessellating path renderer needs rebaselines.
-#define SK_DISABLE_SCREENSPACE_TESS_AA_PATH_RENDERER
-
 #ifndef    SK_SUPPORT_LEGACY_AAA
 #   define SK_SUPPORT_LEGACY_AAA
 #endif
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index ba429261..72804488 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -249,8 +249,7 @@
       },
       {
         "args": [
-          "--enable-browser-side-navigation",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter"
+          "--enable-browser-side-navigation"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -279,8 +278,7 @@
     "scripts": [
       {
         "args": [
-          "content_browsertests",
-          "../../testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter"
+          "content_browsertests"
         ],
         "name": "count_filtered_tests_content_browsertests",
         "script": "count_filtered_tests.py"
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 5f6a780..84b79cc5 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -2793,8 +2793,7 @@
       },
       {
         "args": [
-          "--enable-browser-side-navigation",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter"
+          "--enable-browser-side-navigation"
         ],
         "name": "browser_side_navigation_content_browsertests",
         "swarming": {
@@ -3460,8 +3459,7 @@
       },
       {
         "args": [
-          "--enable-browser-side-navigation",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter"
+          "--enable-browser-side-navigation"
         ],
         "name": "browser_side_navigation_content_browsertests",
         "swarming": {
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 6804ad32..7c54b68 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -31,7 +31,6 @@
   testonly = true
 
   data = [
-    "//testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter",
     "//testing/buildbot/filters/cast-linux.content_browsertests.filter",
     "//testing/buildbot/filters/isolate-extensions.content_browsertests.filter",
     "//testing/buildbot/filters/site-per-process.content_browsertests.filter",
diff --git a/testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter b/testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter
deleted file mode 100644
index 730c7a8..0000000
--- a/testing/buildbot/filters/browser-side-navigation.linux.content_browsertests.filter
+++ /dev/null
@@ -1,2 +0,0 @@
-# Browser-initiated fragment navigations are handled improperly. https://crbug.com/663777
--NavigationControllerBrowserTest.SamePageBrowserInitiated
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 74f62a5..f006541 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -969,6 +969,22 @@
             ]
         }
     ],
+    "ImprovedRecoveryComponent": [
+        {
+            "platforms": [
+                "win",
+                "mac"
+            ],
+            "experiments": [
+                {
+                    "name": "ImprovedRecoveryComponent",
+                    "enable_features": [
+                        "ImprovedRecoveryComponent"
+                    ]
+                }
+            ]
+        }
+    ],
     "InstanceID": [
         {
             "platforms": [
@@ -1521,6 +1537,26 @@
             ]
         }
     ],
+    "PasswordMetadataFilling": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "ios",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "PasswordMetadataFilling"
+                    ]
+                }
+            ]
+        }
+    ],
     "PasswordSeparatedSigninFlow": [
         {
             "platforms": [
@@ -2716,7 +2752,7 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled",
+                    "name": "TunedClippingLevelMin070",
                     "enable_features": [
                         "TunedClippingLevelMin70"
                     ]
diff --git a/third_party/OWNERS b/third_party/OWNERS
index 4cadce06..c79ad1b 100644
--- a/third_party/OWNERS
+++ b/third_party/OWNERS
@@ -2,7 +2,7 @@
 # adding new libraries. Be sure to follow the instructions for adding
 # new third party libraries.
 #
-# http://www.chromium.org/developers/adding-3rd-party-libraries
+# https://chromium.googlesource.com/chromium/src.git/+/master/docs/adding_to_third_party.md
 #
 # For changes to existing code that has no OWNER file, simply TBR= one of
 # people below in addition to getting an appropriate code review. Generally
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
index 81f62a3..500bbcb 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -10,8 +10,8 @@
 crbug.com/669083 virtual/mojo-loading/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ]
 
 # https://crbug.com/661725 - Propagating user gesture via postMessage doesn't work for OOPIFs
-crbug.com/661725 http/tests/security/frameNavigation/xss-ALLOWED-top-navigation-after-postMessage.html [ Failure Timeout ]
-crbug.com/661725 virtual/mojo-loading/http/tests/security/frameNavigation/xss-ALLOWED-top-navigation-after-postMessage.html [ Failure Timeout ]
+crbug.com/661725 http/tests/security/frameNavigation/xss-ALLOWED-top-navigation-after-postMessage.html [ Timeout ]
+crbug.com/661725 virtual/mojo-loading/http/tests/security/frameNavigation/xss-ALLOWED-top-navigation-after-postMessage.html [ Timeout ]
 
 # https://crbug.com/582245 - no exception, b/c BindingSecurity::shouldAllowAccessTo exits early when |!target|.
 crbug.com/582245 http/tests/security/xss-DENIED-getSVGDocument-iframe.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests
index 64bc272..2984e26a 100644
--- a/third_party/WebKit/LayoutTests/NeverFixTests
+++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -218,6 +218,16 @@
 external/wpt/preload [ WontFix ]
 external/wpt/upgrade-insecure-requests [ WontFix ]
 
+# WPT manual tests without automation
+external/wpt/html/semantics/forms/constraints/tooShort-input-email-add-manual.html [ WontFix ]
+external/wpt/html/semantics/forms/constraints/tooShort-input-password-add-manual.html [ WontFix ]
+external/wpt/html/semantics/forms/constraints/tooShort-input-search-add-manual.html [ WontFix ]
+external/wpt/html/semantics/forms/constraints/tooShort-input-tel-add-manual.html [ WontFix ]
+external/wpt/html/semantics/forms/constraints/tooShort-input-text-add-manual.html [ WontFix ]
+external/wpt/html/semantics/forms/constraints/tooShort-input-url-add-manual.html [ WontFix ]
+external/wpt/html/semantics/forms/constraints/tooShort-textarea-add-manual.html [ WontFix ]
+external/wpt/selection/dir-manual.html [ WontFix ]
+
 # Temporary disabling of all encrypted-media WPT tests while enabling
 # https only. Once the switch is complete (and the WPT tests renamed so they
 # run using https), they can be re-enabled.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f93a7bd3..5ef8a9c 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -151,8 +151,8 @@
 # LayoutNG - is a new layout system for Blink.
 
 #### css2.1/20110323
-#### Passed: 110
-#### Skipped: 299
+#### Passed: 109
+#### Skipped: 300
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/absolute-non-replaced-height-002.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/floats-zero-height-wrap-001.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/floats-zero-height-wrap-002.htm [ Skip ]
@@ -425,6 +425,7 @@
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/outline-color-applies-to-014.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/overflow-applies-to-007.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/overflow-applies-to-009.htm [ Skip ]
+crbug.com/635619 virtual/layout_ng/css2.1/20110323/overflow-applies-to-010.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/overflow-applies-to-012.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/overflow-applies-to-013.htm [ Skip ]
 crbug.com/635619 virtual/layout_ng/css2.1/20110323/overflow-applies-to-014.htm [ Skip ]
@@ -942,8 +943,8 @@
 crbug.com/490511 external/wpt/html/browsers/offline/application-cache-api/api_update.html [ Failure Pass ]
 crbug.com/490511 [ Linux Win ] external/wpt/html/rendering/bindings/the-input-element-as-a-text-entry-widget/unrecognized-type-should-fallback-as-text-type.html [ Failure ]
 crbug.com/108417 external/wpt/html/rendering/non-replaced-elements/tables/table-border-1.html [ Failure ]
-crbug.com/490511 external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/color.html [ Failure Pass ]
-crbug.com/490511 external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/width.html [ Failure Pass ]
+crbug.com/490511 external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/color.html [ Failure ]
+crbug.com/490511 external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/width.html [ Failure ]
 crbug.com/490511 external/wpt/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html [ Failure ]
 crbug.com/490511 external/wpt/html/semantics/document-metadata/styling/LinkStyle.html [ Failure Pass ]
 crbug.com/627706 external/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html [ Skip ]
@@ -1392,6 +1393,11 @@
 crbug.com/613672 [ Mac ] fast/events/pointerevents/multi-pointer-event-in-slop-region.html [ Skip ]
 crbug.com/613672 [ Mac ] fast/events/pointerevents/pointerevent_touch-action-pinch_zoom_touch.html [ Skip ]
 crbug.com/613672 [ Mac ] fast/events/pointerevents/pointer-event-in-slop-region.html [ Skip ]
+crbug.com/613672 [ Mac ] external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual.html [ Skip ]
+crbug.com/613672 [ Mac ] external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual.html [ Skip ]
+crbug.com/613672 [ Mac ] external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_click-manual.html [ Skip ]
+crbug.com/613672 [ Mac ] external/wpt/pointerevents/pointerevent_boundary_events_in_capturing-manual.html [ Skip ]
+crbug.com/613672 [ Mac ] external/wpt/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual.html [ Skip ]
 crbug.com/613672 [ Mac ] external/wpt/pointerevents/pointerevent_attributes_nohover_pointers-manual.html [ Skip ]
 crbug.com/613672 [ Mac ] external/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html [ Skip ]
 crbug.com/613672 [ Mac ] external/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html [ Skip ]
@@ -1838,7 +1844,6 @@
 crbug.com/626703 external/wpt/service-workers/service-worker/registration-useCache.https.html [ Timeout ]
 crbug.com/626703 external/wpt/streams/writable-streams/close.sharedworker.html [ Timeout ]
 crbug.com/626703 external/csswg-test/css-flexbox-1/layout-algorithm_algo-cross-line-001.html [ Failure ]
-crbug.com/626703 external/wpt/dom/nodes/Document-characterSet-normalization.html [ Timeout ]
 crbug.com/626703 external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html [ Timeout ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html [ Timeout ]
 crbug.com/626703 external/wpt/html/semantics/scripting-1/the-script-element/async_007.htm [ Timeout ]
@@ -1885,8 +1890,6 @@
 crbug.com/626703 external/wpt/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_with_timing_attributes.html [ Failure ]
 crbug.com/626703 external/wpt/web-animations/interfaces/KeyframeEffect/composite.html [ Failure ]
 crbug.com/626703 external/wpt/web-animations/animation-model/combining-effects/effect-composition.html [ Failure ]
-crbug.com/626703 external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html [ Failure ]
-crbug.com/626703 external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html [ Failure ]
 crbug.com/626703 external/wpt/web-animations/interfaces/KeyframeEffect/copy-contructor.html [ Failure ]
 crbug.com/626703 external/wpt/web-animations/animation-model/animation-types/spacing-keyframes-filters.html [ Failure ]
 crbug.com/626703 external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/moving-documents.html [ Timeout ]
@@ -1911,11 +1914,14 @@
 crbug.com/626703 external/wpt/streams/readable-streams/readable-stream-reader.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/streams/readable-streams/tee.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/streams/readable-streams/templated.html [ Failure Timeout ]
-crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-timeout.html [ Timeout ]
-crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-multiple-calls.html [ Timeout ]
 crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-exception.html [ Timeout ]
-crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-invoked.html [ Timeout ]
 crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-iframe.html [ Timeout ]
+crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-invoked.html [ Timeout ]
+crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-multiple-calls.html [ Timeout ]
+crbug.com/626703 external/wpt/html/webappapis/idle-callbacks/callback-timeout.html [ Timeout ]
+crbug.com/666993 external/wpt/html/webappapis/idle-callbacks/basic.html [ Timeout ]
+crbug.com/666993 external/wpt/html/webappapis/idle-callbacks/callback-idle-periods.html [ Timeout ]
+crbug.com/666993 external/wpt/html/webappapis/idle-callbacks/callback-timeout-with-raf.html [ Timeout ]
 crbug.com/626703 external/wpt/html/browsers/the-window-object/window-open-noopener.html [ Timeout ]
 crbug.com/626703 external/csswg-test/css-display-3/display-contents-before-after-001.html [ Failure ]
 crbug.com/626703 external/csswg-test/css-display-3/display-contents-before-after-002.html [ Failure ]
@@ -1937,20 +1943,7 @@
 
 # Manual tests that have not been automated.
 crbug.com/626703 external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-email-add-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-password-add-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-search-add-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-tel-add-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-text-add-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-input-url-add-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/html/semantics/forms/constraints/tooShort-textarea-add-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/pointerevents/pointerevent_boundary_events_in_capturing-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/pointerevents/pointerevent_element_haspointercapture-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_click-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual.html [ Timeout ]
 crbug.com/626703 external/wpt/pointerevents/pointerlock/pointerevent_movementxy-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/selection/dir-manual.html [ Timeout ]
 
 # Other untriaged test failures, timeouts and crashes from newly-imported WPT tests.
 crbug.com/626703 external/wpt/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html [ Pass Timeout ]
@@ -2128,11 +2121,6 @@
 
 crbug.com/667371 inspector/elements/styles-1/color-aware-property-value-edit.html [ Pass Failure ]
 
-# Newly imported tests that time out.
-crbug.com/666993 external/wpt/html/webappapis/idle-callbacks/callback-idle-periods.html [ Timeout ]
-crbug.com/666993 external/wpt/html/webappapis/idle-callbacks/callback-timeout-with-raf.html [ Timeout ]
-crbug.com/666993 external/wpt/html/webappapis/idle-callbacks/basic.html [ Timeout ]
-
 # [css-ui] Imported tests from W3C suite.
 crbug.com/669473 external/csswg-test/css-ui-3/box-sizing-014.html [ Failure ]
 crbug.com/669473 external/csswg-test/css-ui-3/box-sizing-015.html [ Failure ]
@@ -2269,7 +2257,6 @@
 
 crbug.com/678487 http/tests/inspector/resource-tree/resource-tree-reload.html [ Failure Timeout Pass ]
 crbug.com/678487 virtual/mojo-loading/http/tests/inspector/resource-tree/resource-tree-reload.html [ Failure Timeout Pass ]
-crbug.com/678488 http/tests/inspector/search/source-frame-replace-2.html [ Timeout Pass ]
 crbug.com/678489 http/tests/inspector/tracing/timeline-script-parse.html [ Timeout Pass ]
 crbug.com/678489 virtual/mojo-loading/http/tests/inspector/tracing/timeline-script-parse.html [ Timeout Pass ]
 crbug.com/678490 http/tests/media/media-source/mediasource-seek-beyond-duration.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 09017faf..d18c531c 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -278,6 +278,8 @@
 external/wpt/mathml [ Skip ]
 ## Owners: none; No tests in the directory.
 # external/wpt/media [ Skip ]
+## Owners: mlamouri@chromium.org,zqzhang@chromium.org
+# external/wpt/mediasession [ Pass ]
 external/wpt/media-source [ Skip ]
 external/wpt/mediacapture-record [ Skip ]
 ## Owners: phoglund@chromium.org
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-during-dispatch-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/add-during-dispatch-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-during-dispatch-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/add-during-dispatch-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-during-dispatch.html b/third_party/WebKit/LayoutTests/device_orientation/motion/add-during-dispatch.html
similarity index 98%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-during-dispatch.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/add-during-dispatch.html
index 36fa543..8c4c6d0e6 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-during-dispatch.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/add-during-dispatch.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Test no fire listeners added during event dispatch.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-listener-from-callback-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/add-listener-from-callback-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-listener-from-callback-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/add-listener-from-callback-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-listener-from-callback.html b/third_party/WebKit/LayoutTests/device_orientation/motion/add-listener-from-callback.html
similarity index 97%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-listener-from-callback.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/add-listener-from-callback.html
index 356a98d3..9994abe0 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/add-listener-from-callback.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/add-listener-from-callback.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests that adding a new devicemotion event listener from a callback works as expected.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/create-event-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/create-event-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/create-event-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/create-event-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/create-event.html b/third_party/WebKit/LayoutTests/device_orientation/motion/create-event.html
similarity index 96%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/create-event.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/create-event.html
index 73eb60c..980c7aaf 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/create-event.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/create-event.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description("Tests that document.createEvent() works with DeviceMotionEvent.");
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/fire-last-event-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/fire-last-event-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/fire-last-event-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/fire-last-event-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/fire-last-event.html b/third_party/WebKit/LayoutTests/device_orientation/motion/fire-last-event.html
similarity index 98%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/fire-last-event.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/fire-last-event.html
index 13f470d..21586845 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/fire-last-event.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/fire-last-event.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 
 description('Tests to see if the last available event is fired.');
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/multiple-event-listeners-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/multiple-event-listeners-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/multiple-event-listeners-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/multiple-event-listeners-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/multiple-event-listeners.html b/third_party/WebKit/LayoutTests/device_orientation/motion/multiple-event-listeners.html
similarity index 98%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/multiple-event-listeners.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/multiple-event-listeners.html
index b9590599..ea405da 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/multiple-event-listeners.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/multiple-event-listeners.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 
 description('Tests using multiple event handlers for the Device Motion API.');
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/null-values-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/null-values-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/null-values-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/null-values-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/null-values.html b/third_party/WebKit/LayoutTests/device_orientation/motion/null-values.html
similarity index 98%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/null-values.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/null-values.html
index 23ace57d..18c966bf 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/null-values.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/null-values.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests using null values for some or all of the event properties.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/optional-event-properties-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/optional-event-properties-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/optional-event-properties-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/optional-event-properties-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/optional-event-properties.html b/third_party/WebKit/LayoutTests/device_orientation/motion/optional-event-properties.html
similarity index 98%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/optional-event-properties.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/optional-event-properties.html
index b00d05c..ff941ca 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/optional-event-properties.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/optional-event-properties.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description("Tests the optional properties of DeviceMotionEvent. Each property should be null if not set, or set to null or undefined.");
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/page-visibility-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/page-visibility-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/page-visibility-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/page-visibility-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/page-visibility.html b/third_party/WebKit/LayoutTests/device_orientation/motion/page-visibility.html
similarity index 96%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/page-visibility.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/page-visibility.html
index 15288102..65e663a7 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/page-visibility.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/page-visibility.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 
 description('Tests to check that devicemotion events are not fired when the page is not visible.');
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/window-property-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/motion/window-property-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/window-property-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/motion/window-property-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/window-property.html b/third_party/WebKit/LayoutTests/device_orientation/motion/window-property.html
similarity index 94%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/window-property.html
rename to third_party/WebKit/LayoutTests/device_orientation/motion/window-property.html
index 71c018d6..cd308cb 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceMotion/window-property.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/motion/window-property.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description("Tests that the window.DeviceMotionEvent and window.ondevicemotion properties are present.");
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/add-listener-from-callback-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/add-listener-from-callback-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/add-listener-from-callback.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback.html
similarity index 96%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/add-listener-from-callback.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback.html
index 41f834f..af25eb3 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/add-listener-from-callback.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests that adding a new event listener from a callback works as expected.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation-absolute-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation-absolute-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation-absolute.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute.html
similarity index 82%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation-absolute.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute.html
index f7451238..bf3605b1 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation-absolute.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script src="resources/basic-operation.js"></script>
 <script>
 description('Tests basic operation of deviceorientationabsolute event using mock data.');
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation.html
similarity index 81%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation.html
index e92d451..4c78cdda 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/basic-operation.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script src="resources/basic-operation.js"></script>
 <script>
 description('Tests basic operation of the deviceorientation event using mock data.');
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/create-event-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/create-event-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/create-event-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/create-event.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event.html
similarity index 95%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/create-event.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/create-event.html
index 962b394..d8e41ad 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/create-event.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests that document.createEvent() works with DeviceOrientationEvent.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-event-listeners-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-event-listeners-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-event-listeners.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners.html
similarity index 97%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-event-listeners.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners.html
index 487742d18..2e774ba 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-event-listeners.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners.html
@@ -1,6 +1,6 @@
 <html>
 <head>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-frames-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-frames-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-frames.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames.html
similarity index 96%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-frames.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames.html
index de8ad60..efe82da 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/multiple-frames.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests using DeviceOrientation from multiple frames.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/no-synchronous-events-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/no-synchronous-events-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/no-synchronous-events.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events.html
similarity index 91%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/no-synchronous-events.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events.html
index f7ff86c..6505088 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/no-synchronous-events.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests that events are never fired synchronously from a call to window.addEventListener().');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/null-values-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/null-values-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/null-values-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/null-values.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values.html
similarity index 97%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/null-values.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/null-values.html
index fbf293f..7a0280e 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/null-values.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests using null values for some of the event properties.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/optional-event-properties-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/optional-event-properties-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/optional-event-properties.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties.html
similarity index 97%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/optional-event-properties.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties.html
index 5a4c944..add4a1b 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/optional-event-properties.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests the optional properties of DeviceOrientationEvent. Each property should be null if not set, or set to null or undefined.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/page-visibility-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/page-visibility-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/page-visibility.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility.html
similarity index 96%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/page-visibility.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility.html
index c61adc7..e869ba8 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/page-visibility.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests to check that deviceorientation events are not fired when the page is not visible.');
 window.jsTestIsAsync = true;
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/resources/basic-operation.js b/third_party/WebKit/LayoutTests/device_orientation/orientation/resources/basic-operation.js
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/resources/basic-operation.js
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/resources/basic-operation.js
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/updates-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/updates-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/updates-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/updates-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/updates.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/updates.html
similarity index 96%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/updates.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/updates.html
index c7b600f..6e73fbd 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/updates.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/updates.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests that updates to the orientation causes new events to fire.');
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/window-property-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/window-property-expected.txt
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/window-property-expected.txt
diff --git a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/window-property.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property.html
similarity index 95%
rename from third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/window-property.html
rename to third_party/WebKit/LayoutTests/device_orientation/orientation/window-property.html
index 59c4a93..86f62f4 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/DeviceOrientation/window-property.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../../resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 <script>
 description('Tests that the window.DeviceOrientationEvent and window.ondeviceorientation and window.ondeviceorientationabsolute properties are present.');
 
diff --git a/third_party/WebKit/LayoutTests/editing/assert_selection.js b/third_party/WebKit/LayoutTests/editing/assert_selection.js
index 7d5a84cc..a66aa40 100644
--- a/third_party/WebKit/LayoutTests/editing/assert_selection.js
+++ b/third_party/WebKit/LayoutTests/editing/assert_selection.js
@@ -750,7 +750,8 @@
     if (this.loadSelectionInTextArea(selection))
       return;
     this.selection_.collapse(selection.anchorNode, selection.anchorOffset);
-    this.selection_.extend(selection.focusNode, selection.focusOffset);
+    if (this.selection_.rangeCount > 0)
+      this.selection_.extend(selection.focusNode, selection.focusOffset);
   }
 
   /**
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/indent-button-crash-expected.txt b/third_party/WebKit/LayoutTests/editing/execCommand/indent-button-crash-expected.txt
deleted file mode 100644
index 48aacce..0000000
--- a/third_party/WebKit/LayoutTests/editing/execCommand/indent-button-crash-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-PASS if Blink doesn't crash.
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/indent-button-crash.html b/third_party/WebKit/LayoutTests/editing/execCommand/indent-button-crash.html
deleted file mode 100644
index 7fa5f8121..0000000
--- a/third_party/WebKit/LayoutTests/editing/execCommand/indent-button-crash.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<script>
-if (window.testRunner)
-    testRunner.dumpAsText();
-
-var scriptElements = document.getElementsByTagName('script');
-for (var i = 0; i < scriptElements.length; i++) {
-    scriptElements[i].parentNode.removeChild(scriptElements[i]);
-}
-
-document.addEventListener('DOMCharacterDataModified', function() {
-    document.execCommand('Indent');
-});
-
-document.addEventListener('selectstart', function() {
-    var element = event.srcElement;
-    element.insertAdjacentElement('beforebegin', document.createElement('foo'));
-    element.insertAdjacentHTML('beforebegin', '<bar1><bar2><bar3>abc');
-});
-
-onload = function() {
-    document.execCommand('SelectAll', false);
-    document.designMode = 'on';
-    window.getSelection().getRangeAt(0).deleteContents();
-    document.body.textContent = 'PASS if Blink doesn\'t crash.';
-};
-</script>
-<style>
-*:read-write {
-    -webkit-appearance: push-button;
-}
-</style>
-<link>
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/transpose-backslash-with-euc.html b/third_party/WebKit/LayoutTests/editing/execCommand/transpose-backslash-with-euc.html
index a38b1e9..09bcb8a 100644
--- a/third_party/WebKit/LayoutTests/editing/execCommand/transpose-backslash-with-euc.html
+++ b/third_party/WebKit/LayoutTests/editing/execCommand/transpose-backslash-with-euc.html
@@ -11,6 +11,7 @@
 function test()
 {
     var backslashDivElement = document.getElementById("backslash");
+    getSelection().collapse(backslashDivElement, 0);
     getSelection().extend(backslashDivElement, 1);
     document.execCommand("Transpose");
 
diff --git a/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-DocumentType-expected.txt b/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-DocumentType-expected.txt
index 2e986234..14efec3 100644
--- a/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-DocumentType-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-DocumentType-expected.txt
@@ -7,6 +7,7 @@
 PASS sel.anchorNode is null
 PASS sel.anchorNode is null
 PASS sel.anchorNode is null
+PASS sel.extend(docType, 0) threw exception InvalidStateError: Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges..
 PASS sel.anchorNode is null
 PASS sel.anchorNode is null
 PASS sel.containsNode(docType) is false
diff --git a/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-crossing-document-expected.txt b/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-crossing-document-expected.txt
index b9945161..3d66abe 100644
--- a/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-crossing-document-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/selection/DOMSelection-crossing-document-expected.txt
@@ -7,6 +7,7 @@
 PASS mainSel.anchorNode is null
 PASS foreignSel.anchorNode is null
 PASS mainSel.anchorNode is null
+PASS mainSel.extend(foreignElement, 1) threw exception InvalidStateError: Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges..
 PASS foreignSel.anchorNode is null
 PASS mainSel.anchorNode is null
 PASS foreignSel.anchorNode is null
diff --git a/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js b/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js
index b4e9967f..6b83df332 100644
--- a/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js
+++ b/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-DocumentType.js
@@ -17,7 +17,7 @@
 sel.selectAllChildren(docType);
 shouldBeNull("sel.anchorNode");
 
-sel.extend(docType, 0);
+shouldThrow("sel.extend(docType, 0)");
 shouldBeNull("sel.anchorNode");
 
 sel.containsNode(docType);
diff --git a/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-crossing-document.js b/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-crossing-document.js
index 42634bf..e06a9c12 100644
--- a/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-crossing-document.js
+++ b/third_party/WebKit/LayoutTests/editing/selection/script-tests/DOMSelection-crossing-document.js
@@ -36,7 +36,7 @@
 shouldBeNull("mainSel.anchorNode");
 
 clear();
-mainSel.extend(foreignElement, 1);
+shouldThrow("mainSel.extend(foreignElement, 1)");
 shouldBeNull("foreignSel.anchorNode");
 shouldBeNull("mainSel.anchorNode");
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb-binary-key-detached.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb-binary-key-detached.htm
new file mode 100644
index 0000000..ab672fa8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb-binary-key-detached.htm
@@ -0,0 +1,51 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>IndexedDB: Detached buffers supplied as binary keys</title>
+<meta name="help" href="http://w3c.github.io/IndexedDB/#convert-a-value-to-a-key">
+<meta name="help" href="https://heycam.github.io/webidl/#dfn-get-buffer-source-copy">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<script>
+
+indexeddb_test(
+  (t, db) => { db.createObjectStore('store'); },
+  (t, db) => {
+    const tx = db.transaction('store', 'readwrite');
+    const store = tx.objectStore('store');
+
+    const buffer = new Uint8Array([1,2,3,4]).buffer;
+    assert_equals(buffer.byteLength, 4);
+
+    // Detach the ArrayBuffer by transferring it to a worker.
+    const worker = new Worker(URL.createObjectURL(new Blob([])));
+    worker.postMessage('', [buffer]);
+    assert_equals(buffer.byteLength, 0);
+
+    assert_throws(new TypeError, () => { store.put('', buffer); });
+    t.done();
+  },
+  'Detached ArrayBuffer'
+);
+
+indexeddb_test(
+  (t, db) => { db.createObjectStore('store'); },
+  (t, db) => {
+    const tx = db.transaction('store', 'readwrite');
+    const store = tx.objectStore('store');
+
+    const array = new Uint8Array([1,2,3,4]);
+    assert_equals(array.length, 4);
+
+    // Detach the ArrayBuffer by transferring it to a worker.
+    const worker = new Worker(URL.createObjectURL(new Blob([])));
+    worker.postMessage('', [array.buffer]);
+    assert_equals(array.length, 0);
+
+    assert_throws(new TypeError, () => { store.put('', array); });
+    t.done();
+  },
+  'Detached TypedArray'
+);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb-binary-key-roundtrip.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb-binary-key-roundtrip.htm
new file mode 100644
index 0000000..b1148d6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idb-binary-key-roundtrip.htm
@@ -0,0 +1,115 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>IndexedDB: Binary keys written to a database and read back</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<script>
+
+const sample = [0x44, 0x33, 0x22, 0x11, 0xFF, 0xEE, 0xDD, 0xCC];
+const buffer = new Uint8Array(sample).buffer;
+
+function assert_key_valid(a, message) {
+  assert_equals(indexedDB.cmp(a, a), 0, message);
+}
+
+function assert_buffer_equals(a, b, message) {
+  assert_array_equals(
+      Array.from(new Uint8Array(a)), Array.from(new Uint8Array(b)), message);
+}
+
+// Verifies that a JavaScript value round-trips through IndexedDB as a key.
+function check_key_roundtrip_and_done(t, db, key, key_buffer) {
+  const tx = db.transaction('store', 'readwrite');
+  const store = tx.objectStore('store');
+
+  // Verify put with key
+  const put_request = store.put('value', key);
+  put_request.onerror = t.unreached_func('put should succeed');
+
+  // Verify get with key
+  const get_request = store.get(key);
+  get_request.onerror = t.unreached_func('get should succeed');
+  get_request.onsuccess = t.step_func(() => {
+    assert_equals(
+        get_request.result, 'value',
+        'get should retrieve the value given to put');
+
+    // Verify iteration returning key
+    const cursor_request = store.openCursor();
+    cursor_request.onerror = t.unreached_func('openCursor should succeed');
+    cursor_request.onsuccess = t.step_func(() => {
+      assert_not_equals(
+          cursor_request.result, null, 'cursor should be present');
+      const retrieved_key = cursor_request.result.key;
+      assert_true(
+          retrieved_key instanceof ArrayBuffer,
+          'IndexedDB binary keys should be returned in ArrayBuffer instances');
+      assert_key_equals(
+          retrieved_key, key,
+          'The key returned by IndexedDB should equal the key given to put()');
+      assert_buffer_equals(
+          retrieved_key, key_buffer,
+          'The ArrayBuffer returned by IndexedDB should equal the buffer ' +
+          'backing the key given to put()');
+
+      t.done();
+    });
+  });
+}
+
+// Checks that IndexedDB handles the given view type for binary keys correctly.
+function view_type_test(type) {
+  indexeddb_test(
+    (t, db) => { db.createObjectStore('store'); },
+    (t, db) => {
+      const key = new self[type](buffer);
+      assert_key_valid(key, `${type} should be usable as an IndexedDB key`);
+      assert_key_equals(key, buffer,
+          'Binary keys with the same data but different view types should be ' +
+          ' equal');
+      check_key_roundtrip_and_done(t, db, key, buffer);
+    },
+    `Binary keys can be supplied using the view type ${type}`,
+  );
+}
+
+[
+  'Uint8Array',
+  'Uint8ClampedArray',
+  'Int8Array',
+  'Uint16Array',
+  'Int16Array',
+  'Uint32Array',
+  'Int32Array',
+  'Float32Array',
+  'Float64Array'
+].forEach((type) => { view_type_test(type); });
+
+// Checks that IndexedDB
+function value_test(value_description, value, value_buffer) {
+  indexeddb_test(
+    (t, db) => { db.createObjectStore('store'); },
+    (t, db) => {
+      assert_key_valid(
+          value, value_description + ' should be usable as an valid key');
+      check_key_roundtrip_and_done(t, db, value, value_buffer);
+    },
+    `${value_description} can be used to supply a binary key`
+  );
+}
+
+value_test('ArrayBuffer', buffer, buffer);
+value_test('DataView', new DataView(buffer), buffer);
+value_test('DataView with explicit offset', new DataView(buffer, 3),
+           new Uint8Array([0x11, 0xFF, 0xEE, 0xDD, 0xCC]).buffer);
+value_test('DataView with explicit offset and length',
+           new DataView(buffer, 3, 4),
+           new Uint8Array([0x11, 0xFF, 0xEE, 0xDD]).buffer);
+value_test('Uint8Array with explicit offset', new Uint8Array(buffer, 3),
+           new Uint8Array([0x11, 0xFF, 0xEE, 0xDD, 0xCC]).buffer);
+value_test('Uint8Array with explicit offset and length',
+           new Uint8Array(buffer, 3, 4),
+           new Uint8Array([0x11, 0xFF, 0xEE, 0xDD]).buffer);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js
index f1c599c..63b23e5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support.js
@@ -82,7 +82,7 @@
         })
     }
 
-    // add a .setTest method to the DB object
+    // add a .setTest method to the IDBOpenDBRequest object
     Object.defineProperty(rq_open, 'setTest', {
         enumerable: false,
         value: function(t) {
@@ -101,7 +101,7 @@
 }
 
 function assert_key_equals(actual, expected, description) {
-    assert_equals(indexedDB.cmp(actual, expected), 0, description);
+  assert_equals(indexedDB.cmp(actual, expected), 0, description);
 }
 
 function indexeddb_test(upgrade_func, open_func, description, options) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json b/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json
index 0cfcbca..a44a1150 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/wpt/MANIFEST.json
@@ -13992,6 +13992,16 @@
      {}
     ]
    ],
+   "mediasession/README.md": [
+    [
+     {}
+    ]
+   ],
+   "mediasession/idlharness-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "navigation-timing/idlharness-expected.txt": [
     [
      {}
@@ -17301,6 +17311,18 @@
      {}
     ]
    ],
+   "IndexedDB/idb-binary-key-detached.htm": [
+    [
+     "/IndexedDB/idb-binary-key-detached.htm",
+     {}
+    ]
+   ],
+   "IndexedDB/idb-binary-key-roundtrip.htm": [
+    [
+     "/IndexedDB/idb-binary-key-roundtrip.htm",
+     {}
+    ]
+   ],
    "IndexedDB/idb_binary_key_conversion.htm": [
     [
      "/IndexedDB/idb_binary_key_conversion.htm",
@@ -29259,6 +29281,30 @@
      {}
     ]
    ],
+   "mediasession/idlharness.html": [
+    [
+     "/mediasession/idlharness.html",
+     {}
+    ]
+   ],
+   "mediasession/mediametadata.html": [
+    [
+     "/mediasession/mediametadata.html",
+     {}
+    ]
+   ],
+   "mediasession/playbackstate.html": [
+    [
+     "/mediasession/playbackstate.html",
+     {}
+    ]
+   ],
+   "mediasession/setactionhandler.html": [
+    [
+     "/mediasession/setactionhandler.html",
+     {}
+    ]
+   ],
    "navigation-timing/idlharness.html": [
     [
      "/navigation-timing/idlharness.html",
@@ -34527,7 +34573,7 @@
    "support"
   ],
   "./MANIFEST.json": [
-   "94e506242954020d69b5240f63d2ef297d537608",
+   "468e5393eadca675d9f361840bdb4412f33351ac",
    "support"
   ],
   "./README.md": [
@@ -34790,6 +34836,14 @@
    "0c4584e1b021a286445a2a9d3388ff011a1b933e",
    "testharness"
   ],
+  "IndexedDB/idb-binary-key-detached.htm": [
+   "e7ed8b831bce3a06d21d629cd0112480dfc0f6a5",
+   "testharness"
+  ],
+  "IndexedDB/idb-binary-key-roundtrip.htm": [
+   "ed1e8ae0ca73fdc6fd4d15fcd7623f8f15b7f296",
+   "testharness"
+  ],
   "IndexedDB/idb_binary_key_conversion.htm": [
    "7af8d37d63bbef60a973082f7b9fde99d5dcfca6",
    "testharness"
@@ -35959,7 +36013,7 @@
    "support"
   ],
   "IndexedDB/support.js": [
-   "d419c2daaafebb732e83c0810be816393fdb14f7",
+   "a236eaf6599ad94f26166144a7afe21fafcc5770",
    "support"
   ],
   "IndexedDB/transaction-abort-generator-revert.html": [
@@ -51258,6 +51312,30 @@
    "2907c67a3ab9c22ba98f03acf16adc2f2b31ee30",
    "testharness"
   ],
+  "mediasession/README.md": [
+   "5ceecb2611837e6c52a303cec32d8cb9fabe93a6",
+   "support"
+  ],
+  "mediasession/idlharness-expected.txt": [
+   "9d213cce22b4300c0496ba5438bcc647e276688c",
+   "support"
+  ],
+  "mediasession/idlharness.html": [
+   "9aa84a0143daf03d9a95108d0407fda2443c9849",
+   "testharness"
+  ],
+  "mediasession/mediametadata.html": [
+   "0f0c1f7e3b58321a76229fa5a93e80b6863f181f",
+   "testharness"
+  ],
+  "mediasession/playbackstate.html": [
+   "e9edd18778d437b039bc45f2e3f35db725528447",
+   "testharness"
+  ],
+  "mediasession/setactionhandler.html": [
+   "70a1f9e81faa3dbbe320a71a008e4594a29878a8",
+   "testharness"
+  ],
   "navigation-timing/idlharness-expected.txt": [
    "306b63ff98511e156b27df4b6c0b2c65be597a39",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time-2-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time-2-expected.txt
deleted file mode 100644
index 416f08d7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/time-2-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-This is a testharness.js-based test.
-PASS empty value 
-PASS Valid value: value should be 00:00 
-PASS Valid value: value should be 00:00:00 
-PASS Valid value: value should be 00:00:00.0 
-PASS Valid value: value should be 00:00:00.00 
-PASS Valid value: value should be 00:00:00.000 
-FAIL Invalid value: fraction should have one, two or three ASCII digits. Value should be empty assert_equals: expected "" but got "00:00:00.0000"
-PASS Invalid value: hour should have two ASCII digits. Value should be empty 
-PASS Invalid value: minutes should have two ASCII digits. Value should be empty 
-PASS Invalid value: seconds should have two ASCII digits. Value should be empty 
-PASS Invalid value: hour > 23. Value should be empty 
-PASS Invalid value: minute > 59. Value should be empty 
-PASS Invalid value: second > 59. Value should be empty 
-PASS Value >= min attribute 
-PASS Value < min attribute 
-PASS Value <= max attribute 
-PASS Value > max attribute 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediasession/README.md b/third_party/WebKit/LayoutTests/external/wpt/mediasession/README.md
new file mode 100644
index 0000000..7c7c9f8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediasession/README.md
@@ -0,0 +1,20 @@
+# Media Session specification Tests
+
+The Media Session specification is available here: https://wicg.github.io/mediasession
+
+GitHub repository: https://github.com/WICG/mediasession
+
+File an issue: https://github.com/WICG/mediasession/issues/new
+
+## Device/system dependency
+
+The Media Session specification defines behaviors related to device or system
+features such as the actions to run when a software/hardware media key is used.
+These behaviors are not tested because they would depend on user agent specific
+implementations and device specific features.
+
+## Status of these tests
+
+These tests are not complete and only reflect the Blink tests that could be
+exported. If a reader find a behavior that could be tested and is not, they
+should feel free to file a bug.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness-expected.txt
new file mode 100644
index 0000000..a6e401c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness-expected.txt
@@ -0,0 +1,31 @@
+CONSOLE MESSAGE: line 251: callback not yet supported
+This is a testharness.js-based test.
+PASS Navigator interface: attribute mediaSession 
+PASS Navigator must be primary interface of navigator 
+PASS Stringification of navigator 
+PASS Navigator interface: navigator must inherit property "mediaSession" with the proper type (0) 
+PASS MediaSession interface: existence and properties of interface object 
+PASS MediaSession interface object length 
+PASS MediaSession interface object name 
+FAIL MediaSession interface: existence and properties of interface prototype object assert_equals: class string of MediaSession.prototype expected "[object MediaSessionPrototype]" but got "[object MediaSession]"
+PASS MediaSession interface: existence and properties of interface prototype object's "constructor" property 
+PASS MediaSession interface: attribute metadata 
+PASS MediaSession interface: attribute playbackState 
+PASS MediaSession interface: operation setActionHandler(MediaSessionAction,MediaSessionActionHandler) 
+PASS MediaMetadata interface: existence and properties of interface object 
+PASS MediaMetadata interface object length 
+PASS MediaMetadata interface object name 
+FAIL MediaMetadata interface: existence and properties of interface prototype object assert_equals: class string of MediaMetadata.prototype expected "[object MediaMetadataPrototype]" but got "[object MediaMetadata]"
+PASS MediaMetadata interface: existence and properties of interface prototype object's "constructor" property 
+PASS MediaMetadata interface: attribute title 
+PASS MediaMetadata interface: attribute artist 
+PASS MediaMetadata interface: attribute album 
+PASS MediaMetadata interface: attribute artwork 
+PASS MediaMetadata must be primary interface of [object MediaMetadata] 
+PASS Stringification of [object MediaMetadata] 
+PASS MediaMetadata interface: [object MediaMetadata] must inherit property "title" with the proper type (0) 
+PASS MediaMetadata interface: [object MediaMetadata] must inherit property "artist" with the proper type (1) 
+PASS MediaMetadata interface: [object MediaMetadata] must inherit property "album" with the proper type (2) 
+FAIL MediaMetadata interface: [object MediaMetadata] must inherit property "artwork" with the proper type (3) Unrecognized type FrozenArray
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.html
new file mode 100644
index 0000000..a90c83e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Media Session IDL tests</title>
+<link rel="help" href="https://wicg.github.io/mediasession/"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>Media Session IDL tests</h1>
+
+<pre id='untested_idl' style='display:none'>
+[PrimaryGlobal]
+interface Window {
+};
+
+interface Navigator {
+};
+</pre>
+
+<pre id='idl'>
+[Exposed=Window]
+partial interface Navigator {
+  [SameObject] readonly attribute MediaSession mediaSession;
+};
+
+enum MediaSessionPlaybackState {
+  "none",
+  "paused",
+  "playing"
+};
+
+enum MediaSessionAction {
+  "play",
+  "pause",
+  "seekbackward",
+  "seekforward",
+  "previoustrack",
+  "nexttrack",
+};
+
+callback MediaSessionActionHandler = void();
+
+[Exposed=Window]
+interface MediaSession {
+  attribute MediaMetadata? metadata;
+
+  attribute MediaSessionPlaybackState playbackState;
+
+  void setActionHandler(MediaSessionAction action, MediaSessionActionHandler? handler);
+};
+
+[Constructor(optional MediaMetadataInit init), Exposed=Window]
+interface MediaMetadata {
+  attribute DOMString title;
+  attribute DOMString artist;
+  attribute DOMString album;
+  attribute FrozenArray<MediaImage> artwork;
+};
+
+dictionary MediaMetadataInit {
+  DOMString title = "";
+  DOMString artist = "";
+  DOMString album = "";
+  sequence<MediaImage> artwork = [];
+};
+
+dictionary MediaImage {
+  required USVString src;
+  DOMString sizes = "";
+  DOMString type = "";
+};
+</pre>
+<script>
+var idl_array = new IdlArray();
+idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+idl_array.add_idls(document.getElementById("idl").textContent);
+idl_array.add_objects({
+  MediaMetadata: [new MediaMetadata()],
+  Navigator: ["navigator"]
+});
+idl_array.test();
+</script>
+<div id="log"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediasession/mediametadata.html b/third_party/WebKit/LayoutTests/external/wpt/mediasession/mediametadata.html
new file mode 100644
index 0000000..e545e73
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediasession/mediametadata.html
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<title>MediaMetadata interface</title>
+<script src=/resources/testharness.js></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+test(function() {
+  var metadata = new MediaMetadata({});
+  navigator.mediaSession.metadata = metadata;
+  assert_equals(navigator.mediaSession.metadata, metadata);
+}, "Test that mediaSession.metadata is properly set");
+
+test(function() {
+  var metadata = new MediaMetadata({});
+  navigator.mediaSession.metadata = metadata;
+  metadata.title = 'foo';
+  assert_equals(navigator.mediaSession.metadata.title, 'foo');
+}, "Test that changes to metadata propagate properly");
+
+test(function() {
+  var metadata = new MediaMetadata({});
+  navigator.mediaSession.metadata = metadata;
+  navigator.mediaSession.metadata = null;
+  assert_equals(navigator.mediaSession.metadata, null);
+}, "Test that resetting metadata to null is reflected");
+
+test(function() {
+  var metadata = new MediaMetadata({});
+  assert_not_equals(metadata, null);
+
+  assert_throws(new TypeError(), _ => new MediaMetadata('foobar'));
+  assert_throws(new TypeError(), _ => new MediaMetadata(42));
+}, 'Test that MediaMetadata is constructed using a dictionary');
+
+test(function() {
+  var metadata = new MediaMetadata();
+  assert_not_equals(metadata, null);
+}, "Test that MediaMetadata constructor can take no parameter");
+
+test(function() {
+  var image1 = { src: 'http://example.com/1', sizes: 'sizes1', type: 'type1' };
+  var image2 = { src: 'http://example.com/2', sizes: 'sizes2', type: 'type2' };
+  var metadata = new MediaMetadata({
+      title: 'foo', album: 'bar', artist: 'plop', artwork: [ image1, image2 ]
+  });
+
+  assert_equals(metadata.title, 'foo');
+  assert_equals(metadata.album, 'bar');
+  assert_equals(metadata.artist, 'plop');
+  assert_equals(metadata.artwork.length, 2);
+  assert_equals(metadata.artwork[0].src, image1.src);
+  assert_equals(metadata.artwork[0].sizes, image1.sizes);
+  assert_equals(metadata.artwork[0].type, image1.type);
+  assert_equals(metadata.artwork[1].src, image2.src);
+  assert_equals(metadata.artwork[1].sizes, image2.sizes);
+  assert_equals(metadata.artwork[1].type, image2.type);
+}, 'Test the different values allowed in MediaMetadata init dictionary');
+
+test(function() {
+  var metadata = new MediaMetadata({});
+  assert_equals(metadata.title, '');
+  assert_equals(metadata.artist, '');
+  assert_equals(metadata.album, '');
+  assert_equals(0, metadata.artwork.length);
+}, 'Test the default values for MediaMetadata with empty init dictionary');
+
+test(function() {
+  var metadata = new MediaMetadata();
+  assert_equals(metadata.title, '');
+  assert_equals(metadata.artist, '');
+  assert_equals(metadata.album, '');
+  assert_equals(0, metadata.artwork.length);
+}, 'Test the default values for MediaMetadata with no init dictionary');
+
+test(function() {
+  var metadata = new MediaMetadata({ randomValueThatWillNotBeAdded: '... hopefully ;)' });
+  assert_equals(metadata.randomValueThatWillNotBeAdded, undefined);
+}, 'Test that passing unknown values to the dictionary is a no-op');
+
+test(function() {
+  var image1 = { src: 'http://example.com/1', sizes: 'sizes1', type: 'type1' };
+  var image2 = { src: 'http://example.com/2', sizes: 'sizes2', type: 'type2' };
+  var metadata = new MediaMetadata({
+    title: 'foo', album: 'bar', artist: 'plop', artwork: [ image1, image2 ]
+  });
+
+  metadata.title = 'something else';
+  assert_equals(metadata.title, 'something else');
+
+  metadata.album = 'other value';
+  assert_equals(metadata.album, 'other value');
+
+  metadata.artist = 'someone else';
+  assert_equals(metadata.artist, 'someone else');
+
+  var image = { src: 'http://example.com/', sizes: '40x40', type: 'image/png' };
+  metadata.artwork = [ image ];
+  assert_equals(metadata.artwork.length, 1);
+  assert_equals(metadata.artwork[0].src, 'http://example.com/');
+  assert_equals(metadata.artwork[0].sizes, '40x40');
+  assert_equals(metadata.artwork[0].type, 'image/png');
+}, "Test that MediaMetadata is read/write");
+
+test(function() {
+  var metadata = new MediaMetadata({ artwork: [ { src: 'http://foo.com/' } ] });
+  assert_throws(new TypeError(), _ => {
+    metadata.artwork.push({
+      src: 'http://example.com/', sizes: '40x40', type: 'image/png',
+    });
+  });
+
+  metadata.artwork[0].src = 'bar';
+  assert_equals(metadata.artwork[0].src, 'http://foo.com/');
+}, "Test that MediaMetadat.artwork can't be modified");
+
+test(function() {
+  var metadata = new MediaMetadata({ artwork: [{
+    src: 'http://example.com/', sizes: '40x40', type: 'image/png',
+    some_other_value: 'foo',
+  }]});
+  assert_equals(metadata.artwork[0].src, 'http://example.com/');
+  assert_equals(metadata.artwork[0].sizes, '40x40');
+  assert_equals(metadata.artwork[0].type, 'image/png');
+  assert_false('some_other_value' in metadata.artwork[0]);
+
+  metadata.artwork[0].something_else = 'bar';
+  assert_false('something_else' in metadata.artwork[0]);
+}, "Test that MediaMetadata.artwork will not expose unknown properties");
+
+test(function() {
+  var metadata = new MediaMetadata({ artwork: [
+    { src: 'http://example.com/1', sizes: '40x40', type: 'image/png' },
+    { src: 'http://example.com/2', sizes: '40x40', type: 'image/png' },
+  ]});
+
+  assert_true(Object.isFrozen(metadata.artwork));
+  for (var i = 0; i < metadata.artwork.length; ++i)
+    assert_true(Object.isFrozen(metadata.artwork[i]));
+}, "Test that MediaMetadata.artwork is Frozen");
+
+test(function() {
+  var metadata = new MediaMetadata({ artwork: [
+    { src: 'http://example.com', sizes: '40x40', type: 'image/png' },
+    { src: '../foo', sizes: '40x40', type: 'image/png' },
+    { src: '/foo/bar', sizes: '40x40', type: 'image/png' },
+  ]});
+
+  assert_equals(metadata.artwork[0].src, new URL('http://example.com', document.URL).href)
+  assert_equals(metadata.artwork[1].src, new URL('../foo', document.URL).href)
+  assert_equals(metadata.artwork[2].src, new URL('/foo/bar', document.URL).href)
+}, "Test that MediaMetadata.artwork returns parsed urls");
+
+test(function() {
+  var metadata = 42;
+
+  assert_throws(new TypeError(), _ => {
+    metadata
+      new MediaMetadata({ artwork: [ { src: 'http://[example.com]' }] });
+  });
+  assert_equals(metadata, 42);
+
+  metadata = new MediaMetadata();
+  assert_throws(new TypeError(), _ => {
+    metadata.artwork = [
+      // Valid url.
+      { src: 'http://example.com' },
+      // Invalid url.
+      { src: 'http://example.com:demo' },
+    ];
+  });
+  assert_equals(metadata.artwork.length, 0);
+
+}, "Test that MediaMetadata throws when setting an invalid url");
+
+test(function() {
+  var metadata = new MediaMetadata({ artwork: [ { src: 'foo.jpg' } ] });
+  assert_equals(metadata.artwork[0].type, '');
+  assert_equals(metadata.artwork[0].sizes, '');
+}, "Test MediaImage default values");
+
+test(function() {
+  assert_throws(new TypeError(), _ => {
+    new MediaMetadata({ artwork: [ {} ] });
+  });
+
+  var metadata = new MediaMetadata();
+  assert_throws(new TypeError(), _ => {
+    metadata.artwork = [ { type: 'image/png', sizes: '40x40' } ];
+  });
+}, "Test that MediaImage.src is required")
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/media/mediasession/mediasession-playbackstate.html b/third_party/WebKit/LayoutTests/external/wpt/mediasession/playbackstate.html
similarity index 87%
rename from third_party/WebKit/LayoutTests/media/mediasession/mediasession-playbackstate.html
rename to third_party/WebKit/LayoutTests/external/wpt/mediasession/playbackstate.html
index 71ba39d..63f3548d 100644
--- a/third_party/WebKit/LayoutTests/media/mediasession/mediasession-playbackstate.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediasession/playbackstate.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>MediaSession.playbackState attribute</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
+<script src=/resources/testharness.js></script>
+<script src="/resources/testharnessreport.js"></script>
 <script>
 
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/media/mediasession/mediasession-setactionhandler.html b/third_party/WebKit/LayoutTests/external/wpt/mediasession/setactionhandler.html
similarity index 89%
rename from third_party/WebKit/LayoutTests/media/mediasession/mediasession-setactionhandler.html
rename to third_party/WebKit/LayoutTests/external/wpt/mediasession/setactionhandler.html
index 815a9a4f..120686ae 100644
--- a/third_party/WebKit/LayoutTests/media/mediasession/mediasession-setactionhandler.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediasession/setactionhandler.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>Test that setting MediaSession event handler should notify the service</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
+<script src=/resources/testharness.js></script>
+<script src="/resources/testharnessreport.js"></script>
 <script>
 
 test(function(t) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual-expected.txt
new file mode 100644
index 0000000..6e2f7190a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL touch two-finger pan on 'touch-action: pan-x pan-y' assert_equals: expected "pointerdown@black, pointerdown@black, pointerup@black, pointerup@black" but got "pointerdown@black, pointerdown@black, pointercancel@black, pointercancel@black"
+PASS touch two-finger pan on 'touch-action: pinch-zoom' 
+PASS PointerEvent Automation 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
index 362d6ce..89f3d839 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
@@ -120,12 +120,12 @@
         <h1>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</h1>
         <h4>
             Test Description:
+            Use your pointer and press down in the black box. Then move around in the box and release your pointer.
             After invoking the releasePointerCapture method on an element, subsequent events for the specified
-            pointer must follow normal hit testing mechanisms for determining the event target
+            pointer must follow normal hit testing mechanisms for determining the event target.
         </h4>
         <br />
         <div id="target0">
-            Use mouse, touch or pen to contact here and move around.
         </div>
         <div id="complete-notice">
             <p>Test complete:  Scroll to Summary to view Pass/Fail Results.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/extend-00-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/extend-00-expected.txt
index 7979d05..1bf1a60 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/extend-00-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/extend-00-expected.txt
@@ -263,270 +263,94 @@
 CONSOLE ERROR: line 944: The given range isn't in document.
 CONSOLE ERROR: line 944: The given range isn't in document.
 This is a testharness.js-based test.
-FAIL extend() with range 0 [] and point 0 [paras[0].firstChild, -1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': -1 is not a valid offset." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 1 [paras[0].firstChild, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 2 [paras[0].firstChild, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 3 [paras[0].firstChild, 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 4 [paras[0].firstChild, 8] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 5 [paras[0].firstChild, 9] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 6 [paras[0].firstChild, 10] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 7 [paras[0].firstChild, 65535] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 65535 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 8 [paras[1].firstChild, -1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': -1 is not a valid offset." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 9 [paras[1].firstChild, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 10 [paras[1].firstChild, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 11 [paras[1].firstChild, 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 12 [paras[1].firstChild, 8] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 13 [paras[1].firstChild, 9] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 14 [paras[1].firstChild, 10] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 10 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 15 [paras[1].firstChild, 65535] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 65535 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 16 [detachedPara1.firstChild, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 17 [detachedPara1.firstChild, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 18 [detachedPara1.firstChild, 8] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 19 [detachedPara1.firstChild, 9] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 9 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 20 [foreignPara1.firstChild, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 21 [foreignPara1.firstChild, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 22 [foreignPara1.firstChild, 8] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 23 [foreignPara1.firstChild, 9] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 9 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 24 [document.documentElement, -1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': -1 is not a valid offset." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 25 [document.documentElement, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 26 [document.documentElement, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 27 [document.documentElement, 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 28 [document.documentElement, 7] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 7 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 29 [document.head, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 30 [document.body, 3] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 31 [foreignDoc.documentElement, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 32 [foreignDoc.documentElement, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 33 [foreignDoc.head, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 34 [foreignDoc.body, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 35 [paras[0], 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 36 [paras[0], 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 37 [paras[0], 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 2 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 38 [paras[1], 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 39 [paras[1], 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 40 [paras[1], 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 2 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 41 [detachedPara1, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 42 [detachedPara1, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 43 [testDiv, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 44 [testDiv, 3] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 45 [document, -1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': -1 is not a valid offset." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 46 [document, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 47 [document, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 48 [document, 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 49 [document, 3] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 3 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 50 [comment, -1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': -1 is not a valid offset." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 51 [comment, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 52 [comment, 4] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 53 [comment, 96] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 96 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 54 [foreignDoc, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 55 [foreignDoc, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 56 [foreignComment, 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 57 [foreignTextNode, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 58 [foreignTextNode, 36] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 59 [xmlDoc, -1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': -1 is not a valid offset." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 60 [xmlDoc, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 61 [xmlDoc, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 62 [xmlDoc, 5] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 5 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 63 [xmlComment, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 64 [xmlComment, 4] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 65 [processingInstruction, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 66 [processingInstruction, 5] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 67 [processingInstruction, 9] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 68 [detachedTextNode, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 69 [detachedTextNode, 8] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 70 [detachedForeignTextNode, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 71 [detachedForeignTextNode, 8] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 72 [detachedXmlTextNode, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 73 [detachedXmlTextNode, 8] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 74 [detachedProcessingInstruction, 12] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 75 [detachedComment, 3] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 76 [detachedComment, 5] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 77 [detachedForeignComment, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 78 [detachedForeignComment, 4] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 79 [detachedXmlComment, 2] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 80 [docfrag, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 81 [foreignDocfrag, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 82 [xmlDocfrag, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 83 [doctype, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 84 [doctype, -17] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': -17 is not a valid offset." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 85 [doctype, 1] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" threw object "IndexSizeError: Failed to execute 'extend' on 'Selection': 1 is larger than the given node's length." that is not a DOMException INVALID_STATE_ERR: property "code" is equal to 1, expected 11
-FAIL extend() with range 0 [] and point 86 [foreignDoctype, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
-FAIL extend() with range 0 [] and point 87 [xmlDoctype, 0] assert_throws: extend() when rangeCount is 0 must throw InvalidStateError function "function () {
-            selection.extend(node, offset);
-        }" did not throw
+PASS extend() with range 0 [] and point 0 [paras[0].firstChild, -1] 
+PASS extend() with range 0 [] and point 1 [paras[0].firstChild, 0] 
+PASS extend() with range 0 [] and point 2 [paras[0].firstChild, 1] 
+PASS extend() with range 0 [] and point 3 [paras[0].firstChild, 2] 
+PASS extend() with range 0 [] and point 4 [paras[0].firstChild, 8] 
+PASS extend() with range 0 [] and point 5 [paras[0].firstChild, 9] 
+PASS extend() with range 0 [] and point 6 [paras[0].firstChild, 10] 
+PASS extend() with range 0 [] and point 7 [paras[0].firstChild, 65535] 
+PASS extend() with range 0 [] and point 8 [paras[1].firstChild, -1] 
+PASS extend() with range 0 [] and point 9 [paras[1].firstChild, 0] 
+PASS extend() with range 0 [] and point 10 [paras[1].firstChild, 1] 
+PASS extend() with range 0 [] and point 11 [paras[1].firstChild, 2] 
+PASS extend() with range 0 [] and point 12 [paras[1].firstChild, 8] 
+PASS extend() with range 0 [] and point 13 [paras[1].firstChild, 9] 
+PASS extend() with range 0 [] and point 14 [paras[1].firstChild, 10] 
+PASS extend() with range 0 [] and point 15 [paras[1].firstChild, 65535] 
+PASS extend() with range 0 [] and point 16 [detachedPara1.firstChild, 0] 
+PASS extend() with range 0 [] and point 17 [detachedPara1.firstChild, 1] 
+PASS extend() with range 0 [] and point 18 [detachedPara1.firstChild, 8] 
+PASS extend() with range 0 [] and point 19 [detachedPara1.firstChild, 9] 
+PASS extend() with range 0 [] and point 20 [foreignPara1.firstChild, 0] 
+PASS extend() with range 0 [] and point 21 [foreignPara1.firstChild, 1] 
+PASS extend() with range 0 [] and point 22 [foreignPara1.firstChild, 8] 
+PASS extend() with range 0 [] and point 23 [foreignPara1.firstChild, 9] 
+PASS extend() with range 0 [] and point 24 [document.documentElement, -1] 
+PASS extend() with range 0 [] and point 25 [document.documentElement, 0] 
+PASS extend() with range 0 [] and point 26 [document.documentElement, 1] 
+PASS extend() with range 0 [] and point 27 [document.documentElement, 2] 
+PASS extend() with range 0 [] and point 28 [document.documentElement, 7] 
+PASS extend() with range 0 [] and point 29 [document.head, 1] 
+PASS extend() with range 0 [] and point 30 [document.body, 3] 
+PASS extend() with range 0 [] and point 31 [foreignDoc.documentElement, 0] 
+PASS extend() with range 0 [] and point 32 [foreignDoc.documentElement, 1] 
+PASS extend() with range 0 [] and point 33 [foreignDoc.head, 0] 
+PASS extend() with range 0 [] and point 34 [foreignDoc.body, 1] 
+PASS extend() with range 0 [] and point 35 [paras[0], 0] 
+PASS extend() with range 0 [] and point 36 [paras[0], 1] 
+PASS extend() with range 0 [] and point 37 [paras[0], 2] 
+PASS extend() with range 0 [] and point 38 [paras[1], 0] 
+PASS extend() with range 0 [] and point 39 [paras[1], 1] 
+PASS extend() with range 0 [] and point 40 [paras[1], 2] 
+PASS extend() with range 0 [] and point 41 [detachedPara1, 0] 
+PASS extend() with range 0 [] and point 42 [detachedPara1, 1] 
+PASS extend() with range 0 [] and point 43 [testDiv, 0] 
+PASS extend() with range 0 [] and point 44 [testDiv, 3] 
+PASS extend() with range 0 [] and point 45 [document, -1] 
+PASS extend() with range 0 [] and point 46 [document, 0] 
+PASS extend() with range 0 [] and point 47 [document, 1] 
+PASS extend() with range 0 [] and point 48 [document, 2] 
+PASS extend() with range 0 [] and point 49 [document, 3] 
+PASS extend() with range 0 [] and point 50 [comment, -1] 
+PASS extend() with range 0 [] and point 51 [comment, 0] 
+PASS extend() with range 0 [] and point 52 [comment, 4] 
+PASS extend() with range 0 [] and point 53 [comment, 96] 
+PASS extend() with range 0 [] and point 54 [foreignDoc, 0] 
+PASS extend() with range 0 [] and point 55 [foreignDoc, 1] 
+PASS extend() with range 0 [] and point 56 [foreignComment, 2] 
+PASS extend() with range 0 [] and point 57 [foreignTextNode, 0] 
+PASS extend() with range 0 [] and point 58 [foreignTextNode, 36] 
+PASS extend() with range 0 [] and point 59 [xmlDoc, -1] 
+PASS extend() with range 0 [] and point 60 [xmlDoc, 0] 
+PASS extend() with range 0 [] and point 61 [xmlDoc, 1] 
+PASS extend() with range 0 [] and point 62 [xmlDoc, 5] 
+PASS extend() with range 0 [] and point 63 [xmlComment, 0] 
+PASS extend() with range 0 [] and point 64 [xmlComment, 4] 
+PASS extend() with range 0 [] and point 65 [processingInstruction, 0] 
+PASS extend() with range 0 [] and point 66 [processingInstruction, 5] 
+PASS extend() with range 0 [] and point 67 [processingInstruction, 9] 
+PASS extend() with range 0 [] and point 68 [detachedTextNode, 0] 
+PASS extend() with range 0 [] and point 69 [detachedTextNode, 8] 
+PASS extend() with range 0 [] and point 70 [detachedForeignTextNode, 0] 
+PASS extend() with range 0 [] and point 71 [detachedForeignTextNode, 8] 
+PASS extend() with range 0 [] and point 72 [detachedXmlTextNode, 0] 
+PASS extend() with range 0 [] and point 73 [detachedXmlTextNode, 8] 
+PASS extend() with range 0 [] and point 74 [detachedProcessingInstruction, 12] 
+PASS extend() with range 0 [] and point 75 [detachedComment, 3] 
+PASS extend() with range 0 [] and point 76 [detachedComment, 5] 
+PASS extend() with range 0 [] and point 77 [detachedForeignComment, 0] 
+PASS extend() with range 0 [] and point 78 [detachedForeignComment, 4] 
+PASS extend() with range 0 [] and point 79 [detachedXmlComment, 2] 
+PASS extend() with range 0 [] and point 80 [docfrag, 0] 
+PASS extend() with range 0 [] and point 81 [foreignDocfrag, 0] 
+PASS extend() with range 0 [] and point 82 [xmlDocfrag, 0] 
+PASS extend() with range 0 [] and point 83 [doctype, 0] 
+PASS extend() with range 0 [] and point 84 [doctype, -17] 
+PASS extend() with range 0 [] and point 85 [doctype, 1] 
+PASS extend() with range 0 [] and point 86 [foreignDoctype, 0] 
+PASS extend() with range 0 [] and point 87 [xmlDoctype, 0] 
 PASS extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 0 [paras[0].firstChild, -1] 
 PASS extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 1 [paras[0].firstChild, 0] 
 FAIL extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 2 [paras[0].firstChild, 1] assert_equals: focusOffset must be the offset passed to extend() expected 1 but got 2
@@ -2557,357 +2381,357 @@
 FAIL extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
@@ -2997,357 +2821,357 @@
 FAIL extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 PASS extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 0 [paras[0].firstChild, -1] 
 FAIL extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: startContainer must be correct expected Element node <html><head><title>Selection extend() tests</title>
 <meta... but got Text node "Äb̈c̈d̈ëf̈g̈ḧ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/extend-20-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/extend-20-expected.txt
index 1c9e6922..5cc2ff8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/extend-20-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/extend-20-expected.txt
@@ -176,181 +176,181 @@
 CONSOLE ERROR: line 944: The given range isn't in document.
 This is a testharness.js-based test.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
@@ -1202,181 +1202,181 @@
 FAIL extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 PASS extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 0 [paras[0].firstChild, -1] 
 FAIL extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: endContainer must be correct expected Text node "Ijklmnop
 " but got Element node <p id="c">Qrstuvwx</p>
@@ -3719,181 +3719,181 @@
 <meta... but got Text node "Äb̈c̈d̈ëf̈g̈ḧ
 "
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 PASS extend() forwards with range 35 [document, 0, document, 1] and point 0 [paras[0].firstChild, -1] 
 FAIL extend() backwards with range 35 [document, 0, document, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: startContainer must be correct expected Document node with 2 children but got Text node "Äb̈c̈d̈ëf̈g̈ḧ
 "
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/extend-40-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/extend-40-expected.txt
index 0e9026a2..0946b73f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/extend-40-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/extend-40-expected.txt
@@ -704,357 +704,357 @@
 FAIL extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
@@ -1144,357 +1144,357 @@
 FAIL extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
@@ -1584,181 +1584,181 @@
 FAIL extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
@@ -1848,357 +1848,357 @@
 FAIL extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
@@ -2288,181 +2288,181 @@
 FAIL extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
@@ -2552,181 +2552,181 @@
 FAIL extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 0 [paras[0].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 1 [paras[0].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 2 [paras[0].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 3 [paras[0].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 3 [paras[0].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 4 [paras[0].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 4 [paras[0].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 5 [paras[0].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 5 [paras[0].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 6 [paras[0].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 6 [paras[0].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 7 [paras[0].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 7 [paras[0].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 8 [paras[1].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 8 [paras[1].firstChild, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 9 [paras[1].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 9 [paras[1].firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 10 [paras[1].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 10 [paras[1].firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 11 [paras[1].firstChild, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 11 [paras[1].firstChild, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 12 [paras[1].firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 12 [paras[1].firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 13 [paras[1].firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 13 [paras[1].firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 14 [paras[1].firstChild, 10] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 14 [paras[1].firstChild, 10] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 15 [paras[1].firstChild, 65535] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 15 [paras[1].firstChild, 65535] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 16 [detachedPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 16 [detachedPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 17 [detachedPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 17 [detachedPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 18 [detachedPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 18 [detachedPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 19 [detachedPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 19 [detachedPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 20 [foreignPara1.firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 20 [foreignPara1.firstChild, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 21 [foreignPara1.firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 21 [foreignPara1.firstChild, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 22 [foreignPara1.firstChild, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 22 [foreignPara1.firstChild, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 23 [foreignPara1.firstChild, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 23 [foreignPara1.firstChild, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 24 [document.documentElement, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 24 [document.documentElement, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 25 [document.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 25 [document.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 26 [document.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 26 [document.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 27 [document.documentElement, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 27 [document.documentElement, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 28 [document.documentElement, 7] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 28 [document.documentElement, 7] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 29 [document.head, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 29 [document.head, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 30 [document.body, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 30 [document.body, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 31 [foreignDoc.documentElement, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 31 [foreignDoc.documentElement, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 32 [foreignDoc.documentElement, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 32 [foreignDoc.documentElement, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 33 [foreignDoc.head, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 33 [foreignDoc.head, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 34 [foreignDoc.body, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 34 [foreignDoc.body, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 35 [paras[0], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 35 [paras[0], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 36 [paras[0], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 36 [paras[0], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 37 [paras[0], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 37 [paras[0], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 38 [paras[1], 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 38 [paras[1], 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 39 [paras[1], 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 39 [paras[1], 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 40 [paras[1], 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 40 [paras[1], 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 41 [detachedPara1, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 41 [detachedPara1, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 42 [detachedPara1, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 42 [detachedPara1, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 43 [testDiv, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 43 [testDiv, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 44 [testDiv, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 44 [testDiv, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 45 [document, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 45 [document, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 46 [document, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 46 [document, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 47 [document, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 47 [document, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 48 [document, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 48 [document, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 49 [document, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 49 [document, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 50 [comment, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 50 [comment, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 51 [comment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 51 [comment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 52 [comment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 52 [comment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 53 [comment, 96] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 53 [comment, 96] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 54 [foreignDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 54 [foreignDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 55 [foreignDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 55 [foreignDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 56 [foreignComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 56 [foreignComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 57 [foreignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 57 [foreignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 58 [foreignTextNode, 36] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 58 [foreignTextNode, 36] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 59 [xmlDoc, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 59 [xmlDoc, -1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 60 [xmlDoc, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 60 [xmlDoc, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 61 [xmlDoc, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 61 [xmlDoc, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 62 [xmlDoc, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 62 [xmlDoc, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 63 [xmlComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 63 [xmlComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 64 [xmlComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 64 [xmlComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 65 [processingInstruction, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 65 [processingInstruction, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 66 [processingInstruction, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 66 [processingInstruction, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 67 [processingInstruction, 9] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 67 [processingInstruction, 9] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 68 [detachedTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 68 [detachedTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 69 [detachedTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 69 [detachedTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 70 [detachedForeignTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 70 [detachedForeignTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 71 [detachedForeignTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 71 [detachedForeignTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 72 [detachedXmlTextNode, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 72 [detachedXmlTextNode, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 73 [detachedXmlTextNode, 8] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 73 [detachedXmlTextNode, 8] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 74 [detachedProcessingInstruction, 12] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 74 [detachedProcessingInstruction, 12] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 75 [detachedComment, 3] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 75 [detachedComment, 3] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 76 [detachedComment, 5] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 76 [detachedComment, 5] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 77 [detachedForeignComment, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 77 [detachedForeignComment, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 78 [detachedForeignComment, 4] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 78 [detachedForeignComment, 4] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 79 [detachedXmlComment, 2] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 79 [detachedXmlComment, 2] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 80 [docfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 80 [docfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 81 [foreignDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 81 [foreignDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 82 [xmlDocfrag, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 82 [xmlDocfrag, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 83 [doctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 83 [doctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 84 [doctype, -17] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 84 [doctype, -17] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 85 [doctype, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 85 [doctype, 1] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 86 [foreignDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 86 [foreignDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
-FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 87 [xmlDoctype, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
+FAIL extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 87 [xmlDoctype, 0] Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL extend() with range 56 [docfrag, 0, docfrag, 0] and point 0 [paras[0].firstChild, -1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 56 [docfrag, 0, docfrag, 0] and point 1 [paras[0].firstChild, 0] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
 FAIL extend() with range 56 [docfrag, 0, docfrag, 0] and point 2 [paras[0].firstChild, 1] assert_equals: Sanity check: rangeCount must be correct expected 1 but got 0
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt
index 8d50fe5..4031d547 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt
@@ -37,7 +37,7 @@
 PASS Selection interface: getSelection() must inherit property "extend" with the proper type (8) 
 FAIL Selection interface: calling extend(Node,unsigned long) on getSelection() with too few arguments must throw TypeError assert_throws: Called with 1 arguments function "function () {
             fn.apply(obj, args);
-        }" did not throw
+        }" threw object "InvalidStateError: Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges." ("InvalidStateError") expected object "TypeError" ("TypeError")
 PASS Selection interface: getSelection() must inherit property "selectAllChildren" with the proper type (9) 
 PASS Selection interface: calling selectAllChildren(Node) on getSelection() with too few arguments must throw TypeError 
 PASS Selection interface: getSelection() must inherit property "deleteFromDocument" with the proper type (10) 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/removeAllRanges-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/removeAllRanges-expected.txt
index 38bb25f..ae625b5f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/removeAllRanges-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/removeAllRanges-expected.txt
@@ -27,17 +27,17 @@
 FAIL Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 15 [document.documentElement, 0, document.documentElement, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 15 [document.documentElement, 0, document.documentElement, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 16 [document.documentElement, 0, document.documentElement, 2] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
@@ -49,19 +49,19 @@
 FAIL Range 19 [document.body, 0, document.body, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 19 [document.body, 0, document.body, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 23 [paras[0], 0, paras[0], 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 23 [paras[0], 0, paras[0], 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 24 [paras[0], 0, paras[0], 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 24 [paras[0], 0, paras[0], 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 25 [detachedPara1, 0, detachedPara1, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 25 [detachedPara1, 0, detachedPara1, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 25 [detachedPara1, 0, detachedPara1, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 26 [detachedPara1, 0, detachedPara1, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 26 [detachedPara1, 0, detachedPara1, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 26 [detachedPara1, 0, detachedPara1, 1] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
@@ -77,7 +77,7 @@
 FAIL Range 33 [document.documentElement, 1, document.body, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 33 [document.documentElement, 1, document.body, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 35 [document, 0, document, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 35 [document, 0, document, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 36 [document, 0, document, 2] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
@@ -91,40 +91,40 @@
 FAIL Range 40 [paras[3], 1, comment, 8] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 40 [paras[3], 1, comment, 8] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
 FAIL Range 41 [foreignDoc, 0, foreignDoc, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 41 [foreignDoc, 0, foreignDoc, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 41 [foreignDoc, 0, foreignDoc, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 42 [foreignDoc, 1, foreignComment, 2] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 42 [foreignDoc, 1, foreignComment, 2] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 42 [foreignDoc, 1, foreignComment, 2] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 43 [foreignDoc.body, 0, foreignTextNode, 36] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 43 [foreignDoc.body, 0, foreignTextNode, 36] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 43 [foreignDoc.body, 0, foreignTextNode, 36] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 44 [xmlDoc, 0, xmlDoc, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 44 [xmlDoc, 0, xmlDoc, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 44 [xmlDoc, 0, xmlDoc, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 45 [xmlDoc, 1, xmlComment, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 45 [xmlDoc, 1, xmlComment, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 45 [xmlDoc, 1, xmlComment, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 46 [detachedTextNode, 0, detachedTextNode, 8] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 46 [detachedTextNode, 0, detachedTextNode, 8] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 46 [detachedTextNode, 0, detachedTextNode, 8] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 51 [detachedComment, 3, detachedComment, 4] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 51 [detachedComment, 3, detachedComment, 4] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 51 [detachedComment, 3, detachedComment, 4] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 52 [detachedComment, 5, detachedComment, 5] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 52 [detachedComment, 5, detachedComment, 5] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 52 [detachedComment, 5, detachedComment, 5] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 56 [docfrag, 0, docfrag, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 56 [docfrag, 0, docfrag, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 56 [docfrag, 0, docfrag, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 FAIL Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] forwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
-FAIL Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] backwards assert_equals: After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset expected 1 but got 2
+FAIL Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] backwards Failed to execute 'extend' on 'Selection': This Selection object doesn't have any Ranges.
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual-automation.js b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual-automation.js
new file mode 100644
index 0000000..4c994216
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual-automation.js
@@ -0,0 +1,11 @@
+importAutomationScript('/pointerevents/pointerevent_common_input.js');
+
+function inject_input() {
+  return twoPointerDragInTarget('touch', '#black', 'down').then(function() {
+    return touchTapInTarget('#done');
+  }).then(function() {
+    return twoPointerDragInTarget('touch', '#grey', 'down');
+  }).then(function() {
+    return touchTapInTarget('#done');
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_boundary_events_in_capturing-manual-automation.js b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_boundary_events_in_capturing-manual-automation.js
new file mode 100644
index 0000000..6cd7425
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_boundary_events_in_capturing-manual-automation.js
@@ -0,0 +1,9 @@
+importAutomationScript('/pointerevents/pointerevent_common_input.js');
+
+function inject_input() {
+  return pointerDragInTarget('mouse', '#target0', 'right').then(function() {
+    return pointerDragInTarget('touch', '#target0', 'right');
+  }).then(function() {
+    return pointerDragInTarget('pen', '#target0', 'right');
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_common_input.js b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_common_input.js
index 16e8661..8a79e44 100644
--- a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_common_input.js
+++ b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_common_input.js
@@ -1,8 +1,7 @@
 // This file contains the commonly used functions in pointerevent tests.
 
-const scrollOffset = 30;
-const boundaryOffset = 5;
-const touchSourceType = 1;
+const scrollOffset = 20;
+const boundaryOffset = 2;
 
 function delayPromise(delay) {
   return new Promise(function(resolve, reject) {
@@ -23,8 +22,8 @@
     if (window.chrome && chrome.gpuBenchmarking) {
       chrome.gpuBenchmarking.pointerActionSequence(
           [{
-            'source': 'mouse',
-            'actions': [{'name': 'pointerMove', 'x': 0, 'y': 0}]
+            source: 'mouse',
+            actions: [{name: 'pointerMove', x: 0, y: 0}]
           }],
           resolve);
     } else {
@@ -52,9 +51,9 @@
       var yPosition = frameTop + targetRect.top + boundaryOffset;
       chrome.gpuBenchmarking.pointerActionSequence(
           [{
-            'source': 'mouse',
-            'actions':
-                [{'name': 'pointerMove', 'x': xPosition, 'y': yPosition}]
+            source: 'mouse',
+            actions:
+                [{name: 'pointerMove', x: xPosition, y: yPosition}]
           }],
           resolve);
     } else {
@@ -73,22 +72,22 @@
       var yPosition = targetRect.top + boundaryOffset;
       chrome.gpuBenchmarking.pointerActionSequence(
           [{
-            'source': 'mouse',
-            'actions': [
+            source: 'mouse',
+            actions: [
               {
-                'name': 'pointerDown',
-                'x': xPosition,
-                'y': yPosition,
-                'button': 'left'
+                name: 'pointerDown',
+                x: xPosition,
+                y: yPosition,
+                button: 'left'
               },
               {
-                'name': 'pointerDown',
-                'x': xPosition,
-                'y': yPosition,
-                'button': 'middle'
+                name: 'pointerDown',
+                x: xPosition,
+                y: yPosition,
+                button: 'middle'
               },
-              {'name': 'pointerUp', 'button': 'middle'},
-              {'name': 'pointerUp', 'button': 'left'}
+              {name: 'pointerUp', button: 'middle'},
+              {name: 'pointerUp', button: 'left'}
             ]
           }],
           resolve);
@@ -117,11 +116,11 @@
       var yPosition = frameTop + targetRect.top + boundaryOffset;
       chrome.gpuBenchmarking.pointerActionSequence(
           [{
-            'source': 'mouse',
-            'actions': [
-              {'name': 'pointerMove', 'x': xPosition, 'y': yPosition},
-              {'name': 'pointerDown', 'x': xPosition, 'y': yPosition},
-              {'name': 'pointerUp'}
+            source: 'mouse',
+            actions: [
+              {name: 'pointerMove', x: xPosition, y: yPosition},
+              {name: 'pointerDown', x: xPosition, y: yPosition},
+              {name: 'pointerUp'}
             ]
           }],
           resolve);
@@ -143,7 +142,7 @@
       var pointerAction = pointerActions[0];
       pointerAction.actions = [];
       pointerAction.actions.push(
-          {'name': 'pointerDown', 'x': xPosition, 'y': yPosition});
+          {name: 'pointerDown', x: xPosition, y: yPosition});
       for (var i = 1; i < targetSelectorList.length; i++) {
         scrollPageIfNeeded(targetSelectorList[i], document);
         target = document.querySelector(targetSelectorList[i]);
@@ -151,9 +150,9 @@
         xPosition = targetRect.left + boundaryOffset;
         yPosition = targetRect.top + boundaryOffset;
         pointerAction.actions.push(
-            {'name': 'pointerMove', 'x': xPosition, 'y': yPosition});
+            {name: 'pointerMove', x: xPosition, y: yPosition});
       }
-      pointerAction.actions.push({'name': 'pointerUp'});
+      pointerAction.actions.push({name: 'pointerUp'});
       chrome.gpuBenchmarking.pointerActionSequence(pointerActions, resolve);
     } else {
       reject();
@@ -207,10 +206,61 @@
       var xPosition = frameLeft + targetRect.left + boundaryOffset;
       var yPosition = frameTop + targetRect.top + boundaryOffset;
       chrome.gpuBenchmarking.pointerActionSequence( [
-        {"source": "touch",
-         "actions": [
-            { "name": "pointerDown", "x": xPosition, "y": yPosition },
-            { "name": "pointerUp" }
+        {source: 'touch',
+         actions: [
+            { name: 'pointerDown', x: xPosition, y: yPosition },
+            { name: 'pointerUp' }
+        ]}], resolve);
+    } else {
+      reject();
+    }
+  });
+}
+
+function twoPointerDragInTarget(pointerType, targetSelector, direction) {
+  return new Promise(function(resolve, reject) {
+    if (window.chrome && chrome.gpuBenchmarking) {
+      scrollPageIfNeeded(targetSelector, document);
+      var target = document.querySelector(targetSelector);
+      var targetRect = target.getBoundingClientRect();
+      var xPosition1 = targetRect.left + boundaryOffset + scrollOffset;
+      var yPosition1 = targetRect.top + boundaryOffset + scrollOffset;
+      var xPosition2 = xPosition1;
+      var yPosition2 = yPosition1;
+      var xPosition3 = xPosition1;
+      var yPosition3 = yPosition1;
+      if (direction == "down") {
+        yPosition1 -= scrollOffset;
+        yPosition3 += scrollOffset;
+      } else if (direction == "up") {
+        yPosition1 += scrollOffset;
+        yPosition3 -= scrollOffset;
+      } else if (direction == "right") {
+        xPosition1 -= scrollOffset;
+        xPosition3 += scrollOffset;
+      } else if (direction == "left") {
+        xPosition1 += scrollOffset;
+        xPosition3 -= scrollOffset;
+      } else {
+        throw("drag direction '" + direction + "' is not expected, direction should be 'down', 'up', 'left' or 'right'");
+      }
+
+      chrome.gpuBenchmarking.pointerActionSequence( [
+        {source: pointerType,
+         actions: [
+            { name: 'pointerDown', x: xPosition1, y: yPosition1 },
+            { name: 'pointerMove', x: xPosition2, y: yPosition2 },
+            { name: 'pointerMove', x: xPosition3, y: yPosition3 },
+            { name: 'pause', duration: 0.1 },
+            { name: 'pointerUp' }
+        ]},
+        {source: pointerType,
+         actions: [
+            { name: 'pointerDown', x: xPosition1 + boundaryOffset, y: yPosition1 },
+            { name: 'pointerMove', x: xPosition2 + boundaryOffset, y: yPosition2 },
+            { name: 'pointerMove', x: xPosition3 + boundaryOffset, y: yPosition3 },
+            { name: 'pause', duration: 0.1 },
+            { name: 'pointerUp' }
         ]}], resolve);
     } else {
       reject();
@@ -224,28 +274,36 @@
       scrollPageIfNeeded(targetSelector, document);
       var target = document.querySelector(targetSelector);
       var targetRect = target.getBoundingClientRect();
-      var xPosition = targetRect.left + boundaryOffset;
-      var yPosition = targetRect.top + boundaryOffset;
-      var newXPosition = xPosition;
-      var newYPosition = yPosition;
-      if (direction == "down")
-        newYPosition += scrollOffset;
-      else if (direction == "up")
-        newYPosition -= scrollOffset;
-      else if (direction == "right")
-        newXPosition += scrollOffset;
-      else if (direction == "left")
-        newXPosition -= scrollOffset;
-      else
+      var xPosition1 = targetRect.left + boundaryOffset + scrollOffset;
+      var yPosition1 = targetRect.top + boundaryOffset + scrollOffset;
+      var xPosition2 = xPosition1;
+      var yPosition2 = yPosition1;
+      var xPosition3 = xPosition1;
+      var yPosition3 = yPosition1;
+      if (direction == "down") {
+        yPosition1 -= scrollOffset;
+        yPosition3 += scrollOffset;
+      } else if (direction == "up") {
+        yPosition1 += scrollOffset;
+        yPosition3 -= scrollOffset;
+      } else if (direction == "right") {
+        xPosition1 -= scrollOffset;
+        xPosition3 += scrollOffset;
+      } else if (direction == "left") {
+        xPosition1 += scrollOffset;
+        xPosition3 -= scrollOffset;
+      } else {
         throw("drag direction '" + direction + "' is not expected, direction should be 'down', 'up', 'left' or 'right'");
+      }
 
       chrome.gpuBenchmarking.pointerActionSequence( [
-        {"source": pointerType,
-         "actions": [
-            { "name": "pointerDown", "x": xPosition, "y": yPosition },
-            { "name": "pointerMove", "x": newXPosition, "y": newYPosition },
-            { "name": "pause", "duration": 0.1 },
-            { "name": "pointerUp" }
+        {source: pointerType,
+         actions: [
+            { name: 'pointerDown', x: xPosition1, y: yPosition1 },
+            { name: 'pointerMove', x: xPosition2, y: yPosition2 },
+            { name: 'pointerMove', x: xPosition3, y: yPosition3 },
+            { name: 'pause', duration: 0.1 },
+            { name: 'pointerUp' }
         ]}], resolve);
     } else {
       reject();
@@ -280,23 +338,23 @@
       pointerAction1.actions = [];
       pointerAction2.actions = [];
       pointerAction1.actions.push(
-          {'name': 'pointerDown', 'x': xPosition, 'y': yPosition1});
+          {name: 'pointerDown', x: xPosition, y: yPosition1});
       pointerAction2.actions.push(
-          {'name': 'pointerDown', 'x': xPosition, 'y': yPosition2});
+          {name: 'pointerDown', x: xPosition, y: yPosition2});
       for (var offset = 10; offset < 80; offset += 10) {
         pointerAction1.actions.push({
-          'name': 'pointerMove',
-          'x': xPosition,
-          'y': (yPosition1 - offset)
+          name: 'pointerMove',
+          x: xPosition,
+          y: (yPosition1 - offset)
         });
         pointerAction2.actions.push({
-          'name': 'pointerMove',
-          'x': xPosition,
-          'y': (yPosition2 + offset)
+          name: 'pointerMove',
+          x: xPosition,
+          y: (yPosition2 + offset)
         });
       }
-      pointerAction1.actions.push({'name': 'pointerUp'});
-      pointerAction2.actions.push({'name': 'pointerUp'});
+      pointerAction1.actions.push({name: 'pointerUp'});
+      pointerAction2.actions.push({name: 'pointerUp'});
       chrome.gpuBenchmarking.pointerActionSequence(pointerActions, resolve);
     } else {
       reject();
@@ -309,9 +367,9 @@
   return new Promise(function(resolve, reject) {
     if (window.chrome && chrome.gpuBenchmarking) {
       chrome.gpuBenchmarking.pointerActionSequence( [
-        {"source": "pen",
-         "actions": [
-            { "name": "pointerMove", "x": 0, "y": 0 }
+        {source: 'pen',
+         actions: [
+            { name: 'pointerMove', x: 0, y: 0 }
         ]}], resolve);
     } else {
       reject();
@@ -336,9 +394,9 @@
       var xPosition = frameLeft + targetRect.left + boundaryOffset;
       var yPosition = frameTop + targetRect.top + boundaryOffset;
       chrome.gpuBenchmarking.pointerActionSequence( [
-        {"source": "pen",
-         "actions": [
-            { "name": "pointerMove", "x": xPosition, "y": yPosition }
+        {source: 'pen',
+         actions: [
+            { name: 'pointerMove', x: xPosition, y: yPosition }
         ]}], resolve);
     } else {
       reject();
@@ -364,11 +422,11 @@
       var xPosition = frameLeft + targetRect.left + boundaryOffset;
       var yPosition = frameTop + targetRect.top + boundaryOffset;
       chrome.gpuBenchmarking.pointerActionSequence( [
-        {"source": "pen",
-         "actions": [
-            { "name": "pointerMove", "x": xPosition, "y": yPosition },
-            { "name": "pointerDown", "x": xPosition, "y": yPosition },
-            { "name": "pointerUp" }
+        {source: 'pen',
+         actions: [
+            { name: 'pointerMove', x: xPosition, y: yPosition },
+            { name: 'pointerDown', x: xPosition, y: yPosition },
+            { name: 'pointerUp' }
         ]}], resolve);
     } else {
       reject();
diff --git a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_element_haspointercapture-manual-automation.js b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_element_haspointercapture-manual-automation.js
index 14b5ac1..71a56b38 100644
--- a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_element_haspointercapture-manual-automation.js
+++ b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_element_haspointercapture-manual-automation.js
@@ -1,5 +1,7 @@
 importAutomationScript('/pointerevents/pointerevent_common_input.js');
 
 function inject_input() {
-  return mouseDragInTargets(['#target0', '#target1']);
+  return mouseDragInTargets(['#target0', '#target1']).then(function() {
+    return mouseClickInTarget('#target1');
+  });
 }
diff --git a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_click-manual-automation.js b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_click-manual-automation.js
new file mode 100644
index 0000000..b3480c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_click-manual-automation.js
@@ -0,0 +1,15 @@
+importAutomationScript('/pointerevents/pointerevent_common_input.js');
+
+function inject_input() {
+  return mouseClickInTarget('#target').then(function() {
+    return mouseClickInTarget('#done');
+  }).then(function() {
+    return touchTapInTarget('#target');
+  }).then(function() {
+    return touchTapInTarget('#done');
+  }).then(function() {
+    return penClickInTarget('#target')
+  }).then(function() {
+    return penClickInTarget('#done')
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual-automation.js b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual-automation.js
new file mode 100644
index 0000000..c0b9fbf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_sequence_at_implicit_release_on_drag-manual-automation.js
@@ -0,0 +1,7 @@
+importAutomationScript('/pointerevents/pointerevent_common_input.js');
+
+function inject_input() {
+  return pointerDragInTarget('touch', '#target', 'right').then(function() {
+    return touchTapInTarget('#done');
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js
index 3bf7a69..1c006c4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js
+++ b/third_party/WebKit/LayoutTests/external/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js
@@ -1,8 +1,7 @@
 importAutomationScript('/pointerevents/pointerevent_common_input.js');
 
 function inject_input() {
-  return touchScrollInTarget('#target0 > div', 'down').then(function() {
-    return touchScrollInTarget('#target0 > div', 'right');
+  return touchScrollInTarget('#scrollTarget', 'down').then(function() {
+    return touchScrollInTarget('#scrollTarget', 'right');
   });
 }
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blend-solid-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blend-solid-expected.txt
deleted file mode 100644
index 8a2726db..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blend-solid-expected.txt
+++ /dev/null
@@ -1,1129 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode "source-over"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 171
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 84
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 171
-PASS pixelDataAtPoint(1)[1] is within 5 of 171
-PASS pixelDataAtPoint(1)[2] is within 5 of 84
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 85
-PASS pixelDataAtPoint(2)[2] is within 5 of 84
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "multiply"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 85
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 84
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 85
-PASS pixelDataAtPoint(1)[1] is within 5 of 85
-PASS pixelDataAtPoint(1)[2] is within 5 of 84
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 43
-PASS pixelDataAtPoint(2)[2] is within 5 of 84
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "screen"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 171
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 171
-PASS pixelDataAtPoint(1)[1] is within 5 of 171
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 85
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "overlay"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 85
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 85
-PASS pixelDataAtPoint(1)[1] is within 5 of 85
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 43
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "darken"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 85
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 84
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 85
-PASS pixelDataAtPoint(1)[1] is within 5 of 85
-PASS pixelDataAtPoint(1)[2] is within 5 of 84
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 43
-PASS pixelDataAtPoint(2)[2] is within 5 of 84
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "lighten"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 171
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 171
-PASS pixelDataAtPoint(1)[1] is within 5 of 171
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 85
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "color-dodge"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 85
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 85
-PASS pixelDataAtPoint(1)[1] is within 5 of 85
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 43
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "color-burn"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 85
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 85
-PASS pixelDataAtPoint(1)[1] is within 5 of 85
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 42
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "hard-light"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 1
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 65
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 171
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 84
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 171
-PASS pixelDataAtPoint(1)[1] is within 5 of 171
-PASS pixelDataAtPoint(1)[2] is within 5 of 84
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 43
-PASS pixelDataAtPoint(2)[2] is within 5 of 84
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "soft-light"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 0
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 85
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 85
-PASS pixelDataAtPoint(1)[1] is within 5 of 85
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 43
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "difference"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 0
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 127
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 128
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 171
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 171
-PASS pixelDataAtPoint(1)[1] is within 5 of 171
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 85
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 171
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "exclusion"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 0
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 64
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 127
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 255
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 255
-PASS pixelDataAtPoint(1)[1] is within 5 of 255
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 128
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 128
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 171
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 170
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 171
-PASS pixelDataAtPoint(1)[1] is within 5 of 171
-PASS pixelDataAtPoint(1)[2] is within 5 of 170
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 85
-PASS pixelDataAtPoint(2)[2] is within 5 of 170
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 171
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "hue"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 93
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 31
-PASS pixelDataAtPoint(1)[1] is within 5 of 31
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 46
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 49
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 16
-PASS pixelDataAtPoint(1)[1] is within 5 of 16
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 25
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 175
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 144
-PASS pixelDataAtPoint(1)[1] is within 5 of 144
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 88
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 116
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 84
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 96
-PASS pixelDataAtPoint(1)[1] is within 5 of 96
-PASS pixelDataAtPoint(1)[2] is within 5 of 84
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 58
-PASS pixelDataAtPoint(2)[2] is within 5 of 84
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "saturation"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 14
-PASS pixelDataAtPoint(2)[1] is within 5 of 14
-PASS pixelDataAtPoint(2)[2] is within 5 of 142
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 0
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 0
-PASS pixelDataAtPoint(1)[1] is within 5 of 0
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 7
-PASS pixelDataAtPoint(2)[1] is within 5 of 7
-PASS pixelDataAtPoint(2)[2] is within 5 of 198
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 128
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 128
-PASS pixelDataAtPoint(1)[1] is within 5 of 128
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 7
-PASS pixelDataAtPoint(2)[1] is within 5 of 71
-PASS pixelDataAtPoint(2)[2] is within 5 of 70
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 85
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 167
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 85
-PASS pixelDataAtPoint(1)[1] is within 5 of 85
-PASS pixelDataAtPoint(1)[2] is within 5 of 167
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 48
-PASS pixelDataAtPoint(2)[2] is within 5 of 130
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "color"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 93
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 31
-PASS pixelDataAtPoint(1)[1] is within 5 of 31
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 47
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 49
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 16
-PASS pixelDataAtPoint(1)[1] is within 5 of 16
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 24
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 175
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 0
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 144
-PASS pixelDataAtPoint(1)[1] is within 5 of 144
-PASS pixelDataAtPoint(1)[2] is within 5 of 0
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 88
-PASS pixelDataAtPoint(2)[2] is within 5 of 0
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 116
-PASS pixelDataAtPoint(0)[1] is within 5 of 0
-PASS pixelDataAtPoint(0)[2] is within 5 of 84
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 96
-PASS pixelDataAtPoint(1)[1] is within 5 of 96
-PASS pixelDataAtPoint(1)[2] is within 5 of 84
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 0
-PASS pixelDataAtPoint(2)[1] is within 5 of 58
-PASS pixelDataAtPoint(2)[2] is within 5 of 84
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-Testing blend mode "luminosity"
-solid on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 55
-PASS pixelDataAtPoint(0)[1] is within 5 of 55
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 224
-PASS pixelDataAtPoint(1)[1] is within 5 of 224
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 54
-PASS pixelDataAtPoint(2)[1] is within 5 of 54
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-solid on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 28
-PASS pixelDataAtPoint(0)[1] is within 5 of 28
-PASS pixelDataAtPoint(0)[2] is within 5 of 255
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 112
-PASS pixelDataAtPoint(1)[1] is within 5 of 112
-PASS pixelDataAtPoint(1)[2] is within 5 of 255
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 27
-PASS pixelDataAtPoint(2)[1] is within 5 of 27
-PASS pixelDataAtPoint(2)[2] is within 5 of 255
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on solid
-PASS pixelDataAtPoint(0)[0] is within 5 of 155
-PASS pixelDataAtPoint(0)[1] is within 5 of 27
-PASS pixelDataAtPoint(0)[2] is within 5 of 127
-PASS pixelDataAtPoint(0)[3] is within 5 of 255
-PASS pixelDataAtPoint(1)[0] is within 5 of 239
-PASS pixelDataAtPoint(1)[1] is within 5 of 239
-PASS pixelDataAtPoint(1)[2] is within 5 of 127
-PASS pixelDataAtPoint(1)[3] is within 5 of 255
-PASS pixelDataAtPoint(2)[0] is within 5 of 26
-PASS pixelDataAtPoint(2)[1] is within 5 of 90
-PASS pixelDataAtPoint(2)[2] is within 5 of 127
-PASS pixelDataAtPoint(2)[3] is within 5 of 255
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 255
-alpha on alpha
-PASS pixelDataAtPoint(0)[0] is within 5 of 104
-PASS pixelDataAtPoint(0)[1] is within 5 of 19
-PASS pixelDataAtPoint(0)[2] is within 5 of 167
-PASS pixelDataAtPoint(0)[3] is within 5 of 191
-PASS pixelDataAtPoint(1)[0] is within 5 of 158
-PASS pixelDataAtPoint(1)[1] is within 5 of 158
-PASS pixelDataAtPoint(1)[2] is within 5 of 167
-PASS pixelDataAtPoint(1)[3] is within 5 of 191
-PASS pixelDataAtPoint(2)[0] is within 5 of 16
-PASS pixelDataAtPoint(2)[1] is within 5 of 58
-PASS pixelDataAtPoint(2)[2] is within 5 of 167
-PASS pixelDataAtPoint(2)[3] is within 5 of 191
-PASS pixelDataAtPoint(3)[0] is within 5 of 0
-PASS pixelDataAtPoint(3)[1] is within 5 of 0
-PASS pixelDataAtPoint(3)[2] is within 5 of 255
-PASS pixelDataAtPoint(3)[3] is within 5 of 191
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blend-solid.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blend-solid.html
index dcbdd40..7428e853 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blend-solid.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blend-solid.html
@@ -1,8 +1,185 @@
-<!doctype html>
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
-<script src="script-tests/canvas-blend-solid.js"></script>
+<script>
+var canvas = document.createElement('canvas');
+canvas.width = 200;
+canvas.height = 200;
+ctx = canvas.getContext('2d');
+
+// Create the image for blending test with images.
+var img = document.createElement('canvas');
+img.width = 200;
+img.height = 200;
+var imgCtx = img.getContext('2d');
+imgCtx.fillStyle = "red";
+imgCtx.fillRect(0,0,100,100);
+imgCtx.fillStyle = "yellow";
+imgCtx.fillRect(100,0,100,100);
+imgCtx.fillStyle = "green";
+imgCtx.fillRect(100,100,100,100);
+imgCtx.fillStyle = "blue";
+imgCtx.fillRect(0,100,100,100);
+
+// Create expected results.
+var blendModes =
+// [blendMode, expectations solid on solid, expectations solid on alpha, expectations alpha on solid, expectations alpha on alpha]
+[
+  ['source-over',
+     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
+     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
+     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
+     [[171, 0, 84, 191],[171, 171, 84, 191],[0, 85, 84, 191],[0, 0, 255, 191]]
+  ],
+  ['multiply',
+     [[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 255, 255]],
+     [[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
+     [[128, 0, 0, 255],[128, 128, 0, 255],[0, 64, 0, 255],[0, 0, 255, 255]],
+     [[85, 0, 84, 191],[85, 85, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
+  ],
+  ['screen',
+     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 255, 255]],
+     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 255, 255]],
+     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 255, 255]],
+     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 255, 191]]
+  ],
+  ['overlay',
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
+     [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
+  ],
+  ['darken',
+     [[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 255, 255]],
+     [[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
+     [[128, 0, 0, 255],[128, 128, 0, 255],[0, 64, 0, 255],[0, 0, 255, 255]],
+     [[85, 0, 84, 191],[85, 85, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
+  ],
+  ['lighten',
+     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 255, 255]],
+     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 255, 255]],
+     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 255, 255]],
+     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 255, 191]]
+  ],
+  ['color-dodge',
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
+     [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
+  ],
+  ['color-burn',
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+         [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
+         [[85, 0, 170, 191],[85, 85, 170, 191],[0, 42, 170, 191],[0, 0, 255, 191]]
+
+  ],
+  ['hard-light',
+     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 1, 0, 255],[0, 0, 255, 255]],
+     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
+     [[255, 0, 0, 255],[255, 255, 0, 255],[0, 65, 0, 255],[0, 0, 255, 255]],
+     [[171, 0, 84, 191],[171, 171, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
+  ],
+  ['soft-light',
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+     [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
+     [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
+     [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
+  ],
+  ['difference',
+     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 0, 255]],
+     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 127, 255]],
+     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 128, 255]],
+     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 171, 191]]
+  ],
+  ['exclusion',
+     [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 0, 255]],
+     [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 127, 255]],
+     [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 128, 255]],
+     [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 171, 191]]
+  ],
+  ['hue',
+     [[93, 0, 0, 255],[31, 31, 0, 255],[0, 46, 0, 255],[0, 0, 255, 255]],
+     [[49, 0, 127, 255],[16, 16, 127, 255],[0, 25, 127, 255],[0, 0, 255, 255]],
+     [[175, 0, 0, 255],[144, 144, 0, 255],[0, 88, 0, 255],[0, 0, 255, 255]],
+     [[116, 0, 84, 191],[96, 96, 84, 191],[0, 58, 84, 191],[0, 0, 255, 191]]
+  ],
+  ['saturation',
+     [[0, 0, 255, 255],[0, 0, 255, 255],[14, 14, 142, 255],[0, 0, 255, 255]],
+     [[0, 0, 255, 255],[0, 0, 255, 255],[7, 7, 198, 255],[0, 0, 255, 255]],
+     [[128, 0, 127, 255],[128, 128, 127, 255],[7, 71, 70, 255],[0, 0, 255, 255]],
+     [[85, 0, 167, 191],[85, 85, 167, 191],[0, 48, 130, 191],[0, 0, 255, 191]]
+  ],
+  ['color',
+     [[93, 0, 0, 255],[31, 31, 0, 255],[0, 47, 0, 255],[0, 0, 255, 255]],
+     [[49, 0, 127, 255],[16, 16, 127, 255],[0, 24, 127, 255],[0, 0, 255, 255]],
+     [[175, 0, 0, 255],[144, 144, 0, 255],[0, 88, 0, 255],[0, 0, 255, 255]],
+     [[116, 0, 84, 191],[96, 96, 84, 191],[0, 58, 84, 191],[0, 0, 255, 191]]
+  ],
+  ['luminosity',
+     [[55, 55, 255, 255],[224, 224, 255, 255],[54, 54, 255, 255],[0, 0, 255, 255]],
+     [[28, 28, 255, 255],[112, 112, 255, 255],[27, 27, 255, 255],[0, 0, 255, 255]],
+     [[155, 27, 127, 255],[239, 239, 127, 255],[26, 90, 127, 255],[0, 0, 255, 255]],
+     [[104, 19, 167, 191],[158, 158, 167, 191],[16, 58, 167, 191],[0, 0, 255, 191]]
+  ]];
+
+// [Scenario, alpha on background, alpha on foreground]
+var testScenario = [
+  ['solid on solid', 1, 1],
+  ['solid on alpha', 1, 0.5],
+  ['alpha on solid', 0.5, 1],
+  ['alpha on alpha', 0.5, 0.5]
+];
+
+testPoints = [{x: 50, y: 50}, {x: 150, y: 50}, {x: 150, y: 150}, {x: 50, y: 150}];
+
+function pixelDataAtPoint(i, blend)
+{
+  return ctx.getImageData(testPoints[i].x, testPoints[i].y , 1, 1).data;
+}
+
+function checkBlendModeResult(blendMode, testScenario, expectedColors, sigma) {
+  for (var i = 0; i < testPoints.length; i++) {
+    var resultColor = pixelDataAtPoint(i);
+    assert_approx_equals(resultColor[0], expectedColors[i][0], sigma);
+    assert_approx_equals(resultColor[1], expectedColors[i][1], sigma);
+    assert_approx_equals(resultColor[2], expectedColors[i][2], sigma);
+    assert_approx_equals(resultColor[3], expectedColors[i][3], sigma);
+    }
+}
+
+// Run test and allow variation of results.
+test(function(t) {
+  var sigma = 5;
+  // Check each blend mode individually.
+  for (var i = 0; i < blendModes.length; i++) {
+    for (var j = 0; j < testScenario.length; j++) {
+      ctx.globalCompositeOperation = 'clear';
+      ctx.fillRect(0,0,200,200);
+      ctx.globalCompositeOperation = 'source-over';
+      ctx.save();
+      
+      // Draw backdrop.
+      ctx.fillStyle = 'rgba(0, 0, 255, ' + testScenario[j][1] + ')';
+      ctx.fillRect(0,0,200,200);
+      
+      // Apply blend mode.
+      ctx.globalCompositeOperation = blendModes[i][0];
+      ctx.globalAlpha = testScenario[j][2];
+      ctx.fillStyle = "red";
+      ctx.fillRect(0,0,100,100);
+      ctx.fillStyle = "yellow";
+      ctx.fillRect(100,0,100,100);
+      ctx.fillStyle = "green";
+      ctx.fillRect(100,100,100,100);
+      ctx.fillStyle = "blue";
+      ctx.fillRect(0,100,100,100);
+      ctx.restore();
+      
+      checkBlendModeResult(blendModes[i][0], testScenario[j][0], blendModes[i][j+1], sigma);
+      ctx.restore();                                  
+      }
+  }    
+}, "Series of tests to ensure correct results on applying different blend modes.");
+</script>
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-helpers.js b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-helpers.js
index af2885c0..c0825df6 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-helpers.js
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-helpers.js
@@ -301,8 +301,12 @@
     return [Math.round(255 * expectedColor[0]), Math.round(255 * expectedColor[1]), Math.round(255 * expectedColor[2]), 255];
 }
 
-function checkBlendModeResult(i, context, sigma) {
-    var actualColor = context.getImageData(0, 0, 1, 1).data;
+function checkBlendModeResult(i, context, sigma, x, y) {
+    if (x === undefined)
+        x = 0;
+    if (y === undefined)
+        y = 0;
+    var actualColor = context.getImageData(x, y, 1, 1).data;
     var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
     assert_approx_equals(actualColor[0], expectedColor[0], sigma);
     assert_approx_equals(actualColor[1], expectedColor[1], sigma);
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-color-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-color-expected.txt
deleted file mode 100644
index 0856257..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-color-expected.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a color.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-color.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-color.html
index d85f313..e84bd478 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-color.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-color.html
@@ -1,63 +1,34 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <script type="text/javascript">
-        if (window.testRunner)
-            testRunner.waitUntilDone();
-        window.jsTestIsAsync = true
-    </script>
-</head>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
-
-        description("Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a color.");
-
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript" src="canvas-blending-helpers.js"></script>
+<script>
+async_test(function(t) {
+    function drawElement(context, i) {
+        if (i >= blendModes.length) {
+            t.done();
+            return;
         }
 
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-        }
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        drawBackdropColorInContext(context);
+        context.globalCompositeOperation = blendModes[i];
 
-        function drawElement(context, i) {
-            if (i >= blendModes.length) {
-                finishJSTest();
-                return;
-            }
-            debug("Testing blend mode " + blendModes[i]);
-
-            context.clearRect(0, 0, 10, 10);
-            context.save();
-            drawBackdropColorInContext(context);
-            context.globalCompositeOperation = blendModes[i];
-
-            drawSourceColorImageInContext(context, function() {
+        drawSourceColorImageInContext(context, function() {
+            t.step(function () {
                 checkBlendModeResult(i, context, 5);
-                context.restore();
-                debug('');
-                drawElement(context, ++i);
             });
-        }
+            context.restore();
+            drawElement(context, ++i);
+        });
+    }
 
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-            drawElement(context, 0);
-        }
+    var canvas = document.createElement('canvas');
+    var sigma = 5;
+    canvas.width = 10;
+    canvas.height = 10;
+    context = canvas.getContext('2d');
+    drawElement(context, 0);
 
-        runTest();
-    </script>
-</body>
-</html>
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a color.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-gradient-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-gradient-expected.txt
deleted file mode 100644
index 6c50b33..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-gradient-expected.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a gradient.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-gradient.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-gradient.html
index bad1f38..4116dba4 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-gradient.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-gradient.html
@@ -1,63 +1,34 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <script type="text/javascript">
-        if (window.testRunner)
-            testRunner.waitUntilDone();
-        window.jsTestIsAsync = true
-    </script>
-</head>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
-
-        description("Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a gradient.");
-
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript" src="canvas-blending-helpers.js"></script>
+<script>
+async_test(function(t) {
+    function drawElement(context, i) {
+        if (i >= blendModes.length) {
+            t.done();
+            return;
         }
 
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-        }
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        drawBackdropColorGradientInContext(context);
+        context.globalCompositeOperation = blendModes[i];
 
-        function drawElement(context, i) {
-            if (i >= blendModes.length) {
-                finishJSTest();
-                return;
-            }
-            debug("Testing blend mode " + blendModes[i]);
-
-            context.clearRect(0, 0, 10, 10);
-            context.save();
-            drawBackdropColorGradientInContext(context);
-            context.globalCompositeOperation = blendModes[i];
-
-            drawSourceColorImageInContext(context, function() {
+        drawSourceColorImageInContext(context, function() {
+            t.step(function () {
                 checkBlendModeResult(i, context, 5);
-                context.restore();
-                debug('');
-                drawElement(context, ++i);
             });
-        }
+            context.restore();
+            drawElement(context, ++i);
+        });
+    }
 
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-            drawElement(context, 0);
-        }
+    var canvas = document.createElement('canvas');
+    var sigma = 5;
+    canvas.width = 10;
+    canvas.height = 10;
+    context = canvas.getContext('2d');
+    drawElement(context, 0);
 
-        runTest();
-    </script>
-</body>
-</html>
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a gradient.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-pattern-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-pattern-expected.txt
deleted file mode 100644
index 8d6e64e..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-pattern-expected.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a pattern.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-pattern.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-pattern.html
index 776a861..185523f 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-pattern.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-image-over-pattern.html
@@ -1,64 +1,33 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <script type="text/javascript">
-        if (window.testRunner)
-            testRunner.waitUntilDone();
-        window.jsTestIsAsync = true
-    </script>
-</head>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
-
-        description("Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a pattern.");
-
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="canvas-blending-helpers.js"></script>
+<script>
+async_test(function(t) {
+    function drawElement(context, i) {
+        if (i >= blendModes.length) {
+            t.done();
+            return;
         }
 
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-        }
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        drawBackdropColorPatternInContext(context, function() {
+            context.globalCompositeOperation = blendModes[i];
 
-        function drawElement(context, i) {
-            if (i >= blendModes.length) {
-                finishJSTest();
-                return;
-            }
-            debug("Testing blend mode " + blendModes[i]);
-
-            context.clearRect(0, 0, 10, 10);
-            context.save();
-            drawBackdropColorPatternInContext(context, function() {
-                context.globalCompositeOperation = blendModes[i];
-
-                drawSourceColorImageInContext(context, function() {
+            drawSourceColorImageInContext(context, function() {
+                t.step(function () {
                     checkBlendModeResult(i, context, 5);
-                    context.restore();
-                    debug('');
-                    drawElement(context, ++i);
                 });
+                context.restore();
+                drawElement(context, ++i);
             });
-        }
+        });
+    }
 
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-            drawElement(context, 0);
-        }
+    var canvas = document.createElement('canvas');
+    canvas.width = canvas.height = 10;
+    context = canvas.getContext('2d');
+    drawElement(context, 0);
 
-        runTest();
-    </script>
-</body>
-</html>
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing an image on top of a pattern.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-color-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-color-expected.txt
deleted file mode 100644
index 8466235cb..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-color-expected.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of a color.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-color.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-color.html
index 50449f2..d244d6b 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-color.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-color.html
@@ -1,63 +1,33 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <script type="text/javascript">
-        if (window.testRunner)
-            testRunner.waitUntilDone();
-        window.jsTestIsAsync = true
-    </script>
-</head>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
-
-        description("Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of a color.");
-
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript" src="canvas-blending-helpers.js"></script>
+<script>
+async_test(function(t) {
+    function drawElement(context, i) {
+        if (i >= blendModes.length) {
+            t.done();
+            return;
         }
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        drawBackdropColorInContext(context);
+        context.globalCompositeOperation = blendModes[i];
 
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-        }
-
-        function drawElement(context, i) {
-            if (i >= blendModes.length) {
-                finishJSTest();
-                return;
-            }
-            debug("Testing blend mode " + blendModes[i]);
-
-            context.clearRect(0, 0, 10, 10);
-            context.save();
-            drawBackdropColorInContext(context);
-            context.globalCompositeOperation = blendModes[i];
-
-            drawSourceColorPatternInContext(context, function() {
+        drawSourceColorPatternInContext(context, function() {
+            t.step(function () {
                 checkBlendModeResult(i, context, 5);
-                context.restore();
-                debug('');
-                drawElement(context, ++i);
             });
-        }
+            context.restore();
+            drawElement(context, ++i);
+        });
+    }
 
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-            drawElement(context, 0);
-        }
+    var canvas = document.createElement('canvas');
+    var sigma = 5;
+    canvas.width = 10;
+    canvas.height = 10;
+    context = canvas.getContext('2d');
+    drawElement(context, 0);
 
-        runTest();
-    </script>
-</body>
-</html>
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of a color.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-gradient-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-gradient-expected.txt
deleted file mode 100644
index bc1bbf1..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-gradient-expected.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of an gradient.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-gradient.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-gradient.html
index 9614f171..8972f6e 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-gradient.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-gradient.html
@@ -1,63 +1,33 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <script type="text/javascript">
-        if (window.testRunner)
-            testRunner.waitUntilDone();
-        window.jsTestIsAsync = true
-    </script>
-</head>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
-
-        description("Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of an gradient.");
-
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript" src="canvas-blending-helpers.js"></script>
+<script>
+async_test(function(t) {
+    function drawElement(context, i) {
+        if (i >= blendModes.length) {
+            t.done();
+            return;
         }
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        drawBackdropColorGradientInContext(context);
+        context.globalCompositeOperation = blendModes[i];
 
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-        }
-
-        function drawElement(context, i) {
-            if (i >= blendModes.length) {
-                finishJSTest();
-                return;
-            }
-            debug("Testing blend mode " + blendModes[i]);
-
-            context.clearRect(0, 0, 10, 10);
-            context.save();
-            drawBackdropColorGradientInContext(context);
-            context.globalCompositeOperation = blendModes[i];
-
-            drawSourceColorPatternInContext(context, function() {
+        drawSourceColorPatternInContext(context, function() {
+            t.step(function () {
                 checkBlendModeResult(i, context, 5);
-                context.restore();
-                debug('');
-                drawElement(context, ++i);
             });
-        }
+            context.restore();
+            drawElement(context, ++i);
+        });
+    }
 
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-            drawElement(context, 0);
-        }
+    var canvas = document.createElement('canvas');
+    var sigma = 5;
+    canvas.width = 10;
+    canvas.height = 10;
+    context = canvas.getContext('2d');
+    drawElement(context, 0);
 
-        runTest();
-    </script>
-</body>
-</html>
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of an gradient.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-image-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-image-expected.txt
deleted file mode 100644
index c595d831..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-image-expected.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of an image.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-image.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-image.html
index 9271977..10563cf 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-image.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-image.html
@@ -1,64 +1,34 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <script type="text/javascript">
-        if (window.testRunner)
-            testRunner.waitUntilDone();
-        window.jsTestIsAsync = true
-    </script>
-</head>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
-
-        description("Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of an image.");
-
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript" src="canvas-blending-helpers.js"></script>
+<script>
+async_test(function(t) {
+    function drawElement(context, i) {
+        if (i >= blendModes.length) {
+            t.done();
+            return;
         }
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        drawBackdropColorImageInContext(context, function() {
+            context.globalCompositeOperation = blendModes[i];
 
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-        }
-
-        function drawElement(context, i) {
-            if (i >= blendModes.length) {
-                finishJSTest();
-                return;
-            }
-            debug("Testing blend mode " + blendModes[i]);
-
-            context.clearRect(0, 0, 10, 10);
-            context.save();
-            drawBackdropColorImageInContext(context, function() {
-                context.globalCompositeOperation = blendModes[i];
-
-                drawSourceColorPatternInContext(context, function() {
+            drawSourceColorPatternInContext(context, function() {
+                t.step(function () {
                     checkBlendModeResult(i, context, 5);
-                    context.restore();
-                    debug('');
-                    drawElement(context, ++i);
                 });
+                context.restore();
+                drawElement(context, ++i);
             });
-        }
+        });
+    }
 
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-            drawElement(context, 0);
-        }
+    var canvas = document.createElement('canvas');
+    var sigma = 5;
+    canvas.width = 10;
+    canvas.height = 10;
+    context = canvas.getContext('2d');
+    drawElement(context, 0);
 
-        runTest();
-    </script>
-</body>
-</html>
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of an image.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-pattern-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-pattern-expected.txt
deleted file mode 100644
index 4db30d50..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-pattern-expected.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of another.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-pattern.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-pattern.html
index 9c22020..b71b5e7a 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-pattern.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-pattern-over-pattern.html
@@ -1,64 +1,33 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <script type="text/javascript">
-        if (window.testRunner)
-            testRunner.waitUntilDone();
-        window.jsTestIsAsync = true
-    </script>
-</head>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
-
-        description("Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of another.");
-
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="canvas-blending-helpers.js"></script>
+<script>
+async_test(function(t) {
+    function drawElement(context, i) {
+        if (i >= blendModes.length) {
+            t.done();
+            return;
         }
 
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-        }
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        drawBackdropColorPatternInContext(context, function() {
+            context.globalCompositeOperation = blendModes[i];
 
-        function drawElement(context, i) {
-            if (i >= blendModes.length) {
-                finishJSTest();
-                return;
-            }
-            debug("Testing blend mode " + blendModes[i]);
-
-            context.clearRect(0, 0, 10, 10);
-            context.save();
-            drawBackdropColorPatternInContext(context, function() {
-                context.globalCompositeOperation = blendModes[i];
-
-                drawSourceColorPatternInContext(context, function() {
+            drawSourceColorPatternInContext(context, function() {
+                t.step(function () {
                     checkBlendModeResult(i, context, 5);
-                    context.restore();
-                    debug('');
-                    drawElement(context, ++i);
                 });
+                context.restore();
+                drawElement(context, i + 1);
             });
-        }
+        });
+    }
 
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-            drawElement(context, 0);
-        }
+    var canvas = document.createElement('canvas');
+    canvas.width = canvas.height = 10;
+    context = canvas.getContext('2d');
+    drawElement(context, 0);
 
-        runTest();
-    </script>
-</body>
-</html>
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing a pattern on top of another.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-shadow-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-shadow-expected.txt
deleted file mode 100644
index 5cc26b2..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-shadow-expected.txt
+++ /dev/null
@@ -1,169 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing a rectangle with shadow.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 255
-PASS actualColor(11, 11)[1] is within 5 of 129
-PASS actualColor(11, 11)[2] is within 5 of 129
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode multiply
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 192
-PASS actualColor(11, 11)[1] is within 5 of 97.12941176470588
-PASS actualColor(11, 11)[2] is within 5 of 97.12941176470588
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode screen
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 255
-PASS actualColor(11, 11)[1] is within 5 of 223.87058823529412
-PASS actualColor(11, 11)[2] is within 5 of 223.87058823529412
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode overlay
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 255
-PASS actualColor(11, 11)[1] is within 5 of 192.74117647058821
-PASS actualColor(11, 11)[2] is within 5 of 192.74117647058821
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode darken
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 129
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 192
-PASS actualColor(11, 11)[1] is within 5 of 129
-PASS actualColor(11, 11)[2] is within 5 of 129
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode lighten
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 255
-PASS actualColor(11, 11)[1] is within 5 of 192
-PASS actualColor(11, 11)[2] is within 5 of 192
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode color-dodge
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 255
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 255
-PASS actualColor(11, 11)[1] is within 5 of 255
-PASS actualColor(11, 11)[2] is within 5 of 255
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode color-burn
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 192
-PASS actualColor(11, 11)[1] is within 5 of 130.46511627906978
-PASS actualColor(11, 11)[2] is within 5 of 130.46511627906978
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode hard-light
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 255
-PASS actualColor(11, 11)[1] is within 5 of 192.74117647058821
-PASS actualColor(11, 11)[2] is within 5 of 192.74117647058821
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode soft-light
-PASS actualColor(0, 0)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 221.2690669750293
-PASS actualColor(11, 11)[1] is within 5 of 192.3443419644121
-PASS actualColor(11, 11)[2] is within 5 of 192.3443419644121
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode difference
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 0
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 63
-PASS actualColor(11, 11)[1] is within 5 of 63
-PASS actualColor(11, 11)[2] is within 5 of 63
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode exclusion
-PASS actualColor(0, 0)[0] is within 5 of 126
-PASS actualColor(0, 0)[1] is within 5 of 126
-PASS actualColor(0, 0)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 63
-PASS actualColor(11, 11)[1] is within 5 of 126.74117647058823
-PASS actualColor(11, 11)[2] is within 5 of 126.74117647058823
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode hue
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 192
-PASS actualColor(11, 11)[1] is within 5 of 192
-PASS actualColor(11, 11)[2] is within 5 of 192
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode saturation
-PASS actualColor(0, 0)[0] is within 5 of 129
-PASS actualColor(0, 0)[1] is within 5 of 255
-PASS actualColor(0, 0)[2] is within 5 of 129
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 192
-PASS actualColor(11, 11)[1] is within 5 of 192
-PASS actualColor(11, 11)[2] is within 5 of 192
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode color
-PASS actualColor(0, 0)[0] is within 5 of 255
-PASS actualColor(0, 0)[1] is within 5 of 181
-PASS actualColor(0, 0)[2] is within 5 of 181
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 255
-PASS actualColor(11, 11)[1] is within 5 of 165
-PASS actualColor(11, 11)[2] is within 5 of 165
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-Testing blend mode luminosity
-PASS actualColor(0, 0)[0] is within 5 of 92
-PASS actualColor(0, 0)[1] is within 5 of 218
-PASS actualColor(0, 0)[2] is within 5 of 92
-PASS actualColor(0, 0)[3] is within 5 of 255
-PASS actualColor(11, 11)[0] is within 5 of 167
-PASS actualColor(11, 11)[1] is within 5 of 167
-PASS actualColor(11, 11)[2] is within 5 of 167
-PASS actualColor(11, 11)[3] is within 5 of 255
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-shadow.html
index 7cd457e7..c117b7d 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-shadow.html
@@ -1,55 +1,35 @@
 <!DOCTYPE HTML>
 <html>
 <body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript" src="canvas-blending-helpers.js"></script>
+<script>
+test(function(t) {
+    function checkShadowColor(i, context, sigma) {
+        var expectedShadowColor = blendColors([192 / 255, 192 / 255, 192 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
+        var ac = context.getImageData(11, 11, 1, 1).data;
+        assert_approx_equals(ac[0], expectedShadowColor[0], sigma);
+        assert_approx_equals(ac[1], expectedShadowColor[1], sigma);
+        assert_approx_equals(ac[2], expectedShadowColor[2], sigma);
+        assert_approx_equals(ac[3], expectedShadowColor[3], sigma);
+    }
 
-        description("Series of tests to ensure correct results on applying different blend modes when drawing a rectangle with shadow.");
+    var canvas = document.createElement('canvas');
+    var sigma = 5;
+    canvas.width = 12;
+    canvas.height = 12;
+    context = canvas.getContext('2d');
 
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
-        }
-
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 0)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-
-            var expectedShadowColor = blendColors([192 / 255, 192 / 255, 192 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(11, 11)";
-            shouldBeCloseTo(ac + "[0]", expectedShadowColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedShadowColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedShadowColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedShadowColor[3], sigma);
-        }
-
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 12;
-            canvas.height = 12;
-            context = canvas.getContext("2d");
-
-            for (var i = 0; i < blendModes.length; ++i) {
-                debug("Testing blend mode " + blendModes[i]);
-
-                context.clearRect(0, 0, 12, 12);
-                context.save();
-                drawBackdropColorWithShadowInContext(context);
-                context.globalCompositeOperation = blendModes[i];
-                drawSourceColorRectOverShadow(context);
-                checkBlendModeResult(i, context, sigma);
-                context.restore();
-                debug('');
-            }
-        }
-
-        runTest();
-    </script>
-</body>
-</html>
+    for (var i = 0; i < blendModes.length; ++i) {
+        context.clearRect(0, 0, 12, 12);
+        context.save();
+        drawBackdropColorWithShadowInContext(context);
+        context.globalCompositeOperation = blendModes[i];
+        drawSourceColorRectOverShadow(context);
+        checkBlendModeResult(i, context, 5);
+        checkShadowColor(i, context, sigma);
+        context.restore();
+    }
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing a rectangle with shadow.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-transforms-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-transforms-expected.txt
deleted file mode 100644
index 41f7d20..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-transforms-expected.txt
+++ /dev/null
@@ -1,169 +0,0 @@
-Series of tests to ensure correct results on applying different blend modes when drawing in a transformed context.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Testing blend mode source-over
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 129
-PASS actualColor(0, 1)[2] is within 5 of 129
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode multiply
-PASS actualColor(0, 1)[0] is within 5 of 129
-PASS actualColor(0, 1)[1] is within 5 of 129
-PASS actualColor(0, 1)[2] is within 5 of 65.25882352941176
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode screen
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 192.74117647058821
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode overlay
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode darken
-PASS actualColor(0, 1)[0] is within 5 of 129
-PASS actualColor(0, 1)[1] is within 5 of 129
-PASS actualColor(0, 1)[2] is within 5 of 129
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode lighten
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 129
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode color-dodge
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 255
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode color-burn
-PASS actualColor(0, 1)[0] is within 5 of 129
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 5.930232558139517
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode hard-light
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 130.48235294117646
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode soft-light
-PASS actualColor(0, 1)[0] is within 5 of 181.3697880023021
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 129.61611515296823
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode difference
-PASS actualColor(0, 1)[0] is within 5 of 126
-PASS actualColor(0, 1)[1] is within 5 of 126
-PASS actualColor(0, 1)[2] is within 5 of 0
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode exclusion
-PASS actualColor(0, 1)[0] is within 5 of 126
-PASS actualColor(0, 1)[1] is within 5 of 126
-PASS actualColor(0, 1)[2] is within 5 of 127.48235294117649
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode hue
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 181
-PASS actualColor(0, 1)[2] is within 5 of 181
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode saturation
-PASS actualColor(0, 1)[0] is within 5 of 129
-PASS actualColor(0, 1)[1] is within 5 of 255
-PASS actualColor(0, 1)[2] is within 5 of 129
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode color
-PASS actualColor(0, 1)[0] is within 5 of 255
-PASS actualColor(0, 1)[1] is within 5 of 181
-PASS actualColor(0, 1)[2] is within 5 of 181
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-Testing blend mode luminosity
-PASS actualColor(0, 1)[0] is within 5 of 92
-PASS actualColor(0, 1)[1] is within 5 of 218
-PASS actualColor(0, 1)[2] is within 5 of 92
-PASS actualColor(0, 1)[3] is within 5 of 255
-PASS actualColor(9, 9)[0] is within 5 of 0
-PASS actualColor(9, 9)[1] is within 5 of 0
-PASS actualColor(9, 9)[2] is within 5 of 0
-PASS actualColor(9, 9)[3] is within 5 of 0
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-transforms.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-transforms.html
index fdae15a..b3ffd54 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-transforms.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-blending-transforms.html
@@ -1,55 +1,32 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript" src="canvas-blending-helpers.js"></script>
-    <script type="text/javascript">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script type="text/javascript" src="canvas-blending-helpers.js"></script>
+<script>
+test(function(t) {
+    function checkNonBlendPixel(context, sigma) {
+        ac = context.getImageData(9, 9, 1, 1).data;;
+        assert_approx_equals(ac[0], 0, sigma);
+        assert_approx_equals(ac[1], 0, sigma);
+        assert_approx_equals(ac[2], 0, sigma);
+        assert_approx_equals(ac[3], 0, sigma);
+    }
 
-        description("Series of tests to ensure correct results on applying different blend modes when drawing in a transformed context.");
+    var canvas = document.createElement('canvas');
+    var sigma = 5;
+    canvas.width = 10;
+    canvas.height = 10;
+    context = canvas.getContext('2d');
 
-        var context;
-        function actualColor(x, y) {
-            return context.getImageData(x, y, 1, 1).data;
-        }
-
-        function checkBlendModeResult(i, context, sigma) {
-            var expectedColor = blendColors([129 / 255, 1, 129 / 255, 1], [1, 129 / 255, 129 / 255, 1], i);
-            var ac = "actualColor(0, 1)";
-            shouldBeCloseTo(ac + "[0]", expectedColor[0], sigma);
-            shouldBeCloseTo(ac + "[1]", expectedColor[1], sigma);
-            shouldBeCloseTo(ac + "[2]", expectedColor[2], sigma);
-            shouldBeCloseTo(ac + "[3]", expectedColor[3], sigma);
-
-            ac = "actualColor(9, 9)";
-            shouldBeCloseTo(ac + "[0]", 0, sigma);
-            shouldBeCloseTo(ac + "[1]", 0, sigma);
-            shouldBeCloseTo(ac + "[2]", 0, sigma);
-            shouldBeCloseTo(ac + "[3]", 0, sigma);
-        }
-
-        function runTest() {
-            var canvas = document.createElement("canvas");
-            var sigma = 5;
-            canvas.width = 10;
-            canvas.height = 10;
-            context = canvas.getContext("2d");
-
-            for (var i = 0; i < blendModes.length; ++i) {
-                debug("Testing blend mode " + blendModes[i]);
-
-                context.clearRect(0, 0, 10, 10);
-                context.save();
-                applyTransformsToContext(context);
-                drawBackdropColorInContext(context);
-                context.globalCompositeOperation = blendModes[i];
-                drawSourceColorInContext(context);
-                checkBlendModeResult(i, context, sigma);
-                context.restore();
-                debug('');
-            }
-        }
-
-        runTest();
-    </script>
-</body>
-</html>
\ No newline at end of file
+    for (var i = 0; i < blendModes.length; ++i) {
+        context.clearRect(0, 0, 10, 10);
+        context.save();
+        applyTransformsToContext(context);
+        drawBackdropColorInContext(context);
+        context.globalCompositeOperation = blendModes[i];
+        drawSourceColorInContext(context);
+        checkBlendModeResult(i, context, sigma, 0, 1);
+        checkNonBlendPixel(context, sigma);
+        context.restore();
+    }
+}, 'Series of tests to ensure correct results on applying different blend modes when drawing in a transformed context.');
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-blend-solid.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-blend-solid.js
deleted file mode 100644
index a05c67a..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-blend-solid.js
+++ /dev/null
@@ -1,187 +0,0 @@
-description("Series of tests to ensure correct results on applying different blend modes.");
-
-var tmpimg = document.createElement('canvas');
-tmpimg.width = 200;
-tmpimg.height = 200;
-ctx = tmpimg.getContext('2d');
-
-// Create the image for blending test with images.
-var img = document.createElement('canvas');
-img.width = 200;
-img.height = 200;
-var imgCtx = img.getContext('2d');
-imgCtx.fillStyle = "red";
-imgCtx.fillRect(0,0,100,100);
-imgCtx.fillStyle = "yellow";
-imgCtx.fillRect(100,0,100,100);
-imgCtx.fillStyle = "green";
-imgCtx.fillRect(100,100,100,100);
-imgCtx.fillStyle = "blue";
-imgCtx.fillRect(0,100,100,100);
-
-
-// Create expected results.
-var blendModes =
-// [blendMode, expectations solid on solid, expectations solid on alpha, expectations alpha on solid, expectations alpha on alpha]
-[
-  ['source-over',
-	 [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
-	 [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
-	 [[255, 0, 0, 255],[255, 255, 0, 255],[0, 128, 0, 255],[0, 0, 255, 255]],
-	 [[171, 0, 84, 191],[171, 171, 84, 191],[0, 85, 84, 191],[0, 0, 255, 191]]
-  ],
-  ['multiply',
-	 [[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 255, 255]],
-	 [[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
-	 [[128, 0, 0, 255],[128, 128, 0, 255],[0, 64, 0, 255],[0, 0, 255, 255]],
-	 [[85, 0, 84, 191],[85, 85, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
-  ],
-  ['screen',
-	 [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 255, 255]],
-	 [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 255, 255]],
-	 [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 255, 255]],
-	 [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 255, 191]]
-  ],
-  ['overlay',
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-	 [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
-	 [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
-  ],
-  ['darken',
-	 [[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 0, 255],[0, 0, 255, 255]],
-	 [[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
-	 [[128, 0, 0, 255],[128, 128, 0, 255],[0, 64, 0, 255],[0, 0, 255, 255]],
-	 [[85, 0, 84, 191],[85, 85, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
-  ],
-  ['lighten',
-	 [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 255, 255]],
-	 [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 255, 255]],
-	 [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 255, 255]],
-	 [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 255, 191]]
-  ],
-  ['color-dodge',
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-	 [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
-	 [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
-  ],
-  ['color-burn',
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-         [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
-         [[85, 0, 170, 191],[85, 85, 170, 191],[0, 42, 170, 191],[0, 0, 255, 191]]
-
-  ],
-  ['hard-light',
-	 [[255, 0, 0, 255],[255, 255, 0, 255],[0, 1, 0, 255],[0, 0, 255, 255]],
-	 [[128, 0, 127, 255],[128, 128, 127, 255],[0, 0, 127, 255],[0, 0, 255, 255]],
-	 [[255, 0, 0, 255],[255, 255, 0, 255],[0, 65, 0, 255],[0, 0, 255, 255]],
-	 [[171, 0, 84, 191],[171, 171, 84, 191],[0, 43, 84, 191],[0, 0, 255, 191]]
-  ],
-  ['soft-light',
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255],[0, 0, 255, 255]],
-	 [[128, 0, 127, 255],[128, 128, 127, 255],[0, 64, 127, 255],[0, 0, 255, 255]],
-	 [[85, 0, 170, 191],[85, 85, 170, 191],[0, 43, 170, 191],[0, 0, 255, 191]]
-  ],
-  ['difference',
-	 [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 0, 255]],
-	 [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 127, 255]],
-	 [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 128, 255]],
-	 [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 171, 191]]
-  ],
-  ['exclusion',
-	 [[255, 0, 255, 255],[255, 255, 255, 255],[0, 128, 255, 255],[0, 0, 0, 255]],
-	 [[128, 0, 255, 255],[128, 128, 255, 255],[0, 64, 255, 255],[0, 0, 127, 255]],
-	 [[255, 0, 127, 255],[255, 255, 127, 255],[0, 128, 127, 255],[0, 0, 128, 255]],
-	 [[171, 0, 170, 191],[171, 171, 170, 191],[0, 85, 170, 191],[0, 0, 171, 191]]
-  ],
-  ['hue',
-	 [[93, 0, 0, 255],[31, 31, 0, 255],[0, 46, 0, 255],[0, 0, 255, 255]],
-	 [[49, 0, 127, 255],[16, 16, 127, 255],[0, 25, 127, 255],[0, 0, 255, 255]],
-	 [[175, 0, 0, 255],[144, 144, 0, 255],[0, 88, 0, 255],[0, 0, 255, 255]],
-	 [[116, 0, 84, 191],[96, 96, 84, 191],[0, 58, 84, 191],[0, 0, 255, 191]]
-  ],
-  ['saturation',
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[14, 14, 142, 255],[0, 0, 255, 255]],
-	 [[0, 0, 255, 255],[0, 0, 255, 255],[7, 7, 198, 255],[0, 0, 255, 255]],
-	 [[128, 0, 127, 255],[128, 128, 127, 255],[7, 71, 70, 255],[0, 0, 255, 255]],
-	 [[85, 0, 167, 191],[85, 85, 167, 191],[0, 48, 130, 191],[0, 0, 255, 191]]
-  ],
-  ['color',
-	 [[93, 0, 0, 255],[31, 31, 0, 255],[0, 47, 0, 255],[0, 0, 255, 255]],
-	 [[49, 0, 127, 255],[16, 16, 127, 255],[0, 24, 127, 255],[0, 0, 255, 255]],
-	 [[175, 0, 0, 255],[144, 144, 0, 255],[0, 88, 0, 255],[0, 0, 255, 255]],
-	 [[116, 0, 84, 191],[96, 96, 84, 191],[0, 58, 84, 191],[0, 0, 255, 191]]
-  ],
-  ['luminosity',
-	 [[55, 55, 255, 255],[224, 224, 255, 255],[54, 54, 255, 255],[0, 0, 255, 255]],
-	 [[28, 28, 255, 255],[112, 112, 255, 255],[27, 27, 255, 255],[0, 0, 255, 255]],
-	 [[155, 27, 127, 255],[239, 239, 127, 255],[26, 90, 127, 255],[0, 0, 255, 255]],
-	 [[104, 19, 167, 191],[158, 158, 167, 191],[16, 58, 167, 191],[0, 0, 255, 191]]
-  ]];
-
-// [Scenario, alpha on background, alpha on foreground]
-var testScenario = [
-  ['solid on solid', 1, 1],
-  ['solid on alpha', 1, 0.5],
-  ['alpha on solid', 0.5, 1],
-  ['alpha on alpha', 0.5, 0.5]
-];
-
-testPoints = [{x: 50, y: 50}, {x: 150, y: 50}, {x: 150, y: 150}, {x: 50, y: 150}];
-
-function pixelDataAtPoint(i, blend)
-{
-  return ctx.getImageData(testPoints[i].x, testPoints[i].y , 1, 1).data;
-}
-
-function checkBlendModeResult(blendMode, testScenario, expectedColors, sigma) {
-  debug(testScenario);
-  for (var i = 0; i < testPoints.length; i++) {
-    var resultColor = "pixelDataAtPoint(" + i + ")";
-    shouldBeCloseTo(resultColor +"[0]", expectedColors[i][0], sigma);
-    shouldBeCloseTo(resultColor +"[1]", expectedColors[i][1], sigma);
-    shouldBeCloseTo(resultColor +"[2]", expectedColors[i][2], sigma);
-    shouldBeCloseTo(resultColor +"[3]", expectedColors[i][3], sigma);
-    }
-}
-
-// Execute test.
-function prepareTestScenario(sigma) {
-  // Check each blend mode individually.
-  for (var i = 0; i < blendModes.length; i++) {
-	debug('Testing blend mode "' + blendModes[i][0] + '"');
-	for (var j = 0; j < testScenario.length; j++) {
-	  ctx.globalCompositeOperation = 'clear';
-	  ctx.fillRect(0,0,200,200);
-	  ctx.globalCompositeOperation = 'source-over';
-	  ctx.save();
-	  
-	  // Draw backdrop.
-	  ctx.fillStyle = 'rgba(0, 0, 255, ' + testScenario[j][1] + ')';
-	  ctx.fillRect(0,0,200,200);
-	  
-	  // Apply blend mode.
-	  ctx.globalCompositeOperation = blendModes[i][0];
-	  ctx.globalAlpha = testScenario[j][2];
-	  ctx.fillStyle = "red";
-	  ctx.fillRect(0,0,100,100);
-	  ctx.fillStyle = "yellow";
-	  ctx.fillRect(100,0,100,100);
-	  ctx.fillStyle = "green";
-	  ctx.fillRect(100,100,100,100);
-	  ctx.fillStyle = "blue";
-	  ctx.fillRect(0,100,100,100);
-	  ctx.restore();
-	  
-	  checkBlendModeResult(blendModes[i][0], testScenario[j][0], blendModes[i][j+1], sigma);
-	  ctx.restore();                                  
-	  }
-	debug('');
-  }
-}
-
-// Run test and allow variation of results.
-prepareTestScenario(5);
diff --git a/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/height-css-tables-expected.html b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/height-css-tables-expected.html
index 5f4d437..1e3c7f2 100644
--- a/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/height-css-tables-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/height-css-tables-expected.html
@@ -28,9 +28,10 @@
   </div>
 </div>
 
-
-<div class="table container" style="display: block; float: left; height: 98px;">
-  <div class="td" style="height: 90px;" style="display: block;">
+<!-- crbug.com/690087: We use 99px instead of 100px because we end up discarding 1px when trying
+     to allocate the spare pixels to the table. -->
+<div class="table container" style="display: block; float: left; height: 99px;">
+  <div class="td" style="height: 91px;" style="display: block;">
     <div class="item"></div>
   </div>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
index c563597..9ae932e3 100644
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk.html b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk.html
new file mode 100644
index 0000000..02c7666
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<style>
+.test-block {
+  border: 2px solid orange;
+  padding: 1px;
+  line-height: 1.2;
+  position: relative;
+  display: inline-block;
+  vertical-align: top;
+}
+.test-block::before {
+  content: attr(title);
+  font-family: sans-serif;
+  background-color: white;
+  border: 2px solid gray;
+  padding: .2em;
+  line-height: 1;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+.test-block div {
+  display: inline-block;
+  border: 1px solid lime;
+}
+.vrl {
+  -webkit-writing-mode: vertical-rl;
+  writing-mode: vertical-rl;
+}
+.vlr {
+  -webkit-writing-mode: vertical-lr;
+  writing-mode: vertical-lr;
+}
+.sideways {
+  text-orientation: sideways;
+}
+.msgothic { font-family: 'MS Gothic'; }
+.meiryo { font-family: Meiryo; }
+.noto { font-family: 'Noto Sans CJK JP'; }
+.yugothic { font-family: 'Yu Gothic', YuGothic; }
+.large { font-size: 200%; }
+.under {
+  text-underline-position: under;
+  -moz-text-underline-position: under;
+  -ms-text-underline-position: below;
+  -webkit-text-underline-position: under;
+}
+.under-left {
+  text-underline-position: under left;
+  -moz-text-underline-position: under left;
+  -ms-text-underline-position: below;
+  -webkit-text-underline-position: under left;
+}
+.under-right {
+  text-underline-position: under right;
+  -moz-text-underline-position: under right;
+  -ms-text-underline-position: below;
+  -webkit-text-underline-position: under right;
+}
+</style>
+<body>
+  <div title="initial" class="test-block">
+    <div>
+      <div><u>漢efg混植</u></div><br>
+      <div class="msgothic"><u>漢efg混植</u></div><br>
+      <div class="meiryo"><u>漢efg混植</u></div><br>
+      <div class="yugothic"><u>漢efg混植</u></div><br>
+      <div class="noto"><u>漢efg混植</u></div><br>
+      <div><u>漢<span class="large">efg</span>混植</u></div><br>
+    </div><br>
+    <div class="vrl"><u>漢efg混植</u></div>
+    <div class="vrl meiryo"><u>漢efg混植</u></div>
+    <div class="vrl sideways"><u>漢efg混植</u></div>
+    <div class="vlr"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+    <div class="vlr sideways"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+    <div class="vrl"><u>漢<span class="large">漢fg</span>混植</u></div>
+    <div class="vlr"><u>漢<span class="large">漢fg</span>混植</u></div>
+  </div>
+  <div title="lang=zh" lang="zh" class="test-block">
+    <div>
+      <div><u>漢efg混植</u></div><br>
+      <div class="msgothic"><u>漢efg混植</u></div><br>
+      <div class="meiryo"><u>漢efg混植</u></div><br>
+      <div class="yugothic"><u>漢efg混植</u></div><br>
+      <div class="noto"><u>漢efg混植</u></div><br>
+      <div><u>漢<span class="large">efg</span>混植</u></div><br>
+    </div><br>
+    <div class="vrl"><u>漢efg混植</u></div>
+    <div class="vrl meiryo"><u>漢efg混植</u></div>
+    <div class="vrl sideways"><u>漢efg混植</u></div>
+    <div class="vlr"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+    <div class="vlr sideways"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+    <div class="vrl"><u>漢<span class="large">漢fg</span>混植</u></div>
+    <div class="vlr"><u>漢<span class="large">漢fg</span>混植</u></div>
+  </div>
+  <div title="lang=ja" lang="ja" class="test-block">
+    <div>
+      <div><u>漢efg混植</u></div><br>
+      <div class="msgothic"><u>漢efg混植</u></div><br>
+      <div class="meiryo"><u>漢efg混植</u></div><br>
+      <div class="yugothic"><u>漢efg混植</u></div><br>
+      <div class="noto"><u>漢efg混植</u></div><br>
+      <div><u>漢<span class="large">efg</span>混植</u></div><br>
+    </div><br>
+    <div class="vrl"><u>漢efg混植</u></div>
+    <div class="vrl meiryo"><u>漢efg混植</u></div>
+    <div class="vrl sideways"><u>漢efg混植</u></div>
+    <div class="vlr"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+    <div class="vlr sideways"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+    <div class="vrl"><u>漢<span class="large">漢fg</span>混植</u></div>
+    <div class="vlr"><u>漢<span class="large">漢fg</span>混植</u></div>
+  </div>
+  <div class="under">
+    <div title="under" class="test-block">
+      <div>
+        <div><u>漢efg混植</u></div><br>
+        <div class="msgothic"><u>漢efg混植</u></div><br>
+        <div class="meiryo"><u>漢efg混植</u></div><br>
+        <div class="yugothic"><u>漢efg混植</u></div><br>
+        <div class="noto"><u>漢efg混植</u></div><br>
+        <div><u>漢<span class="large">efg</span>混植</u></div><br>
+      </div><br>
+      <div class="vrl"><u>漢efg混植</u></div>
+      <div class="vrl meiryo"><u>漢efg混植</u></div>
+      <div class="vrl sideways"><u>漢efg混植</u></div>
+      <div class="vlr"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+      <div class="vlr sideways"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+      <div class="vrl"><u>漢<span class="large">漢fg</span>混植</u></div>
+      <div class="vlr"><u>漢<span class="large">漢fg</span>混植</u></div>
+    </div>
+    <div title="under zh" lang="zh" class="test-block">
+      <div>
+        <div><u>漢efg混植</u></div><br>
+        <div class="msgothic"><u>漢efg混植</u></div><br>
+        <div class="meiryo"><u>漢efg混植</u></div><br>
+        <div class="yugothic"><u>漢efg混植</u></div><br>
+        <div class="noto"><u>漢efg混植</u></div><br>
+        <div><u>漢<span class="large">efg</span>混植</u></div><br>
+      </div><br>
+      <div class="vrl"><u>漢efg混植</u></div>
+      <div class="vrl meiryo"><u>漢efg混植</u></div>
+      <div class="vrl sideways"><u>漢efg混植</u></div>
+      <div class="vlr"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+      <div class="vlr sideways"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+      <div class="vrl"><u>漢<span class="large">漢fg</span>混植</u></div>
+      <div class="vlr"><u>漢<span class="large">漢fg</span>混植</u></div>
+    </div>
+    <div title="under ja" lang="ja" class="test-block">
+      <div>
+        <div><u>漢efg混植</u></div><br>
+        <div class="msgothic"><u>漢efg混植</u></div><br>
+        <div class="meiryo"><u>漢efg混植</u></div><br>
+        <div class="yugothic"><u>漢efg混植</u></div><br>
+        <div class="noto"><u>漢efg混植</u></div><br>
+        <div><u>漢<span class="large">efg</span>混植</u></div><br>
+      </div><br>
+      <div class="vrl"><u>漢efg混植</u></div>
+      <div class="vrl meiryo"><u>漢efg混植</u></div>
+      <div class="vrl sideways"><u>漢efg混植</u></div>
+      <div class="vlr"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+      <div class="vlr sideways"><u>ᠮᠣᠨᠭᠭᠣᠯ ᠬᠡᠯᠡ efg漢</u></div>
+      <div class="vrl"><u>漢<span class="large">漢fg</span>混植</u></div>
+      <div class="vlr"><u>漢<span class="large">漢fg</span>混植</u></div>
+    </div>
+  </div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt
index 70bffc0a..2531e7e1 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt
@@ -9,13 +9,13 @@
 PASS "2009-09-07T16:49:31.1" is a correct valid datetime-local string.
 PASS "2009-09-07T16:49:31.12" is a correct valid datetime-local string.
 PASS "2009-09-07T16:49:31.123" is a correct valid datetime-local string.
-PASS "2009-09-07T16:49:31.1234567890" is a correct valid datetime-local string.
 PASS "275760-09-13T00:00:00.000" is a correct valid datetime-local string.
 PASS "0001-01-01T00:00:00.000" is a correct valid datetime-local string.
 PASS " 2009-09-07T16:49 " is an invalid datetime-local string and was sanitized.
 PASS "2009-09-07t16:49" is an invalid datetime-local string and was sanitized.
 PASS "2009-09-07 16:49" is an invalid datetime-local string and was sanitized.
 PASS "2009/09/07T16:49" is an invalid datetime-local string and was sanitized.
+PASS "2009-09-07T16:49:31.1234567890" is an invalid datetime-local string and was sanitized.
 PASS "a" is an invalid datetime-local string and was sanitized.
 PASS "-1-09-07T16:49" is an invalid datetime-local string and was sanitized.
 PASS "0000-12-31T23:59:59.999" is an invalid datetime-local string and was sanitized.
diff --git a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html
index 4db35fc..47f9ab9 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html
@@ -45,7 +45,6 @@
 shouldBeValid('2009-09-07T16:49:31.1');
 shouldBeValid('2009-09-07T16:49:31.12');
 shouldBeValid('2009-09-07T16:49:31.123');
-shouldBeValid('2009-09-07T16:49:31.1234567890');
 shouldBeValid('275760-09-13T00:00:00.000');
 shouldBeValid('0001-01-01T00:00:00.000');
 
@@ -54,6 +53,7 @@
 shouldBeInvalid('2009-09-07t16:49');
 shouldBeInvalid('2009-09-07 16:49');
 shouldBeInvalid('2009/09/07T16:49');
+shouldBeInvalid('2009-09-07T16:49:31.1234567890');
 shouldBeInvalid('a');
 shouldBeInvalid('-1-09-07T16:49');
 shouldBeInvalid('0000-12-31T23:59:59.999');
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch-expected.txt
index 64fb0c5..f7ffedf 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch-expected.txt
@@ -10,8 +10,6 @@
 PASS "23:59:59.1" is a correct valid time string.
 PASS "23:59:59.12" is a correct valid time string.
 PASS "23:59:59.123" is a correct valid time string.
-PASS "23:59:59.1234567890" is a correct valid time string.
-PASS "00:00:00.0000000000" is a correct valid time string.
 PASS " 00:00 " is an invalid time string and was sanitized.
 PASS "1:23" is an invalid time string and was sanitized.
 PASS "011:11" is an invalid time string and was sanitized.
@@ -33,6 +31,8 @@
 PASS "23:45:06." is an invalid time string and was sanitized.
 PASS "23:45:06.abc" is an invalid time string and was sanitized.
 PASS "23:45:06.789abc" is an invalid time string and was sanitized.
+PASS "23:59:59.1234567890" is an invalid time string and was sanitized.
+PASS "00:00:00.0000000000" is an invalid time string and was sanitized.
 PASS "invalid" is an invalid time string and was sanitized while disabled.
 PASS successfullyParsed is true
 
diff --git a/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch.html b/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch.html
index ed410ac..c5a7d4c 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/time/time-validity-typemismatch.html
@@ -46,8 +46,6 @@
 shouldBeValid('23:59:59.1');
 shouldBeValid('23:59:59.12');
 shouldBeValid('23:59:59.123');
-shouldBeValid('23:59:59.1234567890');
-shouldBeValid('00:00:00.0000000000');
 
 // Invalid values
 shouldBeInvalid(' 00:00 ');
@@ -71,6 +69,8 @@
 shouldBeInvalid('23:45:06.');
 shouldBeInvalid('23:45:06.abc');
 shouldBeInvalid('23:45:06.789abc');
+shouldBeInvalid('23:59:59.1234567890');
+shouldBeInvalid('00:00:00.0000000000');
 
 // Disabled
 shouldBeInvalid('invalid', true);
diff --git a/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html b/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html
index 98b1789..34d718f 100644
--- a/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html
+++ b/third_party/WebKit/LayoutTests/fast/text/selection-exceptions.html
@@ -21,6 +21,7 @@
         shouldThrow('getSelection().getRangeAt(-1)', '"IndexSizeError: Failed to execute \'getRangeAt\' on \'Selection\': -1 is not a valid index."');
 
         shouldThrow('getSelection().extend(0, -1)', '"TypeError: Failed to execute \'extend\' on \'Selection\': parameter 1 is not of type \'Node\'."');
+        getSelection().addRange(document.createRange());
         shouldThrow('getSelection().extend(document.documentElement, -1)', '"IndexSizeError: Failed to execute \'extend\' on \'Selection\': -1 is not a valid offset."');
         shouldThrow('getSelection().extend(document.documentElement, 1000)', '"IndexSizeError: Failed to execute \'extend\' on \'Selection\': 1000 is larger than the given node\'s length."');
     </script>
diff --git a/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter-window.html b/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter-window.html
new file mode 100644
index 0000000..399894a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter-window.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Shared Worker: UseCounter</title>
+<script>
+self.connectToWorker = () => {
+  return new Promise(resolve => {
+    var worker = new SharedWorker('shared-worker-usecounter.js');
+    worker.port.onmessage = resolve;
+  });
+};
+window.opener.postMessage('LOADED', '*');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter.js b/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter.js
new file mode 100644
index 0000000..80445e5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/workers/resources/shared-worker-usecounter.js
@@ -0,0 +1,11 @@
+onconnect = e => {
+  var port = e.ports[0];
+  port.onmessage = (e) => {
+    if (e.data.type == 'COUNT_FEATURE')
+      internals.countFeature(e.data.feature);
+    else if (e.data.type == 'COUNT_DEPRECATION')
+      internals.countDeprecation(e.data.feature);
+    port.postMessage('COUNTED');
+  };
+  port.postMessage('CONNECTED');
+}
diff --git a/third_party/WebKit/LayoutTests/fast/workers/shared-worker-usecounter.html b/third_party/WebKit/LayoutTests/fast/workers/shared-worker-usecounter.html
new file mode 100644
index 0000000..ef5fecb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/workers/shared-worker-usecounter.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<title>Shared Worker: UseCounter</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<body>
+</body>
+<script>
+
+const kFeature = 675;  // From UseCounter.h
+const kDeprecatedFeature = 538;  // From Deprecation.h
+
+function isUseCounted(win, feature) {
+  return win.internals.isUseCounted(win.document, feature);
+}
+
+function openWindow(url) {
+  return new Promise(resolve => {
+      let win = window.open(url, '_blank');
+      add_completion_callback(() => win.close());
+      window.onmessage = e => {
+        assert_equals(e.data, 'LOADED');
+        resolve(win);
+      };
+    });
+}
+
+promise_test(t => {
+  const kWindowUrl = 'resources/shared-worker-usecounter-window.html';
+
+  let win1;
+  let win2;
+  let win3;
+  let worker;
+
+  return openWindow(kWindowUrl)
+    .then(win => {
+        win1 = win;
+        win1.connectToWorker();
+        return openWindow(kWindowUrl);
+      })
+    .then(win => {
+        win2 = win;
+        win2.connectToWorker();
+
+        // Connect to a shared worker from the main document to get a
+        // communication channel to the worker.
+        worker = new SharedWorker('resources/shared-worker-usecounter.js');
+        return new Promise(resolve => worker.port.onmessage = resolve);
+      })
+    .then(e => {
+        assert_equals(e.data, 'CONNECTED');
+
+        assert_false(isUseCounted(win1, kFeature));
+        assert_false(isUseCounted(win2, kFeature));
+
+        // Request to count a feature.
+        let promise =
+            new Promise(resolve => worker.port.onmessage = resolve);
+        worker.port.postMessage({type: 'COUNT_FEATURE', feature: kFeature});
+        return promise;
+      })
+    .then(e => {
+        assert_equals(e.data, 'COUNTED');
+
+        // API use on the SharedWorkerGlobalScope is recorded in UseCounters on
+        // all connected documents.
+        assert_true(isUseCounted(win1, kFeature));
+        assert_true(isUseCounted(win2, kFeature));
+
+        assert_false(isUseCounted(win1, kDeprecatedFeature));
+        assert_false(isUseCounted(win2, kDeprecatedFeature));
+
+        // Request to count a deprecated feature.
+        let promise =
+            new Promise(resolve => worker.port.onmessage = resolve);
+        worker.port.postMessage(
+            {type: 'COUNT_DEPRECATION', feature: kDeprecatedFeature});
+        return promise;
+      })
+    .then(e => {
+        assert_equals(e.data, 'COUNTED');
+
+        // Deprecated API use on the SharedWorkerGlobalScope is recorded in
+        // UseCounters on all connected documents.
+        assert_true(isUseCounted(win1, kDeprecatedFeature));
+        assert_true(isUseCounted(win2, kDeprecatedFeature));
+
+        return openWindow(kWindowUrl);
+      })
+    .then(win => {
+        win3 = win;
+        // A new document hasn't connected to the worker, so the API use should
+        // not be counted yet.
+        assert_false(isUseCounted(win3, kFeature));
+        assert_false(isUseCounted(win3, kDeprecatedFeature));
+        return win3.connectToWorker();
+      })
+    .then(() => {
+        // A counter of the newly connected document should be synced with
+        // others.
+        assert_true(isUseCounted(win3, kFeature));
+        assert_true(isUseCounted(win3, kDeprecatedFeature));
+      });
+}, 'UseCounter on SharedWorkerGlobalScope');
+
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
index 494994b..9ef1231 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
@@ -79,7 +79,7 @@
 
 InspectorTest.tracingModel = function()
 {
-    return UI.panels.timeline._tracingModel;
+    return UI.panels.timeline._performanceModel.tracingModel();
 }
 
 InspectorTest.invokeWithTracing = function(functionName, callback, additionalCategories, enableJSSampling)
@@ -104,37 +104,36 @@
     }
 }
 
+InspectorTest.performanceModel = function()
+{
+    return UI.panels.timeline._performanceModel;
+}
+
 InspectorTest.timelineModel = function()
 {
-    return UI.panels.timeline._model;
+    return InspectorTest.performanceModel().timelineModel();
 }
 
 InspectorTest.timelineFrameModel = function()
 {
-    return UI.panels.timeline._frameModel;
+    return InspectorTest.performanceModel().frameModel();
 }
 
-InspectorTest.setTraceEvents = function(timelineModel, tracingModel, events)
-{
-    tracingModel.reset();
-    tracingModel.addEvents(events);
-    tracingModel.tracingComplete();
-    timelineModel.setEvents(tracingModel);
-}
-
-InspectorTest.createTimelineModelWithEvents = function(events)
+InspectorTest.createPerformanceModelWithEvents = function(events)
 {
     var tracingModel = new SDK.TracingModel(new Bindings.TempFileBackingStorage("tracing"));
-    var timelineModel = new TimelineModel.TimelineModel();
-    InspectorTest.setTraceEvents(timelineModel, tracingModel, events);
-    return timelineModel;
+    tracingModel.addEvents(events);
+    tracingModel.tracingComplete();
+    var performanceModel = new Timeline.PerformanceModel();
+    performanceModel.setTracingModel(tracingModel);
+    return performanceModel;
 }
 
 InspectorTest.timelineController = function()
 {
-    var mainTarget = SDK.targetManager.mainTarget();
-    var timelinePanel =  UI.panels.timeline;
-    return new Timeline.TimelineController(mainTarget, timelinePanel, timelinePanel._tracingModel);
+    var performanceModel = new Timeline.PerformanceModel();
+    UI.panels.timeline._pendingPerformanceModel = performanceModel;
+    return new Timeline.TimelineController(SDK.targetManager.mainTarget(), performanceModel, UI.panels.timeline);
 }
 
 InspectorTest.startTimeline = function(callback)
@@ -215,9 +214,10 @@
 
 InspectorTest.walkTimelineEventTree = function(callback)
 {
-    var model = InspectorTest.timelineModel();
-    var view = new Timeline.EventsTimelineTreeView(model, UI.panels.timeline._filters, null);
-    var selection = Timeline.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime());
+    var performanceModel = InspectorTest.performanceModel();
+    var view = new Timeline.EventsTimelineTreeView(UI.panels.timeline._filters, null);
+    view.setModel(performanceModel);
+    var selection = Timeline.TimelineSelection.fromRange(performanceModel.timelineModel().minimumRecordTime(), performanceModel.timelineModel().maximumRecordTime());
     view.updateContents(selection);
     InspectorTest.walkTimelineEventTreeUnderNode(callback, view._currentTree, 0);
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-receive-response-event.html b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-receive-response-event.html
index 447cf2dc..5b77470 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-receive-response-event.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/tracing/timeline-receive-response-event.html
@@ -27,7 +27,6 @@
 {
     UI.viewManager.showView("timeline");
     const panel = UI.panels.timeline;
-    panel._model._currentTarget = SDK.targetManager.mainTarget();
     panel._disableCaptureJSProfileSetting.set(true);
     InspectorTest.invokeAsyncWithTimeline("performActions", finish);
 
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-timestamp-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-timestamp-expected.txt
index 5256333f..a320cae 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-timestamp-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-timestamp-expected.txt
@@ -3,13 +3,6 @@
 Console messages with timestamps disabled:
 3<Before>
 Console messages with timestamps enabled:
-2014-05-13 16:53:20.123 <Before>
-2014-05-13 16:53:20.123 <Before>
-2014-05-13 16:53:20.456 <Before>
-2014-05-13 16:53:21.000 <After>
-2014-05-13 16:53:21.000 <After>
-2014-05-13 16:53:21.456 <After>
-Console messages with short timestamps:
 16:53:20.123 <Before>
 16:53:20.123 <Before>
 16:53:20.456 <Before>
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html b/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html
index 8e75051..634b5d0 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html
@@ -37,20 +37,16 @@
     InspectorTest.dumpConsoleMessages();
 
     InspectorTest.addResult("Console messages with timestamps enabled:");
-    Common.settingForTest("consoleTimestampFormat").set(Console.ConsoleViewMessage.TimestampFormat.Full);
+    Common.settingForTest("consoleTimestampsEnabled").set(true);
 
     addMessageWithFixedTimestamp("<After>", baseTimestamp + 1000);
     addMessageWithFixedTimestamp("<After>", baseTimestamp + 1000);
     addMessageWithFixedTimestamp("<After>", baseTimestamp + 1456);
 
-    Common.settingForTest("consoleTimestampFormat").set(Console.ConsoleViewMessage.TimestampFormat.None);
-    Common.settingForTest("consoleTimestampFormat").set(Console.ConsoleViewMessage.TimestampFormat.Full);
+    Common.settingForTest("consoleTimestampsEnabled").set(false);
+    Common.settingForTest("consoleTimestampsEnabled").set(true);
 
     InspectorTest.dumpConsoleMessages();
-
-    InspectorTest.addResult("Console messages with short timestamps:");
-    Common.settingForTest("consoleTimestampFormat").set(Console.ConsoleViewMessage.TimestampFormat.Short);
-    InspectorTest.dumpConsoleMessages();
     InspectorTest.completeTest();
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage-expected.txt
index 4f903256..8eca530 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage-expected.txt
@@ -1,8 +1,8 @@
 Tests that buffer usage update are sent when recording trace events and TimelineLifecycleDelegate methods are properly invoked in the expected order.
 
-TimelineLifecycleDelegate.recordingStarted
-TimelineLifecycleDelegate.recordingProgress
-TimelineLifecycleDelegate.loadingStarted
-TimelineLifecycleDelegate.loadingProgress
-TimelineLifecycleDelegate.loadingComplete
+TimelineControllerClient.recordingStarted
+TimelineControllerClient.recordingProgress
+TimelineControllerClient.loadingStarted
+TimelineControllerClient.loadingProgress
+TimelineControllerClient.loadingComplete
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage.html b/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage.html
index a7309171..b97c38ec 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/buffer-usage.html
@@ -6,29 +6,29 @@
 
 function test()
 {
-    TestTimelineLifecycleDelegate = function()
+    TestTimelineControllerClient = function()
     {
         this._hadLoadingProgress = false;
     }
 
-    TestTimelineLifecycleDelegate.prototype = {
+    TestTimelineControllerClient.prototype = {
         recordingStarted: function()
         {
-            InspectorTest.addResult("TimelineLifecycleDelegate.recordingStarted");
+            InspectorTest.addResult("TimelineControllerClient.recordingStarted");
         },
 
         recordingProgress: function()
         {
             if (!controller)
                 return;
-            InspectorTest.addResult("TimelineLifecycleDelegate.recordingProgress");
+            InspectorTest.addResult("TimelineControllerClient.recordingProgress");
             controller.stopRecording();
             controller = null;
         },
 
         loadingStarted: function()
         {
-            InspectorTest.addResult("TimelineLifecycleDelegate.loadingStarted");
+            InspectorTest.addResult("TimelineControllerClient.loadingStarted");
         },
 
         loadingProgress: function()
@@ -36,17 +36,17 @@
             if (this._hadLoadingProgress)
                 return;
             this._hadLoadingProgress = true;
-            InspectorTest.addResult("TimelineLifecycleDelegate.loadingProgress");
+            InspectorTest.addResult("TimelineControllerClient.loadingProgress");
         },
 
         loadingComplete: function()
         {
-            InspectorTest.addResult("TimelineLifecycleDelegate.loadingComplete");
+            InspectorTest.addResult("TimelineControllerClient.loadingComplete");
             InspectorTest.completeTest();
         }
     };
-
-    var controller = new Timeline.TimelineController(SDK.targetManager.mainTarget(), new TestTimelineLifecycleDelegate(), InspectorTest.createTracingModel());
+    var performanceModel = new Timeline.PerformanceModel();
+    var controller = new Timeline.TimelineController(SDK.targetManager.mainTarget(), performanceModel, new TestTimelineControllerClient());
     controller.startRecording({}, []);
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html b/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html
index 689e6e6e..415f3d9 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/category-filter.html
@@ -35,9 +35,10 @@
         {"name": "foooooo", "ts": 1099999, "ph": "E", "tid": mainThread, "pid": pid, "cat":"toplevel", "args": {}}
     ];
 
-    var model = InspectorTest.createTimelineModelWithEvents(testData);
-    var view = new Timeline.EventsTimelineTreeView(model, UI.panels.timeline._filters, null);
-    view.updateContents(Timeline.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime()));
+    var model = InspectorTest.createPerformanceModelWithEvents(testData);
+    var view = new Timeline.EventsTimelineTreeView(UI.panels.timeline._filters, null);
+    view.setModel(model);
+    view.updateContents(Timeline.TimelineSelection.fromRange(model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime()));
     var filtersControl = view._filtersControl;
 
     InspectorTest.addResult("Original records");
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/console-timeline.html b/third_party/WebKit/LayoutTests/inspector/tracing/console-timeline.html
index 4b7f23b8..7bb3dfeb 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/console-timeline.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/console-timeline.html
@@ -79,9 +79,6 @@
 
 function test()
 {
-    var panel = UI.panels.timeline;
-    panel._model._currentTarget = SDK.targetManager.mainTarget();
-
     InspectorTest.runTestSuite([
         function testStartStopTimeline(next)
         {
@@ -171,7 +168,7 @@
     ]);
 
     function printTimelineAndTimestampEvents() {
-        panel._tracingModel.sortedProcesses().forEach(function(process)
+        InspectorTest.tracingModel().sortedProcesses().forEach(function(process)
         {
             process.sortedThreads().forEach(function(thread)
             {
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/frame-model.html b/third_party/WebKit/LayoutTests/inspector/tracing/frame-model.html
index f4f013e80..59300dc0 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/frame-model.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/frame-model.html
@@ -276,20 +276,11 @@
         ],
     };
 
-    var frameModel = new TimelineModel.TimelineFrameModel(event => Timeline.TimelineUIUtils.eventStyle(event).category.name);
-
-    function loadEvents(events)
-    {
-        var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(events);
-        frameModel.reset();
-        frameModel.addTraceEvents(SDK.targetManager.mainTarget(), tracingTimelineModel.inspectedTargetEvents(), sessionId);
-    }
-
     for (var testName in testData) {
         var data = testData[testName];
-        loadEvents(commonMetadata.concat(data))
+        var performanceModel = InspectorTest.createPerformanceModelWithEvents(commonMetadata.concat(data));
         InspectorTest.addResult("Test: " + testName);
-        frameModel.frames().forEach(InspectorTest.dumpFrame, InspectorTest);
+        performanceModel.frameModel().frames().forEach(InspectorTest.dumpFrame, InspectorTest);
     }
     InspectorTest.completeTest();
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing.html
index cb4404a..bdf1e129 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing.html
@@ -283,9 +283,8 @@
     }
 
     Runtime.experiments.enableForTest("blackboxJSFramesOnTimeline");
-    var timelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents);
-    var frameModel = new TimelineModel.TimelineFrameModel(event => Timeline.TimelineUIUtils.eventStyle(event).category.name);
-    var dataProvider = new Timeline.TimelineFlameChartDataProvider(timelineModel, frameModel, new TimelineModel.TimelineIRModel(), UI.panels.timeline._filters);
+    var dataProvider = new Timeline.TimelineFlameChartDataProvider(UI.panels.timeline._filters);
+    dataProvider.setModel(InspectorTest.createPerformanceModelWithEvents(rawTraceEvents));
 
     InspectorTest.addResult("\nBlackboxed url: lib_script.js");
     Bindings.blackboxManager._blackboxURL("lib_script.js");
@@ -294,7 +293,6 @@
     InspectorTest.addResult("\nUnblackboxed url: lib_script.js");
     Bindings.blackboxManager._unblackboxURL("lib_script.js");
     printTimelineData(dataProvider);
-
     InspectorTest.completeTest();
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks.html
index e2957c9..5182973 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks.html
@@ -550,9 +550,9 @@
     }
     ];
 
-    var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents);
-    var events = TimelineModel.TimelineJSProfileProcessor.generateJSFrameEvents(tracingTimelineModel.mainThreadEvents());
-    events = events.mergeOrdered(tracingTimelineModel.mainThreadEvents(), SDK.TracingModel.Event.orderedCompareStartTime);
+    var model = InspectorTest.createPerformanceModelWithEvents(rawTraceEvents);
+    var events = TimelineModel.TimelineJSProfileProcessor.generateJSFrameEvents(model.timelineModel().mainThreadEvents());
+    events = events.mergeOrdered(model.timelineModel().mainThreadEvents(), SDK.TracingModel.Event.orderedCompareStartTime);
     events.filter(function(e) { return e.duration; }).forEach(function(e) {
         InspectorTest.addResult(e.name + ": " + e.startTime.toFixed(3) + " / " + (e.duration.toFixed(3) || 0) + " " + (e.args.data && e.args.data.functionName || ""));
     });
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-streamed-cpu-profile.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-streamed-cpu-profile.html
index 2f64c89..8563e67 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-streamed-cpu-profile.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-streamed-cpu-profile.html
@@ -158,8 +158,8 @@
         }
     }];
 
-    var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents);
-    var events = tracingTimelineModel.mainThreadEvents();
+    var model = InspectorTest.createPerformanceModelWithEvents(rawTraceEvents);
+    var events = model.timelineModel().mainThreadEvents();
     events.filter(e => e.name === "JSFrame").forEach(e => {
         InspectorTest.addResult(`${e.name}: ${e.startTime.toFixed(3)} / ${(e.duration || 0).toFixed(3)} ${e.args.data.functionName}`);
     });
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-microtasks.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-microtasks.html
index 21dcde0..49d8a8e 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-microtasks.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-microtasks.html
@@ -24,12 +24,11 @@
 
 function test()
 {
-    var model = UI.panels.timeline._model;
     InspectorTest.invokeAsyncWithTimeline("performActions", finish);
 
     function finish()
     {
-        var event = model.mainThreadEvents().find(e => e.name === TimelineModel.TimelineModel.RecordType.RunMicrotasks);
+        var event = InspectorTest.timelineModel().mainThreadEvents().find(e => e.name === TimelineModel.TimelineModel.RecordType.RunMicrotasks);
         InspectorTest.printTraceEventProperties(event);
         InspectorTest.completeTest();
     }
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-open-function-call.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-open-function-call.html
index d034006..99524b3 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-open-function-call.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-open-function-call.html
@@ -61,8 +61,8 @@
         "args": {}
     }];
 
-    var model = InspectorTest.createTimelineModelWithEvents(rawTraceEvents);
-    var event = model.mainThreadEvents().find(e => e.name === TimelineModel.TimelineModel.RecordType.FunctionCall);
+    var model = InspectorTest.createPerformanceModelWithEvents(rawTraceEvents);
+    var event = model.timelineModel().mainThreadEvents().find(e => e.name === TimelineModel.TimelineModel.RecordType.FunctionCall);
     InspectorTest.addResult(`${event.startTime} ${event.endTime}`);
     InspectorTest.completeTest();
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-runtime-stats.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-runtime-stats.html
index e9773779..01242e61 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-runtime-stats.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-runtime-stats.html
@@ -15,12 +15,11 @@
 {
     Runtime.experiments.enableForTest("timelineV8RuntimeCallStats");
     Runtime.experiments.enableForTest("timelineShowAllEvents");
-    var model = UI.panels.timeline._model;
     InspectorTest.evaluateWithTimeline("performActions()", finish);
 
     function finish()
     {
-        var frame = model.mainThreadEvents()
+        var frame = InspectorTest.timelineModel().mainThreadEvents()
             .filter(e => e.name === TimelineModel.TimelineModel.RecordType.JSFrame)
             .map(e => e.args["data"]["callFrame"])
             .find(frame => frame.functionName === "FunctionCallback" && frame.url === "native V8Runtime");
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details.html
index 140e339..ed5da41 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details.html
@@ -594,7 +594,7 @@
     ];
 
     var timeline = UI.panels.timeline;
-    InspectorTest.setTraceEvents(InspectorTest.timelineModel(), InspectorTest.tracingModel(), rawTraceEvents);
+    timeline._setModel(InspectorTest.createPerformanceModelWithEvents(rawTraceEvents));
 
     timeline.requestWindowTimes(0, Infinity);
     var groupByEnum = Timeline.AggregatedTimelineTreeView.GroupBy;
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom.html
index dab3117..d79aa77 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom.html
@@ -33,7 +33,8 @@
         {"name": "FunctionCall", "ts": 6000000, "dur":  1000, "ph": "X", args: {},  "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}
     ];
 
-    InspectorTest.setTraceEvents(InspectorTest.timelineModel(), InspectorTest.tracingModel(), traceEvents);
+    UI.panels.timeline._setModel(InspectorTest.createPerformanceModelWithEvents(traceEvents));
+
     var overview = UI.panels.timeline._overviewPane;
     var startTime = overview._windowStartTime;
     var endTime = overview._windowEndTime;
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
index 1c4700801..13c4cc56 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
@@ -51,9 +51,10 @@
     ];
 
 
-    var model = InspectorTest.createTimelineModelWithEvents(testData);
-    var view = new Timeline.EventsTimelineTreeView(model, UI.panels.timeline._filters, null);
-    view.updateContents(Timeline.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime()));
+    var model = InspectorTest.createPerformanceModelWithEvents(testData);
+    var view = new Timeline.EventsTimelineTreeView(UI.panels.timeline._filters, null);
+    view.setModel(model);
+    view.updateContents(Timeline.TimelineSelection.fromRange(model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime()));
     var filtersControl = view._filtersControl;
     function printEventMessage(event, level)
     {
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model.html
index d72855c..1845301 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model.html
@@ -51,8 +51,8 @@
         {"name": "Program", "ts": 2009999, "ph": "E", args: {},  "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}
     ];
 
-    var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(commonMetadata.concat(traceEvents));
-    InspectorTest.forAllEvents(tracingTimelineModel.mainThreadEvents(), (event, stack) => {
+    var tracingTimelineModel = InspectorTest.createPerformanceModelWithEvents(commonMetadata.concat(traceEvents));
+    InspectorTest.forAllEvents(tracingTimelineModel.timelineModel().mainThreadEvents(), (event, stack) => {
         const prefix = Array(stack.length + 1).join("----") + (stack.length ? "> " : "");
         const details = Timeline.TimelineUIUtils.buildDetailsTextForTraceEvent(event, null) || "";
         InspectorTest.addResult(`${prefix}${event.name}: ${details}`);
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference.html
index 4155580..94f8399 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference.html
@@ -27,8 +27,8 @@
 
     function clickValueLink(event, row)
     {
-        var panel = UI.panels.timeline;
-        Timeline.TimelineUIUtils.buildTraceEventDetails(event, panel._model, new Components.Linkifier(), true, onDetailsContentReady);
+        var model = UI.panels.timeline._performanceModel.timelineModel();
+        Timeline.TimelineUIUtils.buildTraceEventDetails(event, model, new Components.Linkifier(), true, onDetailsContentReady);
 
         function onDetailsContentReady(element)
         {
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-range-stats.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-range-stats.html
index 96c5271..96018ee8 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-range-stats.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-range-stats.html
@@ -23,7 +23,7 @@
         {"cat": "disabled-by-default-devtools.timeline", "name": "Layout", "ph": "X", "ts": 107000,"dur":1000, "tid": mainThread, "pid": pid, args:{beginData:{}, endData:{}}},
     ];
 
-    var timelineModel = InspectorTest.createTimelineModelWithEvents(testData);
+    var timelineModel = InspectorTest.createPerformanceModelWithEvents(testData).timelineModel();
     for (var startTime = 100000; startTime <= 109000; startTime += 1000) {
         for (var endTime = startTime + 1000; endTime <= 109000; endTime += 1000) {
             dumpStats(startTime, endTime, Timeline.TimelineUIUtils.statsForTimeRange(timelineModel, startTime / 1000, endTime / 1000));
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter.html
index 945e2919..99ae408c 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter.html
@@ -12,8 +12,6 @@
 
     InspectorTest.loadTimeline(InspectorTest.timelineData());
 
-    timeline._currentViews[0].refreshRecords();
-
     overviewPane._update();
     InspectorTest.addResult("OverviewPane:");
     overviewPane._overviewCalculator.setDisplayWidth(450);
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details.html
index 6ca26e0..8edd25c 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details.html
@@ -20,12 +20,11 @@
 
 function test()
 {
-    var model = UI.panels.timeline._model;
-
     InspectorTest.invokeAsyncWithTimeline("performActions", finish);
 
     function finish()
     {
+        var model = InspectorTest.timelineModel();
         var linkifier = new Components.Linkifier();
         function printRequestDetails(request)
         {
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.html
index e989d68..02ade60 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.html
@@ -20,12 +20,11 @@
     var requestId;
     var scriptUrl = "timeline-network-resource.js";
 
-    var model = UI.panels.timeline._model;
-
     InspectorTest.invokeAsyncWithTimeline("performActions", finish);
 
     function finish()
     {
+        var model = InspectorTest.timelineModel();
         model.mainThreadEvents().forEach(event => {
             if (event.name === TimelineModel.TimelineModel.RecordType.ResourceSendRequest)
                 printSend(event);
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/trace-event-self-time.html b/third_party/WebKit/LayoutTests/inspector/tracing/trace-event-self-time.html
index 50e39ed..0495e7b 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/trace-event-self-time.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/trace-event-self-time.html
@@ -290,7 +290,7 @@
     timelineController._addCpuProfile(SDK.targetManager.mainTarget().id(), null, cpuProfile);
     timelineController.traceEventsCollected(rawTraceEvents);
     timelineController._allSourcesFinished();
-    var events = InspectorTest.timelineModel().inspectedTargetEvents();
+    var events = timelineController._performanceModel.timelineModel().inspectedTargetEvents();
     events.forEach(e => InspectorTest.addResult(`${e.name}: ${e.startTime} ${(e.selfTime || 0).toFixed(2)}/${(e.duration || 0).toFixed(2)}`));
     InspectorTest.completeTest();
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load-expected.txt
index de7aae83..9d1fa2a 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load-expected.txt
@@ -2,29 +2,29 @@
 
 
 Running: testNormal
-TimelineLifecycleDelegate.loadingStarted()
-TimelineLifecycleDelegate.loadingProgress()
-TimelineLifecycleDelegate.loadingComplete(true)
+TimelineLoaderClient.loadingStarted()
+TimelineLoaderClient.loadingProgress()
+TimelineLoaderClient.loadingComplete(true)
 Saved data is equal to restored data: true
 
 Running: testJSONObjectFormat
-TimelineLifecycleDelegate.loadingStarted()
-TimelineLifecycleDelegate.loadingProgress()
-TimelineLifecycleDelegate.loadingComplete(true)
+TimelineLoaderClient.loadingStarted()
+TimelineLoaderClient.loadingProgress()
+TimelineLoaderClient.loadingComplete(true)
 Saved data is equal to restored data: true
 
 Running: testJSONObjectFormatWithMetadata
-TimelineLifecycleDelegate.loadingStarted()
-TimelineLifecycleDelegate.loadingProgress()
-TimelineLifecycleDelegate.loadingComplete(true)
+TimelineLoaderClient.loadingStarted()
+TimelineLoaderClient.loadingProgress()
+TimelineLoaderClient.loadingComplete(true)
 Saved data is equal to restored data: true
 
 Running: testBroken
-TimelineLifecycleDelegate.loadingStarted()
-TimelineLifecycleDelegate.loadingComplete(true)
+TimelineLoaderClient.loadingStarted()
+TimelineLoaderClient.loadingComplete(true)
 Model is empty: true
 
 Running: testMalformedJSON
-TimelineLifecycleDelegate.loadingComplete(false)
+TimelineLoaderClient.loadingComplete(false)
 Model is empty: true
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load.html b/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load.html
index 40df4ae..c2b44b4 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/tracing-timeline-load.html
@@ -6,31 +6,29 @@
 
 function test()
 {
-    InspectorTest.TestTimelineLifecycleDelegate = function() {}
+    InspectorTest.TestTimelineLoaderClient = function() {}
 
-    InspectorTest.TestTimelineLifecycleDelegate.prototype = {
+    InspectorTest.TestTimelineLoaderClient.prototype = {
         loadingStarted: function()
         {
-            InspectorTest.addResult("TimelineLifecycleDelegate.loadingStarted()");
+            InspectorTest.addResult("TimelineLoaderClient.loadingStarted()");
         },
 
         loadingProgress: function()
         {
-            InspectorTest.addResult("TimelineLifecycleDelegate.loadingProgress()");
+            InspectorTest.addResult("TimelineLoaderClient.loadingProgress()");
         },
 
-        loadingComplete: function(success)
+        loadingComplete: function(model, storage)
         {
-            InspectorTest.addResult(`TimelineLifecycleDelegate.loadingComplete(${success})`);
+            this.model = model;
+            this.storage = storage;
+            InspectorTest.addResult(`TimelineLoaderClient.loadingComplete(${!!model})`);
         },
     }
 
     function runTestWithDataAndCheck(input, expectedOutput, callback)
     {
-        var model = InspectorTest.tracingModel();
-        model.reset();
-        var timeline = UI.panels.timeline;
-
         function createFileReader(file, delegate)
         {
             return new InspectorTest.FakeFileReader(input, delegate, () => {});
@@ -44,21 +42,17 @@
         }
 
         InspectorTest.override(Timeline.TimelineLoader, "_createFileReader", createFileReader);
-        Timeline.TimelineLoader.loadFromFile(model, {}, new InspectorTest.TestTimelineLifecycleDelegate());
+        var delegate = new InspectorTest.TestTimelineLoaderClient();
+        Timeline.TimelineLoader.loadFromFile({}, delegate);
 
         var saver = new Timeline.TracingTimelineSaver();
         var stream = new InspectorTest.StringOutputStream(InspectorTest.safeWrap(checkSaveData));
-        var storage = timeline._tracingModelBackingStorage;
+        var storage = delegate.storage;
         stream.open("", storage.writeToStream.bind(storage, stream, saver));
     }
 
     function runTestOnMalformedInput(input, callback)
     {
-        var model = InspectorTest.tracingModel();
-        var timeline = UI.panels.timeline;
-
-        model.reset();
-
         function createFileReader(file, delegate)
         {
             return new InspectorTest.FakeFileReader(input, delegate, checkLoadedData);
@@ -66,12 +60,14 @@
 
         function checkLoadedData(data)
         {
-            InspectorTest.addResult("Model is empty: " + (!model.minimumRecordTime() && !model.maximumRecordTime()));
+            var model = delegate.model;
+            InspectorTest.addResult("Model is empty: " + (!model || (!model.minimumRecordTime() && !model.maximumRecordTime())));
             callback();
         }
 
         InspectorTest.override(Timeline.TimelineLoader, "_createFileReader", createFileReader);
-        Timeline.TimelineLoader.loadFromFile(model, {}, new InspectorTest.TestTimelineLifecycleDelegate());
+        var delegate = new InspectorTest.TestTimelineLoaderClient();
+        Timeline.TimelineLoader.loadFromFile({}, delegate);
     }
 
     var data = [{"args":{"number":32},"cat":"__metadata","name":"num_cpus","ph":"M","pid":32127,"tid":0,"ts":0},
diff --git a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html
index 8f132b20..9a3fca1 100644
--- a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html
+++ b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html
@@ -245,39 +245,45 @@
             }, 'Space at end of codecs parameter');
 
             // contentType is not case sensitive (except the codec names).
+            // From RFC 2045: "All media type values, subtype values, and
+            // parameter names as defined are case-insensitive.  However,
+            // parameter values are case-sensitive unless otherwise specified
+            // for the specific parameter."
             expect_config('org.w3.clearkey', [{
                 videoCapabilities: [{contentType: 'Video/webm; codecs="vp8"'}],
             }], {
                 videoCapabilities: [{contentType: 'Video/webm; codecs="vp8"'}],
-            }, 'Video/webm');
+            }, 'Media type value is case-insensitive');
 
             expect_config('org.w3.clearkey', [{
                 videoCapabilities: [{contentType: 'video/Webm; codecs="vp8"'}],
             }], {
                 videoCapabilities: [{contentType: 'video/Webm; codecs="vp8"'}],
-            }, 'video/Webm');
-
-            expect_config('org.w3.clearkey', [{
-                videoCapabilities: [{contentType: 'video/webm; Codecs="vp8"'}],
-            }], {
-                videoCapabilities: [{contentType: 'video/webm; Codecs="vp8"'}],
-            }, 'Codecs=');
+            }, 'Media subtype value is case-insensitive');
 
             expect_config('org.w3.clearkey', [{
                 videoCapabilities: [{contentType: 'VIDEO/WEBM; codecs="vp8"'}],
             }], {
                 videoCapabilities: [{contentType: 'VIDEO/WEBM; codecs="vp8"'}],
-            }, 'VIDEO/WEBM');
+            }, 'Media type values and subtype values are case-insensitive');
 
             expect_config('org.w3.clearkey', [{
                 videoCapabilities: [{contentType: 'video/webm; CODECS="vp8"'}],
             }], {
                 videoCapabilities: [{contentType: 'video/webm; CODECS="vp8"'}],
-            }, 'CODECS=');
+            }, 'Media parameter name is case-insensitive');
+
+            expect_error('org.w3.clearkey', [{
+                videoCapabilities: [{contentType: 'video/webm; CODECS="foo"'}],
+            }], 'NotSupportedError', 'Unsupported codec');
+
+            expect_error('org.w3.clearkey', [{
+                videoCapabilities: [{contentType: 'video/webm; codecs="VP8"'}],
+            }], 'NotSupportedError', 'Codec is case-sensitive');
 
             // Unrecognized attributes are not allowed.
             // TODO(jrummell): Unrecognized attributes are ignored currently.
-            // http://crbug.com/449690
+            // http://crbug.com/690131
 //          expect_error('org.w3.clearkey', [{
 //              videoCapabilities: [{contentType: 'video/webm; foo="bar"'}],
 //          }], 'NotSupportedError', 'Unrecognized foo');
diff --git a/third_party/WebKit/LayoutTests/media/mediasession/mediasession-playbackstate-expected.txt b/third_party/WebKit/LayoutTests/media/mediasession/mediasession-playbackstate-expected.txt
deleted file mode 100644
index 8886ddb..0000000
--- a/third_party/WebKit/LayoutTests/media/mediasession/mediasession-playbackstate-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CONSOLE WARNING: line 22: The provided value 'invalid' is not a valid enum value of type MediaSessionPlaybackState.
-CONSOLE WARNING: line 22: The provided value '' is not a valid enum value of type MediaSessionPlaybackState.
-This is a testharness.js-based test.
-PASS Test that playbackState is initialized as "none" 
-PASS Test that playbackState is read/write 
-PASS Test that warning is thrown when setting invalid playbackState 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/media/mediasession/mediasession.html b/third_party/WebKit/LayoutTests/media/mediasession/mediasession.html
deleted file mode 100644
index 3fbc6257..0000000
--- a/third_party/WebKit/LayoutTests/media/mediasession/mediasession.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<title>MediaSession interface</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script>
-test(function() {
-  var metadata = new MediaMetadata({});
-  navigator.mediaSession.metadata = metadata;
-  assert_equals(navigator.mediaSession.metadata, metadata);
-}, "Test that mediaSession.metadata is properly set");
-
-test(function() {
-  var metadata = new MediaMetadata({});
-  navigator.mediaSession.metadata = metadata;
-  metadata.title = 'foo';
-  assert_equals(navigator.mediaSession.metadata.title, 'foo');
-}, "Test that changes to metadata propagate properly");
-
-test(function() {
-  var metadata = new MediaMetadata({});
-  navigator.mediaSession.metadata = metadata;
-  navigator.mediaSession.metadata = null;
-  assert_equals(navigator.mediaSession.metadata, null);
-}, "Test that resetting metadata to null is reflected");
-</script>
diff --git a/third_party/WebKit/LayoutTests/media/mediasession/mediasessionmetadata.html b/third_party/WebKit/LayoutTests/media/mediasession/mediasessionmetadata.html
deleted file mode 100644
index 90a54dd..0000000
--- a/third_party/WebKit/LayoutTests/media/mediasession/mediasessionmetadata.html
+++ /dev/null
@@ -1,172 +0,0 @@
-<!DOCTYPE html>
-<title>MediaMetadata interface</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script>
-
-  test(function() {
-    var metadata = new MediaMetadata({});
-    assert_not_equals(metadata, null);
-
-    assert_throws(new TypeError(), _ => new MediaMetadata('foobar'));
-    assert_throws(new TypeError(), _ => new MediaMetadata(42));
-  }, 'Test that MediaMetadata is constructed using a dictionary');
-
-  test(function() {
-    var metadata = new MediaMetadata();
-    assert_not_equals(metadata, null);
-  }, "Test that MediaMetadata constructor can take no parameter");
-
-  test(function() {
-    var image1 = { src: 'http://example.com/1', sizes: 'sizes1', type: 'type1' };
-    var image2 = { src: 'http://example.com/2', sizes: 'sizes2', type: 'type2' };
-    var metadata = new MediaMetadata({
-        title: 'foo', album: 'bar', artist: 'plop', artwork: [ image1, image2 ]
-    });
-
-    assert_equals(metadata.title, 'foo');
-    assert_equals(metadata.album, 'bar');
-    assert_equals(metadata.artist, 'plop');
-    assert_equals(metadata.artwork.length, 2);
-    assert_equals(metadata.artwork[0].src, image1.src);
-    assert_equals(metadata.artwork[0].sizes, image1.sizes);
-    assert_equals(metadata.artwork[0].type, image1.type);
-    assert_equals(metadata.artwork[1].src, image2.src);
-    assert_equals(metadata.artwork[1].sizes, image2.sizes);
-    assert_equals(metadata.artwork[1].type, image2.type);
-  }, 'Test the different values allowed in MediaMetadata init dictionary');
-
-  test(function() {
-    var metadata = new MediaMetadata({});
-    assert_equals(metadata.title, '');
-    assert_equals(metadata.artist, '');
-    assert_equals(metadata.album, '');
-    assert_equals(0, metadata.artwork.length);
-  }, 'Test the default values for MediaMetadata with empty init dictionary');
-
-  test(function() {
-    var metadata = new MediaMetadata();
-    assert_equals(metadata.title, '');
-    assert_equals(metadata.artist, '');
-    assert_equals(metadata.album, '');
-    assert_equals(0, metadata.artwork.length);
-  }, 'Test the default values for MediaMetadata with no init dictionary');
-
-  test(function() {
-    var metadata = new MediaMetadata({ randomValueThatWillNotBeAdded: '... hopefully ;)' });
-    assert_equals(metadata.randomValueThatWillNotBeAdded, undefined);
-  }, 'Test that passing unknown values to the dictionary is a no-op');
-
-  test(function() {
-    var image1 = { src: 'http://example.com/1', sizes: 'sizes1', type: 'type1' };
-    var image2 = { src: 'http://example.com/2', sizes: 'sizes2', type: 'type2' };
-    var metadata = new MediaMetadata({
-      title: 'foo', album: 'bar', artist: 'plop', artwork: [ image1, image2 ]
-    });
-
-    metadata.title = 'something else';
-    assert_equals(metadata.title, 'something else');
-
-    metadata.album = 'other value';
-    assert_equals(metadata.album, 'other value');
-
-    metadata.artist = 'someone else';
-    assert_equals(metadata.artist, 'someone else');
-
-    var image = { src: 'http://example.com/', sizes: '40x40', type: 'image/png' };
-    metadata.artwork = [ image ];
-    assert_equals(metadata.artwork.length, 1);
-    assert_equals(metadata.artwork[0].src, 'http://example.com/');
-    assert_equals(metadata.artwork[0].sizes, '40x40');
-    assert_equals(metadata.artwork[0].type, 'image/png');
-  }, "Test that MediaMetadata is read/write");
-
-  test(function() {
-    var metadata = new MediaMetadata({ artwork: [ { src: 'http://foo.com/' } ] });
-    assert_throws(new TypeError(), _ => {
-      metadata.artwork.push({
-        src: 'http://example.com/', sizes: '40x40', type: 'image/png',
-      });
-    });
-
-    metadata.artwork[0].src = 'bar';
-    assert_equals(metadata.artwork[0].src, 'http://foo.com/');
-  }, "Test that MediaMetadat.artwork can't be modified");
-
-  test(function() {
-    var metadata = new MediaMetadata({ artwork: [{
-      src: 'http://example.com/', sizes: '40x40', type: 'image/png',
-      some_other_value: 'foo',
-    }]});
-    assert_equals(metadata.artwork[0].src, 'http://example.com/');
-    assert_equals(metadata.artwork[0].sizes, '40x40');
-    assert_equals(metadata.artwork[0].type, 'image/png');
-    assert_false('some_other_value' in metadata.artwork[0]);
-
-    metadata.artwork[0].something_else = 'bar';
-    assert_false('something_else' in metadata.artwork[0]);
-  }, "Test that MediaMetadata.artwork will not expose unknown properties");
-
-  test(function() {
-    var metadata = new MediaMetadata({ artwork: [
-      { src: 'http://example.com/1', sizes: '40x40', type: 'image/png' },
-      { src: 'http://example.com/2', sizes: '40x40', type: 'image/png' },
-    ]});
-
-    assert_true(Object.isFrozen(metadata.artwork));
-    for (var i = 0; i < metadata.artwork.length; ++i)
-      assert_true(Object.isFrozen(metadata.artwork[i]));
-  }, "Test that MediaMetadata.artwork is Frozen");
-
-  test(function() {
-    var metadata = new MediaMetadata({ artwork: [
-      { src: 'http://example.com', sizes: '40x40', type: 'image/png' },
-      { src: '../foo', sizes: '40x40', type: 'image/png' },
-      { src: '/foo/bar', sizes: '40x40', type: 'image/png' },
-    ]});
-
-    assert_equals(metadata.artwork[0].src, new URL('http://example.com', document.URL).href)
-    assert_equals(metadata.artwork[1].src, new URL('../foo', document.URL).href)
-    assert_equals(metadata.artwork[2].src, new URL('/foo/bar', document.URL).href)
-  }, "Test that MediaMetadata.artwork returns parsed urls");
-
-  test(function() {
-    var metadata = 42;
-
-    assert_throws(new TypeError(), _ => {
-      metadata
-        new MediaMetadata({ artwork: [ { src: 'http://[example.com]' }] });
-    });
-    assert_equals(metadata, 42);
-
-    metadata = new MediaMetadata();
-    assert_throws(new TypeError(), _ => {
-      metadata.artwork = [
-        // Valid url.
-        { src: 'http://example.com' },
-        // Invalid url.
-        { src: 'http://example.com:demo' },
-      ];
-    });
-    assert_equals(metadata.artwork.length, 0);
-
-  }, "Test that MediaMetadata throws when setting an invalid url");
-
-  test(function() {
-    var metadata = new MediaMetadata({ artwork: [ { src: 'foo.jpg' } ] });
-    assert_equals(metadata.artwork[0].type, '');
-    assert_equals(metadata.artwork[0].sizes, '');
-  }, "Test MediaImage default values");
-
-  test(function() {
-    assert_throws(new TypeError(), _ => {
-      new MediaMetadata({ artwork: [ {} ] });
-    });
-
-    var metadata = new MediaMetadata();
-    assert_throws(new TypeError(), _ => {
-      metadata.artwork = [ { type: 'image/png', sizes: '40x40' } ];
-    });
-  }, "Test that MediaImage.src is required")
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/media/mediasession/navigator-mediasession.html b/third_party/WebKit/LayoutTests/media/mediasession/navigator-mediasession.html
deleted file mode 100644
index 607374bd8..0000000
--- a/third_party/WebKit/LayoutTests/media/mediasession/navigator-mediasession.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<title>Navigator MediaSession Test</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script>
-
-test(function() {
-  assert_true(window.navigator.mediaSession instanceof MediaSession);
-});
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/media/track/regions-webvtt/vtt-region-list.html b/third_party/WebKit/LayoutTests/media/track/regions-webvtt/vtt-region-list.html
deleted file mode 100644
index a3cc48e..0000000
--- a/third_party/WebKit/LayoutTests/media/track/regions-webvtt/vtt-region-list.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<title>Tests VTTRegionList functionality: length, operator[], and getRegionById().</title>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-test(function() {
-    var testTrack = document.createElement('track');
-    
-    assert_equals(testTrack.track.mode, 'disabled');
-    assert_equals(testTrack.track.regions, null);
-
-    testTrack.track.mode = 'hidden';
-    var regions = testTrack.track.regions;
-
-    assert_true(regions instanceof VTTRegionList, 'instanceof');
-
-    assert_equals(regions.length, 0);
-
-    var region = new VTTRegion();
-    region.id = 'TestId';
-
-    assert_equals(region.track, null);
-
-    testTrack.track.addRegion(region);
-
-    assert_equals(regions.length, 1);
-    assert_equals(regions[0], region);
-    assert_equals(regions[0].track, testTrack.track);
-
-    assert_equals(region.track, testTrack.track);
-
-    var updatedRegion = new VTTRegion();
-    updatedRegion.id = region.id;
-    updatedRegion.viewportAnchorX = 59;
-    updatedRegion.viewportAnchorY = 68;
-    updatedRegion.regionAnchorX = 20;
-    updatedRegion.regionAnchorY = 30;
-    updatedRegion.height = 5;
-    updatedRegion.width = 87;
-    updatedRegion.scroll = 'up';
-
-    testTrack.track.addRegion(updatedRegion);
-    assert_equals(regions[0].viewportAnchorX, updatedRegion.viewportAnchorX);
-    assert_equals(regions[0].viewportAnchorY, updatedRegion.viewportAnchorY);
-    assert_equals(regions[0].regionAnchorX, updatedRegion.regionAnchorX);
-    assert_equals(regions[0].regionAnchorY, updatedRegion.regionAnchorY);
-    assert_equals(regions[0].height, updatedRegion.height);
-    assert_equals(regions[0].width, updatedRegion.width);
-    assert_equals(regions[0].scroll, updatedRegion.scroll);
-
-    assert_not_equals(regions[0], updatedRegion);
-
-    testTrack.track.addRegion(region);
-    assert_equals(regions.length, 1);
-    testTrack.track.removeRegion(region);
-    assert_equals(regions.length, 0);
-
-    assert_throws('NotFoundError', function() { testTrack.track.removeRegion(region); });
-
-    // FIXME(109818): Update test for multiple initial regions (after parsing is supported).
-});
-</script>
-</html>
diff --git a/third_party/WebKit/LayoutTests/mojo/message-pipe.html b/third_party/WebKit/LayoutTests/mojo/message-pipe.html
new file mode 100644
index 0000000..a8e51b7f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/mojo/message-pipe.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<title>Mojo message pipe tests</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+
+let testData = (() => {
+  let dataIn = new Uint8Array(42);
+  for (let i = 0; i < dataIn.length; ++i)
+    dataIn[i] = i * i;
+
+  return {
+    read(handle) {
+      let {result, buffer, handles} = handle.readMessage();
+      assert_equals(result, Mojo.RESULT_OK);
+      assert_array_equals(new Uint8Array(buffer), dataIn);
+      assert_array_equals(handles, []);
+    },
+    write(handle) {
+      let result = handle.writeMessage(dataIn, []);
+      assert_equals(result, Mojo.RESULT_OK);
+    }
+  };
+})();
+
+test(() => {
+  let {result, handle0, handle1} = Mojo.createMessagePipe();
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_true(handle0 instanceof MojoHandle);
+  assert_true(handle1 instanceof MojoHandle);
+}, "Create pipe");
+
+test(() => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+  handle0.close();
+  let {result} = handle0.readMessage();
+  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
+}, "Read from invalid handle");
+
+test(() => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+  let {result} = handle0.readMessage();
+  assert_equals(result, Mojo.RESULT_SHOULD_WAIT);
+}, "Read from empty pipe");
+
+test(() => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+  handle0.close();
+  let result = handle0.writeMessage(new ArrayBuffer(4), []);
+  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
+}, "Write to invalid handle");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    {
+      let {result, buffer, handles} = handle0.readMessage();
+      assert_equals(result, Mojo.RESULT_OK);
+      assert_equals(buffer, undefined);
+      assert_equals(handles, undefined);
+    }
+  }));
+  let result = handle1.writeMessage(new ArrayBuffer(0), []);
+  assert_equals(result, Mojo.RESULT_OK);
+}, "Send empty message");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    testData.read(handle0);
+  }));
+  testData.write(handle1);
+}, "Send buffer");
+
+async_test((test) => {
+  let pipe1 = Mojo.createMessagePipe();
+  let pipe2 = Mojo.createMessagePipe();
+  pipe2.handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    testData.read(pipe2.handle0);
+  }));
+  pipe1.handle0.watch({readable: true}, test.step_func((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    {
+      let {result, handles} = pipe1.handle0.readMessage();
+      assert_equals(result, Mojo.RESULT_OK);
+      assert_equals(1, handles.length);
+      testData.write(handles[0]);
+    }
+  }));
+  pipe1.handle1.writeMessage(new ArrayBuffer(0), [pipe2.handle1]);
+}, "Send handle");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/mojo/watch.html b/third_party/WebKit/LayoutTests/mojo/watch.html
new file mode 100644
index 0000000..3a0eb377
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/mojo/watch.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>mojo watch tests</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+  }));
+  handle1.writeMessage(new ArrayBuffer(4), []);
+}, "Watch handle readable");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({writable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+  }));
+}, "Watch handle writable");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({peerClosed: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+  }));
+  handle1.close();
+}, "Watch handle peer closed");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.close();
+  handle0.watch({writable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
+  }));
+}, "Watch invalid handle");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_FAILED_PRECONDITION);
+  }));
+}, "Watch with default MojoHandleSignals");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  let watcher = handle0.watch(
+      {writable: true},
+      test.unreached_func("callback triggered after canceling watch"));
+  watcher.cancel();
+  setTimeout(() => { test.done(); });
+}, "Cancel watch");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.html
new file mode 100644
index 0000000..bab878a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline-expected.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<div style="opacity: 0.9; width: 100px; height: 100px; background: green"></div>
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline.html b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline.html
new file mode 100644
index 0000000..1bf6553a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/column-float-under-stacked-inline.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<span style="opacity: 0.9">
+  <div style="columns: 1; float: left">
+    <div id="target" style="width: 100px; height: 100px; background: red"></div>
+  <div style="position: relative"></div>
+</span>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+runAfterLayoutAndPaint(function() {
+  target.style.background = 'green';
+}, true);
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.html
index 013c379..6c8da19 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.html
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.html
@@ -11,8 +11,14 @@
     <tr>
         <td>
             <div id="target"></div>
+            <div id="dummy"></div>
         </td>
     </tr>
 </table>
 </body>
 </html>
+<!-- crbug.com/690087: We do this to force a two-pass layout so that we get the same height on the table as the reference. -->
+<script>
+  document.body.offsetTop;
+  document.getElementById("dummy").style.display = "none";
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.txt
index a3de9dc..f4575e4d 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/table-two-pass-layout-overpaint-expected.txt
@@ -7,17 +7,40 @@
       "drawsContent": true,
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow DIV id='target'",
-          "rect": [61, 44, 50, 25],
+          "object": "LayoutTable TABLE",
+          "rect": [8, 106, 106, 1],
           "reason": "incremental"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [10, 104, 102, 1],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [11, 45, 100, 25],
+          "reason": "bounds change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [11, 44, 50, 25],
+          "reason": "bounds change"
         }
       ]
     }
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow DIV id='target'",
+      "object": "LayoutTable TABLE",
       "reason": "incremental"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "bounds change"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-expected.png
index f7fca15..9b7e665 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/transitions/scale-transition-no-start-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-expected.png
index f055f6c..39f4517 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-hidpi-expected.png
index 047c9ec5..9a26e4c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/grammar-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
index bbb5238..0f41004 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-expected.png
index 482a512..63d0860 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline-spelling-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline_spelling_markers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline_spelling_markers-expected.png
index 940ba311..3b05382 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline_spelling_markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/spelling/inline_spelling_markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
similarity index 78%
rename from third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
rename to third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
index 7d3b5772..0f995cd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details.
 CONSOLE ERROR: Not allowed to load local resource: script%3E
 This is a testharness.js-based test.
 PASS Set HTTP URL frame location.protocol to x 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
similarity index 64%
rename from third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
rename to third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
index 55fb444..274b1280 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details.
 This is a testharness.js-based test.
 PASS Set location.protocol to x 
 FAIL Set location.protocol to data Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame.
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-lr/007-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-lr/007-expected.png
index c3e88b4..0391b9b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-lr/007-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-lr/007-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-rl/007-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-rl/007-expected.png
index 83dc4c1..6c198bee 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-rl/007-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/auto/vertical-rl/007-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-lr/001-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-lr/001-expected.png
index abeb1b7..b88dbca 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-lr/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-lr/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-rl/001-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-rl/001-expected.png
index 2c8124b..671096e7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-rl/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/block/positioning/vertical-rl/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
new file mode 100644
index 0000000..2b68df5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png
new file mode 100644
index 0000000..226ba76
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt
new file mode 100644
index 0000000..3511f48
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt
@@ -0,0 +1,581 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 682
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 785x682 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow {HTML} at (0,0) size 785x682
+    LayoutBlockFlow {BODY} at (8,8) size 769x666
+      LayoutBlockFlow (anonymous) at (0,0) size 769x333
+        LayoutText {#text} at (215,0) size 4x19
+          text run at (215,0) width 4: " "
+        LayoutText {#text} at (434,0) size 4x19
+          text run at (434,0) width 4: " "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (0,333) size 769x333
+        LayoutText {#text} at (215,0) size 4x19
+          text run at (215,0) width 4: " "
+        LayoutText {#text} at (434,0) size 4x19
+          text run at (434,0) width 4: " "
+        LayoutText {#text} at (0,0) size 0x0
+layer at (8,8) size 215x333
+  LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 215x333 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 91x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,2) size 0x19
+      LayoutBlockFlow {DIV} at (1,22) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,23) size 0x19
+      LayoutBlockFlow {DIV} at (1,43) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,44) size 0x19
+      LayoutBlockFlow {DIV} at (1,64) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,65) size 0x19
+      LayoutBlockFlow {DIV} at (1,85) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,86) size 0x19
+      LayoutBlockFlow {DIV} at (1,106) size 89x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 87x19
+          LayoutText {#text} at (1,15) size 16x19
+            text run at (1,15) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 39x36
+            LayoutText {#text} at (17,2) size 39x36
+              text run at (17,2) width 39: "efg"
+          LayoutText {#text} at (56,15) size 32x19
+            text run at (56,15) width 32: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (90,121) size 0x19
+    LayoutBR {BR} at (94,124) size 0x19
+    LayoutBlockFlow {DIV} at (3,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,311) size 4x19
+      text run at (24,311) width 4: " "
+    LayoutBlockFlow {DIV} at (28,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,311) size 4x19
+      text run at (49,311) width 4: " "
+    LayoutBlockFlow {DIV} at (53,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,311) size 4x19
+      text run at (74,311) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,311) size 4x19
+      text run at (99,311) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,311) size 4x19
+      text run at (124,311) width 4: " "
+    LayoutBlockFlow {DIV} at (128,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (10,1) size 19x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 19x32
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,311) size 4x19
+      text run at (168,311) width 4: " "
+    LayoutBlockFlow {DIV} at (172,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (11,1) size 19x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 19x32
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (175,10) size 46x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (166.63,2) size 46.38x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 37x18
+      text run at (5,4) width 37: "initial"
+layer at (227,8) size 215x333
+  LayoutBlockFlow (relative positioned) {DIV} at (219,0) size 215x333 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 91x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,2) size 0x19
+      LayoutBlockFlow {DIV} at (1,22) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,23) size 0x19
+      LayoutBlockFlow {DIV} at (1,43) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,44) size 0x19
+      LayoutBlockFlow {DIV} at (1,64) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,65) size 0x19
+      LayoutBlockFlow {DIV} at (1,85) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,86) size 0x19
+      LayoutBlockFlow {DIV} at (1,106) size 89x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 87x19
+          LayoutText {#text} at (1,15) size 16x19
+            text run at (1,15) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 39x36
+            LayoutText {#text} at (17,2) size 39x36
+              text run at (17,2) width 39: "efg"
+          LayoutText {#text} at (56,15) size 32x19
+            text run at (56,15) width 32: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (90,121) size 0x19
+    LayoutBR {BR} at (94,124) size 0x19
+    LayoutBlockFlow {DIV} at (3,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,311) size 4x19
+      text run at (24,311) width 4: " "
+    LayoutBlockFlow {DIV} at (28,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,311) size 4x19
+      text run at (49,311) width 4: " "
+    LayoutBlockFlow {DIV} at (53,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,311) size 4x19
+      text run at (74,311) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,311) size 4x19
+      text run at (99,311) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,311) size 4x19
+      text run at (124,311) width 4: " "
+    LayoutBlockFlow {DIV} at (128,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (10,1) size 19x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 19x32
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,311) size 4x19
+      text run at (168,311) width 4: " "
+    LayoutBlockFlow {DIV} at (172,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (11,1) size 19x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 19x32
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (377,10) size 63x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (149.63,2) size 63.38x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 54x18
+      text run at (5,4) width 54: "lang=zh"
+layer at (446,8) size 215x333
+  LayoutBlockFlow (relative positioned) {DIV} at (438,0) size 215x333 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 91x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,2) size 0x19
+      LayoutBlockFlow {DIV} at (1,22) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,23) size 0x19
+      LayoutBlockFlow {DIV} at (1,43) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,44) size 0x19
+      LayoutBlockFlow {DIV} at (1,64) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,65) size 0x19
+      LayoutBlockFlow {DIV} at (1,85) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,86) size 0x19
+      LayoutBlockFlow {DIV} at (1,106) size 89x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 87x19
+          LayoutText {#text} at (1,15) size 16x19
+            text run at (1,15) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 39x36
+            LayoutText {#text} at (17,2) size 39x36
+              text run at (17,2) width 39: "efg"
+          LayoutText {#text} at (56,15) size 32x19
+            text run at (56,15) width 32: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (90,121) size 0x19
+    LayoutBR {BR} at (94,124) size 0x19
+    LayoutBlockFlow {DIV} at (3,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,311) size 4x19
+      text run at (24,311) width 4: " "
+    LayoutBlockFlow {DIV} at (28,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,311) size 4x19
+      text run at (49,311) width 4: " "
+    LayoutBlockFlow {DIV} at (53,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,311) size 4x19
+      text run at (74,311) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,311) size 4x19
+      text run at (99,311) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,311) size 4x19
+      text run at (124,311) width 4: " "
+    LayoutBlockFlow {DIV} at (128,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (10,1) size 19x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 19x32
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,311) size 4x19
+      text run at (168,311) width 4: " "
+    LayoutBlockFlow {DIV} at (172,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (11,1) size 19x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 19x32
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (599,10) size 60x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (152.63,2) size 60.38x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 51x18
+      text run at (5,4) width 51: "lang=ja"
+layer at (8,341) size 215x333 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 215x333 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 91x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,2) size 0x19
+      LayoutBlockFlow {DIV} at (1,22) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,23) size 0x19
+      LayoutBlockFlow {DIV} at (1,43) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,44) size 0x19
+      LayoutBlockFlow {DIV} at (1,64) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,65) size 0x19
+      LayoutBlockFlow {DIV} at (1,85) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,86) size 0x19
+      LayoutBlockFlow {DIV} at (1,106) size 89x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 87x19
+          LayoutText {#text} at (1,15) size 16x19
+            text run at (1,15) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 39x36
+            LayoutText {#text} at (17,2) size 39x36
+              text run at (17,2) width 39: "efg"
+          LayoutText {#text} at (56,15) size 32x19
+            text run at (56,15) width 32: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (90,121) size 0x19
+    LayoutBR {BR} at (94,124) size 0x19
+    LayoutBlockFlow {DIV} at (3,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,311) size 4x19
+      text run at (24,311) width 4: " "
+    LayoutBlockFlow {DIV} at (28,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,311) size 4x19
+      text run at (49,311) width 4: " "
+    LayoutBlockFlow {DIV} at (53,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,311) size 4x19
+      text run at (74,311) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,311) size 4x19
+      text run at (99,311) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,311) size 4x19
+      text run at (124,311) width 4: " "
+    LayoutBlockFlow {DIV} at (128,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (10,1) size 19x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 19x32
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,311) size 4x19
+      text run at (168,311) width 4: " "
+    LayoutBlockFlow {DIV} at (172,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (11,1) size 19x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 19x32
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (172,343) size 49x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (163.63,2) size 49.38x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 40x18
+      text run at (5,4) width 40: "under"
+layer at (227,341) size 215x333 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow (relative positioned) {DIV} at (219,0) size 215x333 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 91x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,2) size 0x19
+      LayoutBlockFlow {DIV} at (1,22) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,23) size 0x19
+      LayoutBlockFlow {DIV} at (1,43) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,44) size 0x19
+      LayoutBlockFlow {DIV} at (1,64) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,65) size 0x19
+      LayoutBlockFlow {DIV} at (1,85) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,86) size 0x19
+      LayoutBlockFlow {DIV} at (1,106) size 89x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 87x19
+          LayoutText {#text} at (1,15) size 16x19
+            text run at (1,15) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 39x36
+            LayoutText {#text} at (17,2) size 39x36
+              text run at (17,2) width 39: "efg"
+          LayoutText {#text} at (56,15) size 32x19
+            text run at (56,15) width 32: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (90,121) size 0x19
+    LayoutBR {BR} at (94,124) size 0x19
+    LayoutBlockFlow {DIV} at (3,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,311) size 4x19
+      text run at (24,311) width 4: " "
+    LayoutBlockFlow {DIV} at (28,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,311) size 4x19
+      text run at (49,311) width 4: " "
+    LayoutBlockFlow {DIV} at (53,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,311) size 4x19
+      text run at (74,311) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,311) size 4x19
+      text run at (99,311) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,311) size 4x19
+      text run at (124,311) width 4: " "
+    LayoutBlockFlow {DIV} at (128,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (10,1) size 19x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 19x32
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,311) size 4x19
+      text run at (168,311) width 4: " "
+    LayoutBlockFlow {DIV} at (172,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (11,1) size 19x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 19x32
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (372,343) size 68x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (144.63,2) size 68.38x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 59x18
+      text run at (5,4) width 59: "under zh"
+layer at (446,341) size 215x333 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow (relative positioned) {DIV} at (438,0) size 215x333 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 91x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,2) size 0x19
+      LayoutBlockFlow {DIV} at (1,22) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,23) size 0x19
+      LayoutBlockFlow {DIV} at (1,43) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,44) size 0x19
+      LayoutBlockFlow {DIV} at (1,64) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,65) size 0x19
+      LayoutBlockFlow {DIV} at (1,85) size 68x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 66x19
+          LayoutText {#text} at (1,1) size 66x19
+            text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (69,86) size 0x19
+      LayoutBlockFlow {DIV} at (1,106) size 89x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 87x19
+          LayoutText {#text} at (1,15) size 16x19
+            text run at (1,15) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 39x36
+            LayoutText {#text} at (17,2) size 39x36
+              text run at (17,2) width 39: "efg"
+          LayoutText {#text} at (56,15) size 32x19
+            text run at (56,15) width 32: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (90,121) size 0x19
+    LayoutBR {BR} at (94,124) size 0x19
+    LayoutBlockFlow {DIV} at (3,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,311) size 4x19
+      text run at (24,311) width 4: " "
+    LayoutBlockFlow {DIV} at (28,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,311) size 4x19
+      text run at (49,311) width 4: " "
+    LayoutBlockFlow {DIV} at (53,258) size 21x68 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x66
+        LayoutText {#text} at (1,1) size 19x66
+          text run at (1,1) width 66: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,311) size 4x19
+      text run at (74,311) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,311) size 4x19
+      text run at (99,311) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x176 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x174
+        LayoutText {#text} at (1,1) size 19x174
+          text run at (1,1) width 174: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,311) size 4x19
+      text run at (124,311) width 4: " "
+    LayoutBlockFlow {DIV} at (128,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (10,1) size 19x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 19x32
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,311) size 4x19
+      text run at (168,311) width 4: " "
+    LayoutBlockFlow {DIV} at (172,218) size 40x108 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 19x106
+        LayoutText {#text} at (11,1) size 19x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x58
+          LayoutText {#text} at (2,17) size 36x58
+            text run at (2,17) width 58: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 19x32
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (594,343) size 65x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (147.63,2) size 65.38x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 56x18
+      text run at (5,4) width 56: "under ja"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/lists/002-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/lists/002-vertical-expected.png
index c6cc33ee..32d3525 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/lists/002-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/lists/002-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/lists/006-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/lists/006-vertical-expected.png
index 130ed6a..3cc0bced 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/lists/006-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/lists/006-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/border-collapsing/003-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/border-collapsing/003-vertical-expected.png
index 93d50ed..174cccb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/border-collapsing/003-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/border-collapsing/003-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/decorations-with-text-combine-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/decorations-with-text-combine-expected.png
index ddc641969..4c015cae 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/decorations-with-text-combine-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/decorations-with-text-combine-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-expected.png
index cdcff19..5ad8649 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-125-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-125-expected.png
index 228c788f..3edbc75 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-125-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-125-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-150-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-150-expected.png
index 24533a8..6943bf3c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-150-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-150-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-175-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-175-expected.png
index c97c851..e02e786 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-175-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-175-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-200-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-200-expected.png
index 4da49f0..b5e53dd 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-200-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-200-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-250-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-250-expected.png
index 3632e8cd..bc114d42e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-250-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/spellmarkers/document-markers-zoom-250-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
new file mode 100644
index 0000000..5cd5cb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index c9907e03..e85806ec 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/decorations-with-text-combine-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/decorations-with-text-combine-expected.png
index d651a2b0..08e5cc8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/decorations-with-text-combine-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/decorations-with-text-combine-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/transitions/scale-transition-no-start-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/transitions/scale-transition-no-start-expected.png
index aae222c..d8b394d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/transitions/scale-transition-no-start-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/transitions/scale-transition-no-start-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-expected.png
index 7b6ba864..349eb2a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-hidpi-expected.png
index 6efd2b7..d88b30d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/grammar-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
index 0bf53ce..02f6ae9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-expected.png
index 0bf53ce..02f6ae9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline-spelling-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline_spelling_markers-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline_spelling_markers-expected.png
index 648e961..a92a816 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline_spelling_markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/spelling/inline_spelling_markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
similarity index 78%
copy from third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
copy to third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
index 7d3b5772..0f995cd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details.
 CONSOLE ERROR: Not allowed to load local resource: script%3E
 This is a testharness.js-based test.
 PASS Set HTTP URL frame location.protocol to x 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
similarity index 64%
copy from third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
copy to third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
index 55fb444..274b1280 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details.
 This is a testharness.js-based test.
 PASS Set location.protocol to x 
 FAIL Set location.protocol to data Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame.
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-lr/007-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-lr/007-expected.png
index 42da02b7..d1f911d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-lr/007-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-lr/007-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-rl/007-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-rl/007-expected.png
index ac4850a..4b4cd3d7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-rl/007-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/auto/vertical-rl/007-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-lr/001-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-lr/001-expected.png
index 4c791444..a892cab08f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-lr/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-lr/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-rl/001-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-rl/001-expected.png
index 6ca78027..87fdc2a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-rl/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/block/positioning/vertical-rl/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-expected.png
index 1e09a94e..523e845 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-strict-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-strict-expected.png
index 1e09a94e..523e845 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/text-overflow-ellipsis-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png
new file mode 100644
index 0000000..413374f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt
new file mode 100644
index 0000000..36f4540
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt
@@ -0,0 +1,581 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 608
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 785x608 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow {HTML} at (0,0) size 785x608
+    LayoutBlockFlow {BODY} at (8,8) size 769x592
+      LayoutBlockFlow (anonymous) at (0,0) size 769x296
+        LayoutText {#text} at (215,0) size 4x18
+          text run at (215,0) width 4: " "
+        LayoutText {#text} at (434,0) size 4x18
+          text run at (434,0) width 4: " "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (0,296) size 769x296
+        LayoutText {#text} at (215,0) size 4x18
+          text run at (215,0) width 4: " "
+        LayoutText {#text} at (434,0) size 4x18
+          text run at (434,0) width 4: " "
+        LayoutText {#text} at (0,0) size 0x0
+layer at (8,8) size 215x296
+  LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 215x296 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,2) size 1x18
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,23) size 1x18
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,44) size 1x18
+      LayoutBlockFlow {DIV} at (1,64) size 73.13x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 72x16
+          LayoutText {#text} at (1,2) size 72x16
+            text run at (1,2) width 72: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,66) size 1x18
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,86) size 1x18
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x18
+          LayoutText {#text} at (1,16) size 16x18
+            text run at (1,16) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x37
+            LayoutText {#text} at (17,1) size 41x37
+              text run at (17,1) width 41: "efg"
+          LayoutText {#text} at (57,16) size 33x18
+            text run at (57,16) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,122) size 1x18
+    LayoutBR {BR} at (95,125) size 1x18
+    LayoutBlockFlow {DIV} at (3,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,274) size 4x18
+      text run at (24,274) width 4: " "
+    LayoutBlockFlow {DIV} at (28,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,274) size 4x18
+      text run at (49,274) width 4: " "
+    LayoutBlockFlow {DIV} at (53,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,274) size 4x18
+      text run at (74,274) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,274) size 4x18
+      text run at (99,274) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,274) size 4x18
+      text run at (124,274) width 4: " "
+    LayoutBlockFlow {DIV} at (128,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (11,1) size 18x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 18x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,274) size 4x18
+      text run at (168,274) width 4: " "
+    LayoutBlockFlow {DIV} at (172,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (10,1) size 18x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 18x33
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (174,10) size 47x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (166.16,2) size 46.84x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 37x18
+      text run at (5,4) width 37: "initial"
+layer at (227,8) size 215x296
+  LayoutBlockFlow (relative positioned) {DIV} at (219,0) size 215x296 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,2) size 1x18
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,23) size 1x18
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,44) size 1x18
+      LayoutBlockFlow {DIV} at (1,64) size 73.13x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 72x16
+          LayoutText {#text} at (1,2) size 72x16
+            text run at (1,2) width 72: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,66) size 1x18
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,86) size 1x18
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x18
+          LayoutText {#text} at (1,16) size 16x18
+            text run at (1,16) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x37
+            LayoutText {#text} at (17,1) size 41x37
+              text run at (17,1) width 41: "efg"
+          LayoutText {#text} at (57,16) size 33x18
+            text run at (57,16) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,122) size 1x18
+    LayoutBR {BR} at (95,125) size 1x18
+    LayoutBlockFlow {DIV} at (3,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,274) size 4x18
+      text run at (24,274) width 4: " "
+    LayoutBlockFlow {DIV} at (28,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,274) size 4x18
+      text run at (49,274) width 4: " "
+    LayoutBlockFlow {DIV} at (53,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,274) size 4x18
+      text run at (74,274) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,274) size 4x18
+      text run at (99,274) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,274) size 4x18
+      text run at (124,274) width 4: " "
+    LayoutBlockFlow {DIV} at (128,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (11,1) size 18x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 18x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,274) size 4x18
+      text run at (168,274) width 4: " "
+    LayoutBlockFlow {DIV} at (172,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (10,1) size 18x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 18x33
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (373,10) size 67x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (146.13,2) size 66.88x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 57x18
+      text run at (5,4) width 57: "lang=zh"
+layer at (446,8) size 215x296
+  LayoutBlockFlow (relative positioned) {DIV} at (438,0) size 215x296 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,2) size 1x18
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,23) size 1x18
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,44) size 1x18
+      LayoutBlockFlow {DIV} at (1,64) size 73.13x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 72x16
+          LayoutText {#text} at (1,2) size 72x16
+            text run at (1,2) width 72: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,66) size 1x18
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,86) size 1x18
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x18
+          LayoutText {#text} at (1,16) size 16x18
+            text run at (1,16) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x37
+            LayoutText {#text} at (17,1) size 41x37
+              text run at (17,1) width 41: "efg"
+          LayoutText {#text} at (57,16) size 33x18
+            text run at (57,16) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,122) size 1x18
+    LayoutBR {BR} at (95,125) size 1x18
+    LayoutBlockFlow {DIV} at (3,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,274) size 4x18
+      text run at (24,274) width 4: " "
+    LayoutBlockFlow {DIV} at (28,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,274) size 4x18
+      text run at (49,274) width 4: " "
+    LayoutBlockFlow {DIV} at (53,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,274) size 4x18
+      text run at (74,274) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,274) size 4x18
+      text run at (99,274) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,274) size 4x18
+      text run at (124,274) width 4: " "
+    LayoutBlockFlow {DIV} at (128,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (11,1) size 18x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 18x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,274) size 4x18
+      text run at (168,274) width 4: " "
+    LayoutBlockFlow {DIV} at (172,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (10,1) size 18x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 18x33
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (597,10) size 62x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (150.58,2) size 62.42x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 53x18
+      text run at (5,4) width 53: "lang=ja"
+layer at (8,304) size 215x296
+  LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 215x296 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,2) size 1x18
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,23) size 1x18
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,44) size 1x18
+      LayoutBlockFlow {DIV} at (1,64) size 73.13x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 72x16
+          LayoutText {#text} at (1,2) size 72x16
+            text run at (1,2) width 72: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,66) size 1x18
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,86) size 1x18
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x18
+          LayoutText {#text} at (1,16) size 16x18
+            text run at (1,16) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x37
+            LayoutText {#text} at (17,1) size 41x37
+              text run at (17,1) width 41: "efg"
+          LayoutText {#text} at (57,16) size 33x18
+            text run at (57,16) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,122) size 1x18
+    LayoutBR {BR} at (95,125) size 1x18
+    LayoutBlockFlow {DIV} at (3,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,274) size 4x18
+      text run at (24,274) width 4: " "
+    LayoutBlockFlow {DIV} at (28,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,274) size 4x18
+      text run at (49,274) width 4: " "
+    LayoutBlockFlow {DIV} at (53,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,274) size 4x18
+      text run at (74,274) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,274) size 4x18
+      text run at (99,274) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,274) size 4x18
+      text run at (124,274) width 4: " "
+    LayoutBlockFlow {DIV} at (128,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (11,1) size 18x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 18x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,274) size 4x18
+      text run at (168,274) width 4: " "
+    LayoutBlockFlow {DIV} at (172,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (10,1) size 18x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 18x33
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (170,306) size 51x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (161.70,2) size 51.30x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 42x18
+      text run at (5,4) width 42: "under"
+layer at (227,304) size 215x296
+  LayoutBlockFlow (relative positioned) {DIV} at (219,0) size 215x296 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,2) size 1x18
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,23) size 1x18
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,44) size 1x18
+      LayoutBlockFlow {DIV} at (1,64) size 73.13x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 72x16
+          LayoutText {#text} at (1,2) size 72x16
+            text run at (1,2) width 72: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,66) size 1x18
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,86) size 1x18
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x18
+          LayoutText {#text} at (1,16) size 16x18
+            text run at (1,16) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x37
+            LayoutText {#text} at (17,1) size 41x37
+              text run at (17,1) width 41: "efg"
+          LayoutText {#text} at (57,16) size 33x18
+            text run at (57,16) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,122) size 1x18
+    LayoutBR {BR} at (95,125) size 1x18
+    LayoutBlockFlow {DIV} at (3,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,274) size 4x18
+      text run at (24,274) width 4: " "
+    LayoutBlockFlow {DIV} at (28,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,274) size 4x18
+      text run at (49,274) width 4: " "
+    LayoutBlockFlow {DIV} at (53,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,274) size 4x18
+      text run at (74,274) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,274) size 4x18
+      text run at (99,274) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,274) size 4x18
+      text run at (124,274) width 4: " "
+    LayoutBlockFlow {DIV} at (128,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (11,1) size 18x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 18x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,274) size 4x18
+      text run at (168,274) width 4: " "
+    LayoutBlockFlow {DIV} at (172,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (10,1) size 18x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 18x33
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (367,306) size 73x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (140.36,2) size 72.64x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 63x18
+      text run at (5,4) width 63: "under zh"
+layer at (446,304) size 215x296
+  LayoutBlockFlow (relative positioned) {DIV} at (438,0) size 215x296 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,2) size 1x18
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,23) size 1x18
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,44) size 1x18
+      LayoutBlockFlow {DIV} at (1,64) size 73.13x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 72x16
+          LayoutText {#text} at (1,2) size 72x16
+            text run at (1,2) width 72: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,66) size 1x18
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x18
+          LayoutText {#text} at (1,1) size 69x18
+            text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,86) size 1x18
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x18
+          LayoutText {#text} at (1,16) size 16x18
+            text run at (1,16) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x37
+            LayoutText {#text} at (17,1) size 41x37
+              text run at (17,1) width 41: "efg"
+          LayoutText {#text} at (57,16) size 33x18
+            text run at (57,16) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,122) size 1x18
+    LayoutBR {BR} at (95,125) size 1x18
+    LayoutBlockFlow {DIV} at (3,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,274) size 4x18
+      text run at (24,274) width 4: " "
+    LayoutBlockFlow {DIV} at (28,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,274) size 4x18
+      text run at (49,274) width 4: " "
+    LayoutBlockFlow {DIV} at (53,218) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x69
+        LayoutText {#text} at (1,1) size 18x69
+          text run at (1,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,274) size 4x18
+      text run at (74,274) width 4: " "
+    LayoutBlockFlow {DIV} at (78,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,274) size 4x18
+      text run at (99,274) width 4: " "
+    LayoutBlockFlow {DIV} at (103,150) size 21x137.59 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x136
+        LayoutText {#text} at (1,1) size 18x136
+          text run at (1,1) width 136: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,274) size 4x18
+      text run at (124,274) width 4: " "
+    LayoutBlockFlow {DIV} at (128,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (11,1) size 18x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 18x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,274) size 4x18
+      text run at (168,274) width 4: " "
+    LayoutBlockFlow {DIV} at (172,179) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 18x107
+        LayoutText {#text} at (10,1) size 18x16
+          text run at (10,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 37x59
+          LayoutText {#text} at (1,17) size 37x59
+            text run at (1,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (10,75) size 18x33
+          text run at (10,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (591,306) size 68x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (144.80,2) size 68.20x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 58x18
+      text run at (5,4) width 58: "under ja"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/lists/002-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/lists/002-vertical-expected.png
index 841eea7..a1f3c1da 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/lists/002-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/lists/002-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/lists/006-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/lists/006-vertical-expected.png
index 1366efc..ad37cf35 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/lists/006-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/lists/006-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/table/border-collapsing/003-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/table/border-collapsing/003-vertical-expected.png
index e29c72e..72272d7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/table/border-collapsing/003-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/table/border-collapsing/003-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/decorations-with-text-combine-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/decorations-with-text-combine-expected.png
index 1377f9b..67fe9279 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/decorations-with-text-combine-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/decorations-with-text-combine-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-expected.png
index d4b078e..0f500d6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-125-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-125-expected.png
index a6811c41..ed440400 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-125-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-125-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-150-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-150-expected.png
index bd175d2..c545e327 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-150-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-150-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-175-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-175-expected.png
index 1225d73..4562f674 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-175-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-175-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-200-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-200-expected.png
index 24d2143..08e28e686 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-200-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-200-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-250-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-250-expected.png
index 35227e5..483a9ace 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-250-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/spellmarkers/document-markers-zoom-250-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
new file mode 100644
index 0000000..5cd5cb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 17d6e81c..1d9fa9f3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-expected.png
index 5d1f9b51..a6af056 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png
index 327f2c9..dcf0e731 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
index b4ae1b2..92fc15b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png
index b4ae1b2..92fc15b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline_spelling_markers-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline_spelling_markers-expected.png
index cd7e4a7b..eed93287 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline_spelling_markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline_spelling_markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt b/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
similarity index 71%
copy from third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
copy to third_party/WebKit/LayoutTests/platform/win/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
index 7d3b5772..c158bbfb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt
@@ -1,3 +1,6 @@
+CONSOLE ERROR: Not allowed to load local resource: blank.html
+CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details.
+CONSOLE ERROR: Not allowed to load local resource: script%3E
 CONSOLE ERROR: Not allowed to load local resource: script%3E
 This is a testharness.js-based test.
 PASS Set HTTP URL frame location.protocol to x 
diff --git a/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt b/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
new file mode 100644
index 0000000..641e4e1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt
@@ -0,0 +1,11 @@
+CONSOLE ERROR: Not allowed to load local resource: blank.html
+CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details.
+This is a testharness.js-based test.
+PASS Set location.protocol to x 
+FAIL Set location.protocol to data Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame.
+FAIL Set location.protocol to file Failed to set the 'protocol' property on 'Location': 'file://web-platform.test:8001/common/blank.html' is not a valid URL.
+PASS Set location.protocol to ftp 
+PASS Set location.protocol to gopher 
+PASS Set location.protocol to http+x 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-lr/007-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-lr/007-expected.png
index 6b53f60..bbfedc7 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-lr/007-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-lr/007-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-rl/007-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-rl/007-expected.png
index 3683bc3..eab6f2c 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-rl/007-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/auto/vertical-rl/007-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-lr/001-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-lr/001-expected.png
index 4643ec3..d9eefd0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-lr/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-lr/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-rl/001-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-rl/001-expected.png
index 898174d..a5ce3b6 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-rl/001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/block/positioning/vertical-rl/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-expected.png
index 0a1f153..f622b876 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-strict-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-strict-expected.png
index 0a1f153..f622b876 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-ellipsis-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png
new file mode 100644
index 0000000..616c4ee5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt
new file mode 100644
index 0000000..e6b1c44
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.txt
@@ -0,0 +1,581 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x548
+  LayoutBlockFlow {HTML} at (0,0) size 800x548
+    LayoutBlockFlow {BODY} at (8,8) size 784x532
+      LayoutBlockFlow (anonymous) at (0,0) size 784x266
+        LayoutText {#text} at (215,0) size 4x17
+          text run at (215,0) width 4: " "
+        LayoutText {#text} at (434,0) size 4x17
+          text run at (434,0) width 4: " "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (0,266) size 784x266
+        LayoutText {#text} at (215,0) size 4x17
+          text run at (215,0) width 4: " "
+        LayoutText {#text} at (434,0) size 4x17
+          text run at (434,0) width 4: " "
+        LayoutText {#text} at (0,0) size 0x0
+layer at (8,8) size 215x266
+  LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 215x266 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,3) size 1x17
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,24) size 1x17
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,45) size 1x17
+      LayoutBlockFlow {DIV} at (1,64) size 73x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 71x21
+          LayoutText {#text} at (1,0) size 71x21
+            text run at (1,0) width 71: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,67) size 0x17
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,87) size 1x17
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x17
+          LayoutText {#text} at (1,17) size 16x17
+            text run at (1,17) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x36
+            LayoutText {#text} at (17,2) size 41x36
+              text run at (17,2) width 41: "efg"
+          LayoutText {#text} at (57,17) size 33x17
+            text run at (57,17) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,123) size 1x17
+    LayoutBR {BR} at (95,126) size 1x17
+    LayoutBlockFlow {DIV} at (3,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,245) size 4x17
+      text run at (24,245) width 4: " "
+    LayoutBlockFlow {DIV} at (28,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,245) size 4x17
+      text run at (49,245) width 4: " "
+    LayoutBlockFlow {DIV} at (53,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,245) size 4x17
+      text run at (74,245) width 4: " "
+    LayoutBlockFlow {DIV} at (78,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,245) size 4x17
+      text run at (99,245) width 4: " "
+    LayoutBlockFlow {DIV} at (103,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,245) size 4x17
+      text run at (124,245) width 4: " "
+    LayoutBlockFlow {DIV} at (128,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (11,1) size 17x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 17x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,245) size 4x17
+      text run at (168,245) width 4: " "
+    LayoutBlockFlow {DIV} at (172,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (12,1) size 17x16
+          text run at (12,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (12,75) size 17x33
+          text run at (12,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (174,10) size 47x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (166.16,2) size 46.84x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 37x17
+      text run at (5,4) width 37: "initial"
+layer at (227,8) size 215x266
+  LayoutBlockFlow (relative positioned) {DIV} at (219,0) size 215x266 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,3) size 1x17
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,24) size 1x17
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,45) size 1x17
+      LayoutBlockFlow {DIV} at (1,64) size 73x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 71x21
+          LayoutText {#text} at (1,0) size 71x21
+            text run at (1,0) width 71: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,67) size 0x17
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,87) size 1x17
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x17
+          LayoutText {#text} at (1,17) size 16x17
+            text run at (1,17) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x36
+            LayoutText {#text} at (17,2) size 41x36
+              text run at (17,2) width 41: "efg"
+          LayoutText {#text} at (57,17) size 33x17
+            text run at (57,17) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,123) size 1x17
+    LayoutBR {BR} at (95,126) size 1x17
+    LayoutBlockFlow {DIV} at (3,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,245) size 4x17
+      text run at (24,245) width 4: " "
+    LayoutBlockFlow {DIV} at (28,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,245) size 4x17
+      text run at (49,245) width 4: " "
+    LayoutBlockFlow {DIV} at (53,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,245) size 4x17
+      text run at (74,245) width 4: " "
+    LayoutBlockFlow {DIV} at (78,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,245) size 4x17
+      text run at (99,245) width 4: " "
+    LayoutBlockFlow {DIV} at (103,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,245) size 4x17
+      text run at (124,245) width 4: " "
+    LayoutBlockFlow {DIV} at (128,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (11,1) size 17x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 17x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,245) size 4x17
+      text run at (168,245) width 4: " "
+    LayoutBlockFlow {DIV} at (172,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (12,1) size 17x16
+          text run at (12,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (12,75) size 17x33
+          text run at (12,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (373,10) size 67x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (146.13,2) size 66.88x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 57x17
+      text run at (5,4) width 57: "lang=zh"
+layer at (446,8) size 215x266
+  LayoutBlockFlow (relative positioned) {DIV} at (438,0) size 215x266 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,3) size 1x17
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,24) size 1x17
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,45) size 1x17
+      LayoutBlockFlow {DIV} at (1,64) size 73x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 71x21
+          LayoutText {#text} at (1,0) size 71x21
+            text run at (1,0) width 71: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,67) size 0x17
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,87) size 1x17
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x17
+          LayoutText {#text} at (1,17) size 16x17
+            text run at (1,17) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x36
+            LayoutText {#text} at (17,2) size 41x36
+              text run at (17,2) width 41: "efg"
+          LayoutText {#text} at (57,17) size 33x17
+            text run at (57,17) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,123) size 1x17
+    LayoutBR {BR} at (95,126) size 1x17
+    LayoutBlockFlow {DIV} at (3,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,245) size 4x17
+      text run at (24,245) width 4: " "
+    LayoutBlockFlow {DIV} at (28,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,245) size 4x17
+      text run at (49,245) width 4: " "
+    LayoutBlockFlow {DIV} at (53,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,245) size 4x17
+      text run at (74,245) width 4: " "
+    LayoutBlockFlow {DIV} at (78,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,245) size 4x17
+      text run at (99,245) width 4: " "
+    LayoutBlockFlow {DIV} at (103,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,245) size 4x17
+      text run at (124,245) width 4: " "
+    LayoutBlockFlow {DIV} at (128,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (11,1) size 17x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 17x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,245) size 4x17
+      text run at (168,245) width 4: " "
+    LayoutBlockFlow {DIV} at (172,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (12,1) size 17x16
+          text run at (12,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (12,75) size 17x33
+          text run at (12,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (597,10) size 62x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (150.58,2) size 62.42x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 53x17
+      text run at (5,4) width 53: "lang=ja"
+layer at (8,274) size 215x266
+  LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 215x266 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,3) size 1x17
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,24) size 1x17
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,45) size 1x17
+      LayoutBlockFlow {DIV} at (1,64) size 73x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 71x21
+          LayoutText {#text} at (1,0) size 71x21
+            text run at (1,0) width 71: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,67) size 0x17
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,87) size 1x17
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x17
+          LayoutText {#text} at (1,17) size 16x17
+            text run at (1,17) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x36
+            LayoutText {#text} at (17,2) size 41x36
+              text run at (17,2) width 41: "efg"
+          LayoutText {#text} at (57,17) size 33x17
+            text run at (57,17) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,123) size 1x17
+    LayoutBR {BR} at (95,126) size 1x17
+    LayoutBlockFlow {DIV} at (3,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,245) size 4x17
+      text run at (24,245) width 4: " "
+    LayoutBlockFlow {DIV} at (28,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,245) size 4x17
+      text run at (49,245) width 4: " "
+    LayoutBlockFlow {DIV} at (53,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,245) size 4x17
+      text run at (74,245) width 4: " "
+    LayoutBlockFlow {DIV} at (78,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,245) size 4x17
+      text run at (99,245) width 4: " "
+    LayoutBlockFlow {DIV} at (103,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,245) size 4x17
+      text run at (124,245) width 4: " "
+    LayoutBlockFlow {DIV} at (128,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (11,1) size 17x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 17x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,245) size 4x17
+      text run at (168,245) width 4: " "
+    LayoutBlockFlow {DIV} at (172,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (12,1) size 17x16
+          text run at (12,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (12,75) size 17x33
+          text run at (12,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (170,276) size 51x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (161.70,2) size 51.30x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 42x17
+      text run at (5,4) width 42: "under"
+layer at (227,274) size 215x266
+  LayoutBlockFlow (relative positioned) {DIV} at (219,0) size 215x266 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,3) size 1x17
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,24) size 1x17
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,45) size 1x17
+      LayoutBlockFlow {DIV} at (1,64) size 73x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 71x21
+          LayoutText {#text} at (1,0) size 71x21
+            text run at (1,0) width 71: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,67) size 0x17
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,87) size 1x17
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x17
+          LayoutText {#text} at (1,17) size 16x17
+            text run at (1,17) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x36
+            LayoutText {#text} at (17,2) size 41x36
+              text run at (17,2) width 41: "efg"
+          LayoutText {#text} at (57,17) size 33x17
+            text run at (57,17) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,123) size 1x17
+    LayoutBR {BR} at (95,126) size 1x17
+    LayoutBlockFlow {DIV} at (3,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,245) size 4x17
+      text run at (24,245) width 4: " "
+    LayoutBlockFlow {DIV} at (28,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,245) size 4x17
+      text run at (49,245) width 4: " "
+    LayoutBlockFlow {DIV} at (53,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,245) size 4x17
+      text run at (74,245) width 4: " "
+    LayoutBlockFlow {DIV} at (78,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,245) size 4x17
+      text run at (99,245) width 4: " "
+    LayoutBlockFlow {DIV} at (103,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,245) size 4x17
+      text run at (124,245) width 4: " "
+    LayoutBlockFlow {DIV} at (128,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (11,1) size 17x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 17x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,245) size 4x17
+      text run at (168,245) width 4: " "
+    LayoutBlockFlow {DIV} at (172,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (12,1) size 17x16
+          text run at (12,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (12,75) size 17x33
+          text run at (12,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (367,276) size 73x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (140.36,2) size 72.64x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 63x17
+      text run at (5,4) width 63: "under zh"
+layer at (446,274) size 215x266
+  LayoutBlockFlow (relative positioned) {DIV} at (438,0) size 215x266 [border: (2px solid #FFA500)]
+    LayoutBlockFlow {DIV} at (3,3) size 92.86x147 [border: (1px solid #00FF00)]
+      LayoutBlockFlow {DIV} at (1,1) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,3) size 1x17
+      LayoutBlockFlow {DIV} at (1,22) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,24) size 1x17
+      LayoutBlockFlow {DIV} at (1,43) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,45) size 1x17
+      LayoutBlockFlow {DIV} at (1,64) size 73x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 71x21
+          LayoutText {#text} at (1,0) size 71x21
+            text run at (1,0) width 71: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (74,67) size 0x17
+      LayoutBlockFlow {DIV} at (1,85) size 70.44x21 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 69x17
+          LayoutText {#text} at (1,2) size 69x17
+            text run at (1,2) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (71,87) size 1x17
+      LayoutBlockFlow {DIV} at (1,106) size 90.86x40 [border: (1px solid #00FF00)]
+        LayoutInline {U} at (0,0) size 89x17
+          LayoutText {#text} at (1,17) size 16x17
+            text run at (1,17) width 16: "\x{6F22}"
+          LayoutInline {SPAN} at (0,0) size 41x36
+            LayoutText {#text} at (17,2) size 41x36
+              text run at (17,2) width 41: "efg"
+          LayoutText {#text} at (57,17) size 33x17
+            text run at (57,17) width 33: "\x{6DF7}\x{690D}"
+      LayoutBR {BR} at (91,123) size 1x17
+    LayoutBR {BR} at (95,126) size 1x17
+    LayoutBlockFlow {DIV} at (3,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (24,245) size 4x17
+      text run at (24,245) width 4: " "
+    LayoutBlockFlow {DIV} at (28,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (49,245) size 4x17
+      text run at (49,245) width 4: " "
+    LayoutBlockFlow {DIV} at (53,189) size 21x70.44 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x69
+        LayoutText {#text} at (2,1) size 17x69
+          text run at (2,1) width 69: "\x{6F22}efg\x{6DF7}\x{690D}"
+    LayoutText {#text} at (74,245) size 4x17
+      text run at (74,245) width 4: " "
+    LayoutBlockFlow {DIV} at (78,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (99,245) size 4x17
+      text run at (99,245) width 4: " "
+    LayoutBlockFlow {DIV} at (103,172) size 21x86.84 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x85
+        LayoutText {#text} at (2,1) size 17x85
+          text run at (2,1) width 85: "\x{182E}\x{1823}\x{1828}\x{182D}\x{182D}\x{1823}\x{182F} \x{182C}\x{1821}\x{182F}\x{1821} efg\x{6F22}"
+    LayoutText {#text} at (124,245) size 4x17
+      text run at (124,245) width 4: " "
+    LayoutBlockFlow {DIV} at (128,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (11,1) size 17x16
+          text run at (11,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (11,75) size 17x33
+          text run at (11,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (168,245) size 4x17
+      text run at (168,245) width 4: " "
+    LayoutBlockFlow {DIV} at (172,150) size 40x108.66 [border: (1px solid #00FF00)]
+      LayoutInline {U} at (0,0) size 17x107
+        LayoutText {#text} at (12,1) size 17x16
+          text run at (12,1) width 16: "\x{6F22}"
+        LayoutInline {SPAN} at (0,0) size 36x59
+          LayoutText {#text} at (2,17) size 36x59
+            text run at (2,17) width 59: "\x{6F22}fg"
+        LayoutText {#text} at (12,75) size 17x33
+          text run at (12,75) width 32: "\x{6DF7}\x{690D}"
+    LayoutText {#text} at (0,0) size 0x0
+layer at (591,276) size 68x26
+  LayoutBlockFlow (positioned) {<pseudo:before>} at (144.80,2) size 68.20x26.38 [bgcolor=#FFFFFF] [border: (2px solid #808080)]
+    LayoutTextFragment (anonymous) at (5,4) size 58x17
+      text run at (5,4) width 58: "under ja"
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/lists/002-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/lists/002-vertical-expected.png
index 365e130..d83752b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/lists/002-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/lists/002-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/lists/006-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/lists/006-vertical-expected.png
index 210f3586..519868f9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/lists/006-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/lists/006-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/table/border-collapsing/003-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/table/border-collapsing/003-vertical-expected.png
index da37073..e740f92 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/table/border-collapsing/003-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/table/border-collapsing/003-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/decorations-with-text-combine-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/text/decorations-with-text-combine-expected.png
index d0f56c46..ac8f7cae 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/decorations-with-text-combine-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/text/decorations-with-text-combine-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-expected.png
index 424e43b..fd337bf 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-125-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-125-expected.png
index 6689c93..1488d19 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-125-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-125-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-150-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-150-expected.png
index 5182d4d..ddfd487 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-150-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-150-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-175-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-175-expected.png
index 52ffa3a..4518e457 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-175-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-175-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-200-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-200-expected.png
index 7d0902d..53a6ed5 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-200-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-200-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-250-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-250-expected.png
index d2e181dda..902c68f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-250-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/spellmarkers/document-markers-zoom-250-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
new file mode 100644
index 0000000..f1d41e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
index 066e4ff..54a21f4b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/text/decorations-with-text-combine-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/text/decorations-with-text-combine-expected.png
index 5aa3daa..63407f8 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/text/decorations-with-text-combine-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/fast/text/decorations-with-text-combine-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/storage/indexeddb/key-type-binary.html b/third_party/WebKit/LayoutTests/storage/indexeddb/key-type-binary.html
deleted file mode 100644
index f1ccd38..0000000
--- a/third_party/WebKit/LayoutTests/storage/indexeddb/key-type-binary.html
+++ /dev/null
@@ -1,144 +0,0 @@
-<!DOCTYPE html>
-<title>IndexedDB: Verify transaction activation behavior around microtasks</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="resources/testharness-helpers.js"></script>
-<script>
-var sample = [0x44, 0x33, 0x22, 0x11, 0xFF, 0xEE, 0xDD, 0xCC];
-var buffer = new Uint8Array(sample).buffer;
-
-function assert_key_valid(a, message) {
-    assert_equals(indexedDB.cmp(a, a), 0, message);
-}
-
-function assert_buffer_equals(a, b, message) {
-    assert_array_equals(
-        [].slice.call(new Uint8Array(a)),
-        [].slice.call(new Uint8Array(b)),
-        message);
-}
-
-function check_key(t, db, key) {
-    var tx = db.transaction('store', 'readwrite');
-    var store = tx.objectStore('store');
-
-    // Verify put with key
-    var req = store.put('value', key);
-    req.onerror = t.unreached_func('put should succeed');
-
-    // Verify get with key
-    req = store.get(key);
-    req.onerror = t.unreached_func('get should succeed');
-    req.onsuccess = t.step_func(function() {
-        assert_equals(req.result, 'value', 'get with key should succeed');
-
-        // Verify iteration returning key
-        req = store.openCursor();
-        req.onerror = t.unreached_func('openCursor should succeed');
-        req.onsuccess = t.step_func(function() {
-            assert_not_equals(req.result, null, 'cursor should be present');
-            var found_key = req.result.key;
-            assert_true(found_key instanceof ArrayBuffer,
-                        'Key should be an ArrayBuffer');
-            assert_key_equals(found_key, key,
-                              'Key should be equal to put key');
-            assert_buffer_equals(
-                found_key, buffer, 'Buffers should be equal to put buffer');
-
-            t.done();
-        });
-    });
-}
-
-function type_test(type) {
-    indexeddb_test(
-        function(t, db) {
-            db.createObjectStore('store');
-        },
-        function(t, db) {
-            var key = new self[type](buffer);
-            assert_key_valid(key, type + ' should be a valid key');
-            assert_key_equals(key, buffer,
-                              'Keys should be equal regardless of type');
-            check_key(t, db, key);
-        },
-        'Binary key: ' + type
-    );
-}
-
-[
-    'Uint8Array',
-    'Uint8ClampedArray',
-    'Int8Array',
-    'Uint16Array',
-    'Int16Array',
-    'Uint32Array',
-    'Int32Array',
-    'Float32Array',
-    'Float64Array'
-].forEach(function(type) { type_test(type); });
-
-function value_test(type, value) {
-    indexeddb_test(
-        function(t, db) {
-            db.createObjectStore('store');
-        },
-        function(t, db) {
-            assert_key_valid(value, type + ' should be a valid key');
-            check_key(t, db, value);
-            t.done();
-        },
-        'Value test: ' + type
-    );
-}
-
-value_test('ArrayBuffer', buffer);
-value_test('DataView', new DataView(buffer));
-value_test('Offset DataView', new DataView(buffer), 3, 3);
-value_test('Offset Uint8Array', new Uint8Array(buffer), 3, 3);
-
-indexeddb_test(
-    function(t, db) {
-        db.createObjectStore('store');
-    },
-    function(t, db) {
-        var tx = db.transaction('store', 'readwrite');
-        var store = tx.objectStore('store');
-
-        var b = new Uint8Array([1,2,3,4]).buffer;
-        assert_equals(b.byteLength, 4);
-
-        // Neuter the ArrayBuffer by transferring it to a worker.
-        var w = new Worker(URL.createObjectURL(new Blob([])));
-        w.postMessage('', [b]);
-        assert_equals(b.byteLength, 0);
-
-        assert_throws(new TypeError, function() { store.put('', b); });
-        t.done();
-    },
-    'Neutered ArrayBuffer'
-);
-
-indexeddb_test(
-    function(t, db) {
-        db.createObjectStore('store');
-    },
-    function(t, db) {
-        var tx = db.transaction('store', 'readwrite');
-        var store = tx.objectStore('store');
-
-        var a = new Uint8Array([1,2,3,4]);
-        assert_equals(a.length, 4);
-
-        // Neuter the ArrayBuffer by transferring it to a worker.
-        var w = new Worker(URL.createObjectURL(new Blob([])));
-        w.postMessage('', [a.buffer]);
-        assert_equals(a.length, 0);
-
-        assert_throws(new TypeError, function() { store.put('', a); });
-        t.done();
-    },
-    'Neutered ArrayBufferView'
-);
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/svg/dom/SVGTransformList-empty-list-consolidation-expected.txt b/third_party/WebKit/LayoutTests/svg/dom/SVGTransformList-empty-list-consolidation-expected.txt
deleted file mode 100644
index 68a0c3d9..0000000
--- a/third_party/WebKit/LayoutTests/svg/dom/SVGTransformList-empty-list-consolidation-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-This test passes if it doesn't fire an assertion.
diff --git a/third_party/WebKit/LayoutTests/svg/dom/SVGTransformList-empty-list-consolidation.html b/third_party/WebKit/LayoutTests/svg/dom/SVGTransformList-empty-list-consolidation.html
index 946d761b..cefdd25 100644
--- a/third_party/WebKit/LayoutTests/svg/dom/SVGTransformList-empty-list-consolidation.html
+++ b/third_party/WebKit/LayoutTests/svg/dom/SVGTransformList-empty-list-consolidation.html
@@ -1,17 +1,12 @@
-<html>
-<head>
+<!DOCTYPE html>
+<title>SVGTransformList.consolidate() on an empty transform list</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
-if (window.testRunner)
-    testRunner.dumpAsText();
-
-function go() {
-    var oSvgPatternElement = document.createElementNS("http://www.w3.org/2000/svg","pattern");
-    var oSvgTransformList = oSvgPatternElement.patternTransform.baseVal;
-    oSvgTransformList.consolidate();
-}
+test(function() {
+  let element = document.createElementNS("http://www.w3.org/2000/svg", "pattern");
+  let transformList = element.patternTransform.baseVal;
+  assert_equals(transformList.length, 0);
+  assert_equals(transformList.consolidate(), null);
+});
 </script>
-</head>
-<body onload="go()">
-This test passes if it doesn't fire an assertion.
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svgtransformlist-empty-consolidate-and-initialize-crash-expected.txt b/third_party/WebKit/LayoutTests/svg/dom/svgtransformlist-empty-consolidate-and-initialize-crash-expected.txt
new file mode 100644
index 0000000..ddad5eaf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/dom/svgtransformlist-empty-consolidate-and-initialize-crash-expected.txt
@@ -0,0 +1 @@
+PASS if no crash
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svgtransformlist-empty-consolidate-and-initialize-crash.html b/third_party/WebKit/LayoutTests/svg/dom/svgtransformlist-empty-consolidate-and-initialize-crash.html
new file mode 100644
index 0000000..d90aff4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/dom/svgtransformlist-empty-consolidate-and-initialize-crash.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<svg>
+  <rect width="100" height="100"/>
+</svg>
+<script>
+if (window.testRunner)
+  testRunner.dumpAsText();
+
+var transform = document.querySelector('rect').transform;
+var value = transform.baseVal.consolidate();
+try { transform.baseVal.initialize(value); } catch (e) {}
+</script>
+<p>PASS if no crash</p>
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-arc-circumference-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-arc-circumference-expected.png
index f92a57dd..19fc13ed 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-arc-circumference-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-arc-circumference-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
deleted file mode 100644
index 8aabedc6..0000000
--- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-arc-circumference-fill-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-expected.png
index 6bf295d4..792da92 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png
index 5171812e..db71efa 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index f8a9723..f109b9a2 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4090,6 +4090,39 @@
     method constructor
     method item
     method namedItem
+interface Mojo
+    static method createMessagePipe
+    attribute @@toStringTag
+    attribute RESULT_ABORTED
+    attribute RESULT_ALREADY_EXISTS
+    attribute RESULT_BUSY
+    attribute RESULT_CANCELLED
+    attribute RESULT_DATA_LOSS
+    attribute RESULT_DEADLINE_EXCEEDED
+    attribute RESULT_FAILED_PRECONDITION
+    attribute RESULT_INTERNAL
+    attribute RESULT_INVALID_ARGUMENT
+    attribute RESULT_NOT_FOUND
+    attribute RESULT_OK
+    attribute RESULT_OUT_OF_RANGE
+    attribute RESULT_PERMISSION_DENIED
+    attribute RESULT_RESOURCE_EXHAUSTED
+    attribute RESULT_SHOULD_WAIT
+    attribute RESULT_UNAVAILABLE
+    attribute RESULT_UNIMPLEMENTED
+    attribute RESULT_UNKNOWN
+    method constructor
+interface MojoHandle
+    attribute @@toStringTag
+    method close
+    method constructor
+    method readMessage
+    method watch
+    method writeMessage
+interface MojoWatcher
+    attribute @@toStringTag
+    method cancel
+    method constructor
 interface MouseEvent : UIEvent
     attribute @@toStringTag
     getter altKey
@@ -6551,10 +6584,8 @@
     getter oncuechange
     getter regions
     method addCue
-    method addRegion
     method constructor
     method removeCue
-    method removeRegion
     setter mode
     setter oncuechange
 interface TextTrackCue : EventTarget
diff --git a/third_party/WebKit/PRESUBMIT.py b/third_party/WebKit/PRESUBMIT.py
index 517f5bc..ce54af2 100644
--- a/third_party/WebKit/PRESUBMIT.py
+++ b/third_party/WebKit/PRESUBMIT.py
@@ -100,7 +100,6 @@
     results.extend(input_api.canned_checks.PanProjectChecks(
         input_api, output_api, excluded_paths=_EXCLUDED_PATHS,
         maxlen=800, license_header=license_header))
-    results.extend(input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
     results.extend(_CheckForNonBlinkVariantMojomIncludes(input_api, output_api))
     results.extend(_CheckForVersionControlConflicts(input_api, output_api))
     results.extend(_CheckPatchFiles(input_api, output_api))
diff --git a/third_party/WebKit/PerformanceTests/Layout/nested-percent-height-tables.html b/third_party/WebKit/PerformanceTests/Layout/nested-percent-height-tables.html
new file mode 100644
index 0000000..934ed15
--- /dev/null
+++ b/third_party/WebKit/PerformanceTests/Layout/nested-percent-height-tables.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<style>
+.body { margin:0; }
+.maxHeight { width:100%; height:100%; }
+.overflowDiv { overflow:hidden; display:inline-block }
+.overflowAuto { overflow:auto; }
+</style>
+<html id="top">
+  <body class="body" style="height:100%;">
+    <table class="maxHeight">
+      <tr>
+        <td style="height:100%;">
+          <div class="maxHeight">
+            <table class="maxHeight">
+              <tr>
+                <td class="maxHeight">
+                  <table class="maxHeight">
+                    <tr>
+                      <td style="height:100%;">
+                        <div class="maxHeight">
+                          <table id="top" class="maxHeight">
+                            <colgroup>
+                              <col/>
+                              <col />
+                              <col  style="width:100%;"/>
+                            </colgroup>
+                            <tr  style="height:100%;">
+                              <td style="height:100%;">
+                                <div class="overflowAuto maxHeight" style="position:relative;">
+                              </td>
+                              <td rowspan="1">
+                                <div class="overflowDiv" >
+                                </div>
+                              </td>
+                              <td style="height:100%;">
+                                <div class="overflowAuto maxHeight" style="position:relative;">
+                                  <div class="maxHeight">
+                                    <table class="maxHeight">
+                                      <tr>
+                                        <td class="maxHeight">
+                                          <table class="maxHeight">
+                                            <tr>
+                                              <td  style="height:100%;">
+                                                <table  class="maxHeight">
+                                                  <tr>
+                                                    <td colspan="2" class="maxHeight">
+                                                      <div class=" maxHeight">
+                                                        <table class="maxHeight">
+                                                          <tr>
+                                                            <td class="maxHeight">
+                                                              <table class="maxHeight">
+                                                                <tr>
+                                                                  <td  style="height:100%;">
+                                                                    <table class="maxHeight">
+                                                                      <tr>
+                                                                        <td class="maxHeight">
+                                                                          <table class="maxHeight">
+                                                                            <tr>
+                                                                              <td class="maxHeight">
+                                                                                <div class="maxHeight">
+                                                                                  <table class="maxHeight">
+                                                                                    <tr>
+                                                                                      <td class="maxHeight">
+                                                                                        <table class="maxHeight">
+                                                                                          <tr>
+                                                                                            <td  class="maxHeight">
+                                                                                              <table class="maxHeight">
+                                                                                                <tr>
+                                                                                                  <td class="maxHeight">
+                                                                                                    <table class="maxHeight">
+                                                                                                      <tr>
+                                                                                                        <td class="maxHeight">
+                                                                                                          <table class="maxHeight">
+                                                                                                            <tr>
+                                                                                                              <td class="maxHeight">
+                                                                                                                <table class="maxHeight">
+                                                                                                                  <tr>
+                                                                                                                    <td class="maxHeight">
+                                                                                                                      <table class="maxHeight">
+                                                                                                                        <tr>
+                                                                                                                          <td class="maxHeight">
+<script src="../resources/runner.js"></script>
+<script>
+function test() {
+  PerfTestRunner.forceLayout();
+  document.getElementById("top").style.height = "100%";
+  PerfTestRunner.forceLayout();
+  document.getElementById("top").style.height = "auto";
+}
+PerfTestRunner.measureRunsPerSecond({
+  description: "Measures performance of nested tables with percent height.",
+  run: test,
+});
+</script>
diff --git a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
index d0d4dc4..300c31c6 100644
--- a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
+++ b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
@@ -1023,7 +1023,7 @@
 
 Summary: Like `[RuntimeEnabled]`, it controls at runtime whether bindings are exposed, but uses a different mechanism for enabling experimental features.
 
-Usage: `[OriginTrialEnabled=FeatureName]`. FeatureName must be included in [RuntimeEnabledFeatures.in](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in), and is the same value that would be used with `[RuntimeEnabled]`.
+Usage: `[OriginTrialEnabled=FeatureName]`. FeatureName must be included in [RuntimeEnabledFeatures.json5](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5), and is the same value that would be used with `[RuntimeEnabled]`.
 
 ```webidl
 [
@@ -1035,7 +1035,7 @@
 
 `[OriginTrialEnabled]` has similar semantics to `[RuntimeEnabled]`, and is intended as a drop-in replacement. For example, `[OriginTrialEnabled]` _cannot_ be applied to arguments, see `[RuntimeEnabled]` for reasoning. The key implementation difference is that `[OriginTrialEnabled]` wraps the generated code with `if (OriginTrials::FeatureNameEnabled(...)) { ...code... }`.
 
-For more information, see [RuntimeEnabledFeatures](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in) and [OriginTrialContext](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h).
+For more information, see [RuntimeEnabledFeatures](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5) and [OriginTrialContext](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h).
 
 *** note
 **FIXME:** Currently, `[OriginTrialEnabled]` can only be applied to interfaces, attributes, and constants. Methods (including those generated by `iterable`, `setlike`, `maplike`, `serializer` and `stringifier`) are not supported. See [Bug 621641](https://crbug.com/621641).
@@ -1230,7 +1230,7 @@
 
 Summary: `[RuntimeEnabled]` wraps the generated code with `if (RuntimeEnabledFeatures::FeatureNameEnabled) { ...code... }`.
 
-Usage: `[RuntimeEnabled=FeatureName]`. FeatureName must be included in [RuntimeEnabledFeatures.in](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in).
+Usage: `[RuntimeEnabled=FeatureName]`. FeatureName must be included in [RuntimeEnabledFeatures.in](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5).
 
 ```webidl
 [
@@ -1254,7 +1254,7 @@
 [RuntimeEnabled=FeatureName] foo(long x, long y);
 ```
 
-For more information, see [RuntimeEnabledFeatures](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in).
+For more information, see [RuntimeEnabledFeatures](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5).
 
 ### [SaveSameObject] _(a)_
 
diff --git a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
index 026f6d3..4e6998f 100644
--- a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
+++ b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt
@@ -88,7 +88,7 @@
 ReflectOnly=*
 Replaceable
 # Valid values for [RuntimeEnabled] are the Runtime Enabled Features, listed in
-# Source/platform/RuntimeEnabledFeatures.in
+# Source/platform/RuntimeEnabledFeatures.json5
 RuntimeEnabled=*
 SameObject
 SaveSameObject
diff --git a/third_party/WebKit/Source/bindings/OWNERS b/third_party/WebKit/Source/bindings/OWNERS
index a279586..358a048 100644
--- a/third_party/WebKit/Source/bindings/OWNERS
+++ b/third_party/WebKit/Source/bindings/OWNERS
@@ -2,6 +2,7 @@
 esprehn@chromium.org
 haraken@chromium.org
 japhet@chromium.org
+jbroman@chromium.org
 jl@opera.com
 jochen@chromium.org
 marja@chromium.org
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
index de54c30..c5571697 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -129,6 +129,14 @@
   "$blink_core_output_dir/imagebitmap/ImageBitmapOptions.h",
   "$blink_core_output_dir/input/InputDeviceCapabilitiesInit.cpp",
   "$blink_core_output_dir/input/InputDeviceCapabilitiesInit.h",
+  "$blink_core_output_dir/mojo/MojoCreateMessagePipeResult.cpp",
+  "$blink_core_output_dir/mojo/MojoCreateMessagePipeResult.h",
+  "$blink_core_output_dir/mojo/MojoHandleSignals.cpp",
+  "$blink_core_output_dir/mojo/MojoHandleSignals.h",
+  "$blink_core_output_dir/mojo/MojoReadMessageFlags.cpp",
+  "$blink_core_output_dir/mojo/MojoReadMessageFlags.h",
+  "$blink_core_output_dir/mojo/MojoReadMessageResult.cpp",
+  "$blink_core_output_dir/mojo/MojoReadMessageResult.h",
   "$blink_core_output_dir/offscreencanvas/ImageEncodeOptions.cpp",
   "$blink_core_output_dir/offscreencanvas/ImageEncodeOptions.h",
   "$blink_core_output_dir/page/scrolling/ScrollStateInit.cpp",
@@ -221,6 +229,8 @@
 ]
 
 generated_core_callback_function_files = [
+  "$bindings_core_v8_output_dir/MojoWatchCallback.cpp",
+  "$bindings_core_v8_output_dir/MojoWatchCallback.h",
   "$bindings_core_v8_output_dir/PerformanceObserverCallback.cpp",
   "$bindings_core_v8_output_dir/PerformanceObserverCallback.h",
 ]
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
index 38145b01..051c4551 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
@@ -808,13 +808,6 @@
   return valueWriter.takeWireString();
 }
 
-// static
-String ScriptValueSerializer::serializeNullValue() {
-  SerializedScriptValueWriter valueWriter;
-  valueWriter.writeNull();
-  return valueWriter.takeWireString();
-}
-
 ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerialize(
     v8::Local<v8::Value> value,
     StateBase* next) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
index c378d71..7e8a59fa 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
@@ -234,7 +234,6 @@
                                               ExceptionState&);
 
   static String serializeWTFString(const String&);
-  static String serializeNullValue();
 
  protected:
   class StateBase {
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
index 06ead69..a9edce8 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
@@ -132,7 +132,9 @@
 }
 
 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() {
-  return create(ScriptValueSerializer::serializeNullValue());
+  // UChar rather than uint8_t here to get host endian behavior.
+  static const UChar kNullData[] = {0xff09, 0x3000};
+  return create(reinterpret_cast<const char*>(kNullData), sizeof(kNullData));
 }
 
 String SerializedScriptValue::toWireString() const {
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
index 4da53c04..7e3a5d0 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
@@ -1087,5 +1087,14 @@
 // unshipped and likely to not use this mechanism when it does.
 // TODO(jbroman): Update this if that turns out not to be the case.
 
+TEST(V8ScriptValueSerializerTest, DecodeHardcodedNullValue) {
+  ScopedEnableV8BasedStructuredClone enable;
+  V8TestingScope scope;
+  EXPECT_TRUE(V8ScriptValueDeserializer(scope.getScriptState(),
+                                        SerializedScriptValue::nullValue())
+                  .deserialize()
+                  ->IsNull());
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/WebKit/Source/build/scripts/css_properties.py b/third_party/WebKit/Source/build/scripts/css_properties.py
index 0b80a98c..9c149799 100755
--- a/third_party/WebKit/Source/build/scripts/css_properties.py
+++ b/third_party/WebKit/Source/build/scripts/css_properties.py
@@ -59,3 +59,6 @@
             aliased_property = self._properties[name_utilities.enum_for_css_property(property['alias_for'])]
             property['enum_value'] = aliased_property['enum_value'] + 512
         self._properties_including_aliases += self._aliases
+
+    def properties(self):
+        return self._properties
diff --git a/third_party/WebKit/Source/build/scripts/json5_generator.py b/third_party/WebKit/Source/build/scripts/json5_generator.py
index 4c7a63d..5b7184b 100644
--- a/third_party/WebKit/Source/build/scripts/json5_generator.py
+++ b/third_party/WebKit/Source/build/scripts/json5_generator.py
@@ -152,7 +152,11 @@
             return entry
         if "name" not in item:
             raise Exception("Missing name in item: %s" % item)
+        if not self.parameters:
+            entry.update(item)
+            return entry
         entry["name"] = item.pop("name")
+        # Validate parameters if it's specified.
         for key, value in item.items():
             if key not in self.parameters:
                 raise Exception(
diff --git a/third_party/WebKit/Source/build/scripts/make_element_factory.py b/third_party/WebKit/Source/build/scripts/make_element_factory.py
index 5e9af05..68606172 100755
--- a/third_party/WebKit/Source/build/scripts/make_element_factory.py
+++ b/third_party/WebKit/Source/build/scripts/make_element_factory.py
@@ -30,7 +30,7 @@
 import sys
 from collections import defaultdict
 
-import in_generator
+import json5_generator
 import template_expander
 import name_utilities
 
@@ -38,23 +38,23 @@
 
 
 class MakeElementFactoryWriter(MakeQualifiedNamesWriter):
-    defaults = dict(MakeQualifiedNamesWriter.default_parameters, **{
-        'JSInterfaceName': None,
-        'Conditional': None,
-        'constructorNeedsCreatedByParser': None,
-        'interfaceName': None,
-        'noConstructor': None,
-        'noTypeHelpers': None,
-        'runtimeEnabled': None,
-    })
-    default_parameters = dict(MakeQualifiedNamesWriter.default_parameters, **{
+    default_parameters = {
+        'JSInterfaceName': {},
+        'Conditional': {},
+        'constructorNeedsCreatedByParser': {},
+        'interfaceName': {},
+        'noConstructor': {},
+        'noTypeHelpers': {},
+        'runtimeEnabled': {},
+    }
+    default_metadata = dict(MakeQualifiedNamesWriter.default_metadata, **{
         'fallbackInterfaceName': '',
         'fallbackJSInterfaceName': '',
     })
     filters = MakeQualifiedNamesWriter.filters
 
-    def __init__(self, in_file_paths):
-        super(MakeElementFactoryWriter, self).__init__(in_file_paths)
+    def __init__(self, json5_file_paths):
+        super(MakeElementFactoryWriter, self).__init__(json5_file_paths)
 
         # FIXME: When we start using these element factories, we'll want to
         # remove the "new" prefix and also have our base class generate
@@ -64,8 +64,8 @@
             (self.namespace + 'ElementFactory.cpp'): self.generate_factory_implementation,
         })
 
-        fallback_interface = self.tags_in_file.parameters['fallbackInterfaceName'].strip('"')
-        fallback_js_interface = self.tags_in_file.parameters['fallbackJSInterfaceName'].strip('"') or fallback_interface
+        fallback_interface = self.tags_json5_file.metadata['fallbackInterfaceName'].strip('"')
+        fallback_js_interface = self.tags_json5_file.metadata['fallbackJSInterfaceName'].strip('"') or fallback_interface
 
         interface_counts = defaultdict(int)
         tags = self._template_context['tags']
@@ -114,4 +114,4 @@
 
 
 if __name__ == "__main__":
-    in_generator.Maker(MakeElementFactoryWriter).main(sys.argv)
+    json5_generator.Maker(MakeElementFactoryWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_element_lookup_trie.py b/third_party/WebKit/Source/build/scripts/make_element_lookup_trie.py
index 5663f300..89b0d36b 100755
--- a/third_party/WebKit/Source/build/scripts/make_element_lookup_trie.py
+++ b/third_party/WebKit/Source/build/scripts/make_element_lookup_trie.py
@@ -29,21 +29,21 @@
 
 import sys
 
-import in_generator
+import json5_generator
 import trie_builder
 import template_expander
 
 
-class ElementLookupTrieWriter(in_generator.Writer):
+class ElementLookupTrieWriter(json5_generator.Writer):
     # FIXME: Inherit all these from somewhere.
-    defaults = {
-        'JSInterfaceName': None,
-        'constructorNeedsCreatedByParser': None,
-        'interfaceName': None,
-        'noConstructor': None,
-        'runtimeEnabled': None,
-    }
     default_parameters = {
+        'JSInterfaceName': {},
+        'constructorNeedsCreatedByParser': {},
+        'interfaceName': {},
+        'noConstructor': {},
+        'runtimeEnabled': {},
+    }
+    default_metadata = {
         'attrsNullNamespace': None,
         'export': '',
         'fallbackInterfaceName': '',
@@ -53,12 +53,12 @@
         'namespaceURI': '',
     }
 
-    def __init__(self, in_file_paths):
-        super(ElementLookupTrieWriter, self).__init__(in_file_paths)
+    def __init__(self, json5_file_paths):
+        super(ElementLookupTrieWriter, self).__init__(json5_file_paths)
         self._tags = {}
-        for entry in self.in_file.name_dictionaries:
+        for entry in self.json5_file.name_dictionaries:
             self._tags[entry['name']] = entry['name']
-        self._namespace = self.in_file.parameters['namespace'].strip('"')
+        self._namespace = self.json5_file.metadata['namespace'].strip('"')
         self._outputs = {
             (self._namespace + 'ElementLookupTrie.h'): self.generate_header,
             (self._namespace + 'ElementLookupTrie.cpp'): self.generate_implementation,
@@ -79,4 +79,4 @@
 
 
 if __name__ == '__main__':
-    in_generator.Maker(ElementLookupTrieWriter).main(sys.argv)
+    json5_generator.Maker(ElementLookupTrieWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_element_type_helpers.py b/third_party/WebKit/Source/build/scripts/make_element_type_helpers.py
index c6b4063..035bf730 100755
--- a/third_party/WebKit/Source/build/scripts/make_element_type_helpers.py
+++ b/third_party/WebKit/Source/build/scripts/make_element_type_helpers.py
@@ -7,31 +7,27 @@
 from collections import defaultdict
 
 import hasher
-import in_generator
+import json5_generator
 import name_utilities
 import template_expander
 
-from in_file import InFile
-
 
 def _symbol(tag):
-    # FIXME: Remove this special case for the ugly x-webkit-foo attributes.
-    if tag['name'].startswith('-webkit-'):
-        return tag['name'].replace('-', '_')[1:]
     return name_utilities.cpp_name(tag).replace('-', '_')
 
-class MakeElementTypeHelpersWriter(in_generator.Writer):
-    defaults = {
-        'Conditional': None,
-        'ImplementedAs': None,
-        'JSInterfaceName': None,
-        'constructorNeedsCreatedByParser': None,
-        'interfaceName': None,
-        'noConstructor': None,
-        'noTypeHelpers': None,
-        'runtimeEnabled': None,
-    }
+
+class MakeElementTypeHelpersWriter(json5_generator.Writer):
     default_parameters = {
+        'Conditional': {},
+        'ImplementedAs': {},
+        'JSInterfaceName': {},
+        'constructorNeedsCreatedByParser': {},
+        'interfaceName': {},
+        'noConstructor': {},
+        'noTypeHelpers': {},
+        'runtimeEnabled': {},
+    }
+    default_metadata = {
         'attrsNullNamespace': None,
         'export': '',
         'fallbackInterfaceName': '',
@@ -45,11 +41,11 @@
         'symbol': _symbol,
     }
 
-    def __init__(self, in_file_path):
-        super(MakeElementTypeHelpersWriter, self).__init__(in_file_path)
+    def __init__(self, json5_file_path):
+        super(MakeElementTypeHelpersWriter, self).__init__(json5_file_path)
 
-        self.namespace = self.in_file.parameters['namespace'].strip('"')
-        self.fallbackInterface = self.in_file.parameters['fallbackInterfaceName'].strip('"')
+        self.namespace = self.json5_file.metadata['namespace'].strip('"')
+        self.fallback_interface = self.json5_file.metadata['fallbackInterfaceName'].strip('"')
 
         assert self.namespace, 'A namespace is required.'
 
@@ -60,7 +56,7 @@
 
         self._template_context = {
             'namespace': self.namespace,
-            'tags': self.in_file.name_dictionaries,
+            'tags': self.json5_file.name_dictionaries,
             'elements': set(),
         }
 
@@ -73,7 +69,7 @@
             elements.add(tag['interface'])
 
         for tag in tags:
-            tag['multipleTagNames'] = (interface_counts[tag['interface']] > 1 or tag['interface'] == self.fallbackInterface)
+            tag['multipleTagNames'] = (interface_counts[tag['interface']] > 1 or tag['interface'] == self.fallback_interface)
 
     @template_expander.use_jinja("ElementTypeHelpers.h.tmpl", filters=filters)
     def generate_helper_header(self):
@@ -97,4 +93,4 @@
         return '%s%sElement' % (self.namespace, name)
 
 if __name__ == "__main__":
-    in_generator.Maker(MakeElementTypeHelpersWriter).main(sys.argv)
+    json5_generator.Maker(MakeElementTypeHelpersWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_internal_runtime_flags.py b/third_party/WebKit/Source/build/scripts/make_internal_runtime_flags.py
index 1313941..88d9de8 100755
--- a/third_party/WebKit/Source/build/scripts/make_internal_runtime_flags.py
+++ b/third_party/WebKit/Source/build/scripts/make_internal_runtime_flags.py
@@ -30,7 +30,7 @@
 import os.path
 import sys
 
-import in_generator
+import json5_generator
 import make_runtime_features
 import name_utilities
 import template_expander
@@ -41,8 +41,8 @@
 class InternalRuntimeFlagsWriter(make_runtime_features.RuntimeFeatureWriter):
     class_name = 'InternalRuntimeFlags'
 
-    def __init__(self, in_file_path):
-        super(InternalRuntimeFlagsWriter, self).__init__(in_file_path)
+    def __init__(self, json5_file_path):
+        super(InternalRuntimeFlagsWriter, self).__init__(json5_file_path)
         self._outputs = {(self.class_name + '.idl'): self.generate_idl,
                          (self.class_name + '.h'): self.generate_header,
                         }
@@ -64,4 +64,4 @@
 
 
 if __name__ == '__main__':
-    in_generator.Maker(InternalRuntimeFlagsWriter).main(sys.argv)
+    json5_generator.Maker(InternalRuntimeFlagsWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_origin_trials.py b/third_party/WebKit/Source/build/scripts/make_origin_trials.py
index e949346..e9fa2f7 100755
--- a/third_party/WebKit/Source/build/scripts/make_origin_trials.py
+++ b/third_party/WebKit/Source/build/scripts/make_origin_trials.py
@@ -29,7 +29,7 @@
 
 import sys
 
-import in_generator
+import json5_generator
 import make_runtime_features
 import name_utilities
 import template_expander
@@ -40,8 +40,8 @@
 class OriginTrialsWriter(make_runtime_features.RuntimeFeatureWriter):
     class_name = 'OriginTrials'
 
-    def __init__(self, in_file_path):
-        super(OriginTrialsWriter, self).__init__(in_file_path)
+    def __init__(self, json5_file_path):
+        super(OriginTrialsWriter, self).__init__(json5_file_path)
         self._outputs = {
             (self.class_name + '.cpp'): self.generate_implementation,
             (self.class_name + '.h'): self.generate_header,
@@ -61,4 +61,4 @@
 
 
 if __name__ == '__main__':
-    in_generator.Maker(OriginTrialsWriter).main(sys.argv)
+    json5_generator.Maker(OriginTrialsWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_qualified_names.py b/third_party/WebKit/Source/build/scripts/make_qualified_names.py
index a7d9d1a7..b9b5ff5 100755
--- a/third_party/WebKit/Source/build/scripts/make_qualified_names.py
+++ b/third_party/WebKit/Source/build/scripts/make_qualified_names.py
@@ -30,24 +30,20 @@
 import sys
 
 import hasher
-import in_generator
+import json5_generator
 import name_utilities
 import template_expander
 
-from in_file import InFile
+from json5_generator import Json5File
 
 
 def _symbol(entry):
-    # FIXME: Remove this special case for the ugly x-webkit-foo attributes.
-    if entry['name'].startswith('x-webkit-'):
-        return entry['name'].replace('-', '')[1:]
     return entry['name'].replace('-', '_')
 
 
-class MakeQualifiedNamesWriter(in_generator.Writer):
-    defaults = {
-    }
-    default_parameters = {
+class MakeQualifiedNamesWriter(json5_generator.Writer):
+    default_parameters = {}
+    default_metadata = {
         'attrsNullNamespace': None,
         'export': '',
         'namespace': '',
@@ -60,43 +56,44 @@
         'to_macro_style': name_utilities.to_macro_style,
     }
 
-    def __init__(self, in_file_paths):
+    def __init__(self, json5_file_paths):
         super(MakeQualifiedNamesWriter, self).__init__(None)
-        assert len(in_file_paths) <= 2, 'MakeQualifiedNamesWriter requires at most 2 in files, got %d.' % len(in_file_paths)
+        assert len(json5_file_paths) <= 2, 'MakeQualifiedNamesWriter requires at most 2 in files, got %d.' % len(json5_file_paths)
 
-        if len(in_file_paths) == 2:
-            self.tags_in_file = InFile.load_from_files([in_file_paths.pop(0)], self.defaults, self.valid_values, self.default_parameters)
+        if len(json5_file_paths) == 2:
+            self.tags_json5_file = Json5File.load_from_files(
+                [json5_file_paths.pop(0)], self.default_metadata, self.default_parameters)
         else:
-            self.tags_in_file = None
+            self.tags_json5_file = None
 
-        self.attrs_in_file = InFile.load_from_files([in_file_paths.pop()], self.defaults, self.valid_values, self.default_parameters)
+        self.attrs_json5_file = Json5File.load_from_files([json5_file_paths.pop()], self.default_metadata, self.default_parameters)
 
-        self.namespace = self._parameter('namespace')
+        self.namespace = self._metadata('namespace')
 
-        namespace_prefix = self._parameter('namespacePrefix') or self.namespace.lower()
-        namespace_uri = self._parameter('namespaceURI')
+        namespace_prefix = self._metadata('namespacePrefix') or self.namespace.lower()
+        namespace_uri = self._metadata('namespaceURI')
 
-        use_namespace_for_attrs = self.attrs_in_file.parameters['attrsNullNamespace'] is None
+        use_namespace_for_attrs = self.attrs_json5_file.metadata['attrsNullNamespace'] is None
 
         self._outputs = {
             (self.namespace + "Names.h"): self.generate_header,
             (self.namespace + "Names.cpp"): self.generate_implementation,
         }
         self._template_context = {
-            'attrs': self.attrs_in_file.name_dictionaries,
-            'export': self._parameter('export'),
+            'attrs': self.attrs_json5_file.name_dictionaries,
+            'export': self._metadata('export'),
             'namespace': self.namespace,
             'namespace_prefix': namespace_prefix,
             'namespace_uri': namespace_uri,
-            'tags': self.tags_in_file.name_dictionaries if self.tags_in_file else [],
+            'tags': self.tags_json5_file.name_dictionaries if self.tags_json5_file else [],
             'use_namespace_for_attrs': use_namespace_for_attrs,
         }
 
-    def _parameter(self, name):
-        parameter = self.attrs_in_file.parameters[name].strip('"')
-        if self.tags_in_file:
-            assert parameter == self.tags_in_file.parameters[name].strip('"'), 'Both in files must have the same %s.' % name
-        return parameter
+    def _metadata(self, name):
+        metadata = self.attrs_json5_file.metadata[name].strip('"')
+        if self.tags_json5_file:
+            assert metadata == self.tags_json5_file.metadata[name].strip('"'), 'Both files must have the same %s.' % name
+        return metadata
 
     @template_expander.use_jinja('MakeQualifiedNames.h.tmpl', filters=filters)
     def generate_header(self):
@@ -107,5 +104,5 @@
         return self._template_context
 
 
-if __name__ == "__main__":
-    in_generator.Maker(MakeQualifiedNamesWriter).main(sys.argv)
+if __name__ == "__majson5__":
+    json5_generator.Maker(MakeQualifiedNamesWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_runtime_features.py b/third_party/WebKit/Source/build/scripts/make_runtime_features.py
index 24515df..9f647fb 100755
--- a/third_party/WebKit/Source/build/scripts/make_runtime_features.py
+++ b/third_party/WebKit/Source/build/scripts/make_runtime_features.py
@@ -29,38 +29,22 @@
 
 import sys
 
-import in_generator
+import json5_generator
 import name_utilities
 from name_utilities import lower_first
 import template_expander
 
 
-class RuntimeFeatureWriter(in_generator.Writer):
+class RuntimeFeatureWriter(json5_generator.Writer):
     class_name = 'RuntimeEnabledFeatures'
 
-    # FIXME: valid_values and defaults should probably roll into one object.
-    valid_values = {
-        'status': ['stable', 'experimental', 'test'],
-    }
-    defaults = {
-        'condition': None,
-        'custom': False,
-        'depends_on': [],
-        'feature_policy': None,
-        'implied_by': [],
-        'origin_trial_feature_name': None,
-        'origin_trial_os': [],
-        'settable_from_internals': False,
-        'status': None,
-    }
-
-    def __init__(self, in_file_path):
-        super(RuntimeFeatureWriter, self).__init__(in_file_path)
+    def __init__(self, json5_file_path):
+        super(RuntimeFeatureWriter, self).__init__(json5_file_path)
         self._outputs = {(self.class_name + '.h'): self.generate_header,
                          (self.class_name + '.cpp'): self.generate_implementation,
                         }
 
-        self._features = self.in_file.name_dictionaries
+        self._features = self.json5_file.name_dictionaries
         # Make sure the resulting dictionaries have all the keys we expect.
         for feature in self._features:
             feature['first_lowered_name'] = lower_first(feature['name'])
@@ -78,7 +62,7 @@
     def _feature_sets(self):
         # Another way to think of the status levels is as "sets of features"
         # which is how we're referring to them in this generator.
-        return list(self.valid_values['status'])
+        return self.json5_file.parameters['status']['valid_values']
 
     def _template_inputs(self):
         return {
@@ -97,4 +81,4 @@
 
 
 if __name__ == '__main__':
-    in_generator.Maker(RuntimeFeatureWriter).main(sys.argv)
+    json5_generator.Maker(RuntimeFeatureWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/scripts.gni b/third_party/WebKit/Source/build/scripts/scripts.gni
index 4b35a41..3738b76 100644
--- a/third_party/WebKit/Source/build/scripts/scripts.gni
+++ b/third_party/WebKit/Source/build/scripts/scripts.gni
@@ -17,6 +17,7 @@
   "$_scripts_dir/hasher.py",
   "$_scripts_dir/in_file.py",
   "$_scripts_dir/in_generator.py",
+  "$_scripts_dir/json5_generator.py",
   "$_scripts_dir/license.py",
   "$_scripts_dir/name_utilities.py",
   "$_scripts_dir/template_expander.py",
diff --git a/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl
index d329172..847f615 100644
--- a/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/RuntimeEnabledFeatures.h.tmpl
@@ -39,17 +39,8 @@
   {% if feature.custom %}
   static bool {{feature.first_lowered_name}}Enabled();
   {% else %}
-  {% if feature.condition %}
-#if ENABLE({{feature.condition}})
-  {% endif %}
   static void set{{feature.name}}Enabled(bool isEnabled) { is{{feature.name}}Enabled = isEnabled; }
   static bool {{feature.first_lowered_name}}Enabled() { return {{feature.enabled_condition}}; }
-  {% if feature.condition %}
-#else
-  static void set{{feature.name}}Enabled(bool) { }
-  static bool {{feature.first_lowered_name}}Enabled() { return false; }
-#endif
-  {% endif %}
 
   {% endif %}
   {% endfor %}
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index b17a69f7..02b4257 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -185,6 +185,7 @@
     "//third_party/WebKit/Source/core/layout",
     "//third_party/WebKit/Source/core/layout/svg",
     "//third_party/WebKit/Source/core/loader",
+    "//third_party/WebKit/Source/core/mojo",
     "//third_party/WebKit/Source/core/offscreencanvas",
     "//third_party/WebKit/Source/core/origin_trials",
     "//third_party/WebKit/Source/core/page",
@@ -381,7 +382,7 @@
 
   inputs = scripts_for_in_files + [
              "../build/scripts/make_internal_runtime_flags.py",
-             "../platform/RuntimeEnabledFeatures.in",
+             "../platform/RuntimeEnabledFeatures.json5",
              "../build/scripts/templates/InternalRuntimeFlags.h.tmpl",
              "../build/scripts/templates/InternalRuntimeFlags.idl.tmpl",
            ]
@@ -391,7 +392,7 @@
   ]
 
   args = [
-    rebase_path("../platform/RuntimeEnabledFeatures.in", root_build_dir),
+    rebase_path("../platform/RuntimeEnabledFeatures.json5", root_build_dir),
     "--output_dir",
     "$rel_blink_core_gen_dir/testing",
   ]
@@ -509,8 +510,8 @@
   script = "../build/scripts/make_element_factory.py"
 
   in_files = [
-    "html/HTMLTagNames.in",
-    "html/HTMLAttributeNames.in",
+    "html/HTMLTagNames.json5",
+    "html/HTMLAttributeNames.json5",
   ]
   other_inputs = make_element_factory_files
   outputs = [
@@ -524,7 +525,7 @@
 process_in_files("make_core_generated_html_element_type_helpers") {
   script = "../build/scripts/make_element_type_helpers.py"
 
-  in_files = [ "html/HTMLTagNames.in" ]
+  in_files = [ "html/HTMLTagNames.json5" ]
   other_inputs = make_element_type_helpers_files
   outputs = [
     "$blink_core_output_dir/HTMLElementTypeHelpers.cpp",
@@ -536,8 +537,8 @@
   script = "../build/scripts/make_element_factory.py"
 
   in_files = [
-    "svg/SVGTagNames.in",
-    "svg/SVGAttributeNames.in",
+    "svg/SVGTagNames.json5",
+    "svg/SVGAttributeNames.json5",
   ]
   other_inputs = make_element_factory_files
   outputs = [
@@ -551,7 +552,7 @@
 process_in_files("make_core_generated_svg_element_type_helpers") {
   script = "../build/scripts/make_element_type_helpers.py"
 
-  in_files = [ "svg/SVGTagNames.in" ]
+  in_files = [ "svg/SVGTagNames.json5" ]
   other_inputs = make_element_type_helpers_files
   outputs = [
     "$blink_core_output_dir/SVGElementTypeHelpers.h",
@@ -643,8 +644,8 @@
 
 make_qualified_names("make_core_generated_math_ml_names") {
   in_files = [
-    "html/parser/MathMLTagNames.in",
-    "html/parser/MathMLAttributeNames.in",
+    "html/parser/MathMLTagNames.json5",
+    "html/parser/MathMLAttributeNames.json5",
   ]
   outputs = [
     "$blink_core_output_dir/MathMLNames.cpp",
@@ -653,7 +654,7 @@
 }
 
 make_qualified_names("make_core_generated_xlink_names") {
-  in_files = [ "svg/xlinkattrs.in" ]
+  in_files = [ "svg/xlinkattrs.json5" ]
   outputs = [
     "$blink_core_output_dir/XLinkNames.cpp",
     "$blink_core_output_dir/XLinkNames.h",
@@ -661,7 +662,7 @@
 }
 
 make_qualified_names("make_core_generated_xml_ns_names") {
-  in_files = [ "xml/xmlnsattrs.in" ]
+  in_files = [ "xml/xmlnsattrs.json5" ]
   outputs = [
     "$blink_core_output_dir/XMLNSNames.cpp",
     "$blink_core_output_dir/XMLNSNames.h",
@@ -669,7 +670,7 @@
 }
 
 make_qualified_names("make_core_generated_xml_names") {
-  in_files = [ "xml/xmlattrs.in" ]
+  in_files = [ "xml/xmlattrs.json5" ]
   outputs = [
     "$blink_core_output_dir/XMLNames.cpp",
     "$blink_core_output_dir/XMLNames.h",
@@ -773,7 +774,7 @@
   visibility = [ ":*" ]
   script = "../build/scripts/make_element_lookup_trie.py"
 
-  input_file = "html/HTMLTagNames.in"
+  input_file = "html/HTMLTagNames.json5"
   inputs = make_trie_helpers_files + [
              input_file,
              "../build/scripts/templates/ElementLookupTrie.cpp.tmpl",
@@ -804,7 +805,7 @@
 
   inputs = scripts_for_in_files + [
              "../build/scripts/make_origin_trials.py",
-             "../platform/RuntimeEnabledFeatures.in",
+             "../platform/RuntimeEnabledFeatures.json5",
              "../build/scripts/templates/OriginTrials.cpp.tmpl",
              "../build/scripts/templates/OriginTrials.h.tmpl",
            ]
@@ -814,7 +815,7 @@
   ]
 
   args = [
-    rebase_path("../platform/RuntimeEnabledFeatures.in", root_build_dir),
+    rebase_path("../platform/RuntimeEnabledFeatures.json5", root_build_dir),
     "--output_dir",
     "$rel_blink_core_gen_dir/origin_trials",
   ]
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index e6a0ab4..5cf4523 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -289,6 +289,9 @@
                                  "input/InputDeviceCapabilities.idl",
                                  "inspector/InspectorOverlayHost.idl",
                                  "loader/appcache/ApplicationCache.idl",
+                                 "mojo/Mojo.idl",
+                                 "mojo/MojoHandle.idl",
+                                 "mojo/MojoWatcher.idl",
                                  "page/PagePopupController.idl",
                                  "page/scrolling/ScrollState.idl",
                                  "page/scrolling/ScrollStateCallback.idl",
@@ -563,6 +566,10 @@
                     "html/track/TrackEventInit.idl",
                     "imagebitmap/ImageBitmapOptions.idl",
                     "input/InputDeviceCapabilitiesInit.idl",
+                    "mojo/MojoCreateMessagePipeResult.idl",
+                    "mojo/MojoHandleSignals.idl",
+                    "mojo/MojoReadMessageFlags.idl",
+                    "mojo/MojoReadMessageResult.idl",
                     "offscreencanvas/ImageEncodeOptions.idl",
                     "page/scrolling/ScrollStateInit.idl",
                     "timing/PerformanceObserverInit.idl",
diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.cpp b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
index 34c9a1c8..4c937826 100644
--- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
@@ -365,8 +365,11 @@
                           ExceptionState& exceptionState) {
   DCHECK(node);
 
-  if (!isAvailable())
+  if (rangeCount() == 0) {
+    exceptionState.throwDOMException(
+        InvalidStateError, "This Selection object doesn't have any Ranges.");
     return;
+  }
 
   if (offset < 0) {
     exceptionState.throwDOMException(
diff --git a/third_party/WebKit/Source/core/editing/DragCaret.cpp b/third_party/WebKit/Source/core/editing/DragCaret.cpp
index 9a9a4b4..60636c51 100644
--- a/third_party/WebKit/Source/core/editing/DragCaret.cpp
+++ b/third_party/WebKit/Source/core/editing/DragCaret.cpp
@@ -33,7 +33,7 @@
 
 namespace blink {
 
-DragCaret::DragCaret() : m_caretBase(new CaretDisplayItemClient()) {}
+DragCaret::DragCaret() : m_displayItemClient(new CaretDisplayItemClient()) {}
 
 DragCaret::~DragCaret() = default;
 
@@ -42,15 +42,15 @@
 }
 
 void DragCaret::clearPreviousVisualRect(const LayoutBlock& block) {
-  m_caretBase->clearPreviousVisualRect(block);
+  m_displayItemClient->clearPreviousVisualRect(block);
 }
 
 void DragCaret::layoutBlockWillBeDestroyed(const LayoutBlock& block) {
-  m_caretBase->layoutBlockWillBeDestroyed(block);
+  m_displayItemClient->layoutBlockWillBeDestroyed(block);
 }
 
 void DragCaret::updateStyleAndLayoutIfNeeded() {
-  m_caretBase->updateStyleAndLayoutIfNeeded(
+  m_displayItemClient->updateStyleAndLayoutIfNeeded(
       rootEditableElementOf(m_position.position()) ? m_position
                                                    : PositionWithAffinity());
 }
@@ -58,7 +58,7 @@
 void DragCaret::invalidatePaintIfNeeded(const LayoutBlock& block,
                                         const PaintInvalidatorContext& context,
                                         PaintInvalidationReason reason) {
-  m_caretBase->invalidatePaintIfNeeded(block, context, reason);
+  m_displayItemClient->invalidatePaintIfNeeded(block, context, reason);
 }
 
 bool DragCaret::isContentRichlyEditable() const {
@@ -108,14 +108,16 @@
 }
 
 bool DragCaret::shouldPaintCaret(const LayoutBlock& block) const {
-  return m_caretBase->shouldPaintCaret(block);
+  return m_displayItemClient->shouldPaintCaret(block);
 }
 
 void DragCaret::paintDragCaret(const LocalFrame* frame,
                                GraphicsContext& context,
                                const LayoutPoint& paintOffset) const {
-  if (m_position.anchorNode()->document().frame() == frame)
-    m_caretBase->paintCaret(context, paintOffset, DisplayItem::kDragCaret);
+  if (m_position.anchorNode()->document().frame() != frame)
+    return;
+  m_displayItemClient->paintCaret(context, paintOffset,
+                                  DisplayItem::kDragCaret);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/DragCaret.h b/third_party/WebKit/Source/core/editing/DragCaret.h
index 5a06890c..75aa640 100644
--- a/third_party/WebKit/Source/core/editing/DragCaret.h
+++ b/third_party/WebKit/Source/core/editing/DragCaret.h
@@ -77,7 +77,7 @@
   void nodeWillBeRemoved(Node&) final;
 
   PositionWithAffinity m_position;
-  const std::unique_ptr<CaretDisplayItemClient> m_caretBase;
+  const std::unique_ptr<CaretDisplayItemClient> m_displayItemClient;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/FrameCaret.cpp b/third_party/WebKit/Source/core/editing/FrameCaret.cpp
index 002f3f74..a69dbed 100644
--- a/third_party/WebKit/Source/core/editing/FrameCaret.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameCaret.cpp
@@ -47,7 +47,7 @@
                        const SelectionEditor& selectionEditor)
     : m_selectionEditor(&selectionEditor),
       m_frame(frame),
-      m_caretBase(new CaretDisplayItemClient()),
+      m_displayItemClient(new CaretDisplayItemClient()),
       m_caretVisibility(CaretVisibility::Hidden),
       m_caretBlinkTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, &frame),
                         this,
@@ -64,7 +64,7 @@
 }
 
 const DisplayItemClient& FrameCaret::displayItemClient() const {
-  return *m_caretBase;
+  return *m_displayItemClient;
 }
 
 const PositionWithAffinity FrameCaret::caretPosition() const {
@@ -140,11 +140,11 @@
 }
 
 void FrameCaret::clearPreviousVisualRect(const LayoutBlock& block) {
-  m_caretBase->clearPreviousVisualRect(block);
+  m_displayItemClient->clearPreviousVisualRect(block);
 }
 
 void FrameCaret::layoutBlockWillBeDestroyed(const LayoutBlock& block) {
-  m_caretBase->layoutBlockWillBeDestroyed(block);
+  m_displayItemClient->layoutBlockWillBeDestroyed(block);
 }
 
 void FrameCaret::updateStyleAndLayoutIfNeeded() {
@@ -153,14 +153,14 @@
       m_caretVisibility == CaretVisibility::Visible &&
       m_selectionEditor->visibleSelection<EditingStrategy>().hasEditableStyle();
 
-  m_caretBase->updateStyleAndLayoutIfNeeded(
+  m_displayItemClient->updateStyleAndLayoutIfNeeded(
       shouldPaintCaret ? caretPosition() : PositionWithAffinity());
 }
 
 void FrameCaret::invalidatePaintIfNeeded(const LayoutBlock& block,
                                          const PaintInvalidatorContext& context,
                                          PaintInvalidationReason reason) {
-  m_caretBase->invalidatePaintIfNeeded(block, context, reason);
+  m_displayItemClient->invalidatePaintIfNeeded(block, context, reason);
 }
 
 bool FrameCaret::caretPositionIsValidForDocument(
@@ -206,12 +206,12 @@
 }
 
 bool FrameCaret::shouldPaintCaret(const LayoutBlock& block) const {
-  return m_caretBase->shouldPaintCaret(block);
+  return m_displayItemClient->shouldPaintCaret(block);
 }
 
 void FrameCaret::paintCaret(GraphicsContext& context,
                             const LayoutPoint& paintOffset) const {
-  m_caretBase->paintCaret(context, paintOffset, DisplayItem::kCaret);
+  m_displayItemClient->paintCaret(context, paintOffset, DisplayItem::kCaret);
 }
 
 bool FrameCaret::shouldBlinkCaret() const {
diff --git a/third_party/WebKit/Source/core/editing/FrameCaret.h b/third_party/WebKit/Source/core/editing/FrameCaret.h
index b546a80..390ffe26 100644
--- a/third_party/WebKit/Source/core/editing/FrameCaret.h
+++ b/third_party/WebKit/Source/core/editing/FrameCaret.h
@@ -104,7 +104,7 @@
 
   const Member<const SelectionEditor> m_selectionEditor;
   const Member<LocalFrame> m_frame;
-  const std::unique_ptr<CaretDisplayItemClient> m_caretBase;
+  const std::unique_ptr<CaretDisplayItemClient> m_displayItemClient;
   CaretVisibility m_caretVisibility;
   // TODO(https://crbug.com/668758): Consider using BeginFrame update for this.
   TaskRunnerTimer<FrameCaret> m_caretBlinkTimer;
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index 81f66ff..cd5cf67 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -19,6 +19,7 @@
   M57,
   M58,
   M59,
+  M60,
 };
 
 const char* milestoneString(Milestone milestone) {
@@ -34,6 +35,8 @@
       return "M58, around April 2017";
     case M59:
       return "M59, around June 2017";
+    case M60:
+      return "M60, around August 2017";
   }
 
   ASSERT_NOT_REACHED();
@@ -354,6 +357,16 @@
              "switching your application to a secure origin, such as HTTPS. "
              "See https://goo.gl/rStTGz for more details.";
 
+    case UseCounter::NotificationInsecureOrigin:
+    case UseCounter::NotificationAPIInsecureOriginIframe:
+    case UseCounter::NotificationPermissionRequestedInsecureOrigin:
+      return String::format(
+          "Using the Notification API on insecure origins is "
+          "deprecated and will be removed in %s. You should consider "
+          "switching your application to a secure origin, such as HTTPS. See "
+          "https://goo.gl/rStTGz for more details.",
+          milestoneString(M60));
+
     case UseCounter::ElementCreateShadowRootMultiple:
       return "Calling Element.createShadowRoot() for an element which already "
              "hosts a shadow root is deprecated. See "
diff --git a/third_party/WebKit/Source/core/frame/Settings.json5 b/third_party/WebKit/Source/core/frame/Settings.json5
index 57cbfe8..78d8a74 100644
--- a/third_party/WebKit/Source/core/frame/Settings.json5
+++ b/third_party/WebKit/Source/core/frame/Settings.json5
@@ -549,6 +549,11 @@
     },
 
     {
+      name: "encryptedMediaEnabled",
+      initial: true,
+    },
+
+    {
       name: "viewportEnabled",
       initial: false,
       invalidate: "ViewportDescription",
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp
index 95de635c..b16041f0 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.cpp
+++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -1246,7 +1246,6 @@
 }
 
 void UseCounter::count(Feature feature) {
-  DCHECK(Deprecation::deprecationMessage(feature).isEmpty());
   recordMeasurement(feature);
 }
 
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 7d2b9f1b..c5548f7 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -69,7 +69,7 @@
 
   UseCounter(Context = DefaultContext);
 
-  enum Feature {
+  enum Feature : uint32_t {
     // Do not change assigned numbers of existing items: add new features
     // to the end of the list.
     OBSOLETE_PageDestruction = 0,
@@ -1456,6 +1456,8 @@
     ServiceWorkerNavigationPreload = 1803,
     FullscreenRequestWithPendingElement = 1804,
     HTMLIFrameElementAllowfullscreenAttributeSetAfterContentLoad = 1805,
+    PointerEventSetCaptureOutsideDispatch = 1806,
+    NotificationPermissionRequestedInsecureOrigin = 1807,
 
     // Add new features immediately above this line. Don't change assigned
     // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/HTMLAttributeNames.in b/third_party/WebKit/Source/core/html/HTMLAttributeNames.in
deleted file mode 100644
index d7670e9..0000000
--- a/third_party/WebKit/Source/core/html/HTMLAttributeNames.in
+++ /dev/null
@@ -1,348 +0,0 @@
-namespace="HTML"
-namespacePrefix="xhtml"
-namespaceURI="http://www.w3.org/1999/xhtml"
-attrsNullNamespace
-export="CORE_EXPORT"
-
-abbr
-accept-charset
-accept
-accesskey
-action
-align
-alink
-allowfullscreen
-allowpaymentrequest
-alt
-archive
-aria-activedescendant
-aria-atomic
-aria-autocomplete
-aria-busy
-aria-checked
-aria-colcount
-aria-colindex
-aria-colspan
-aria-controls
-aria-current
-aria-describedby
-aria-details
-aria-disabled
-aria-dropeffect
-aria-errormessage
-aria-expanded
-aria-flowto
-aria-grabbed
-aria-haspopup
-aria-help
-aria-hidden
-aria-invalid
-aria-keyshortcuts
-aria-label
-aria-labeledby
-aria-labelledby
-aria-level
-aria-live
-aria-modal
-aria-multiline
-aria-multiselectable
-aria-orientation
-aria-owns
-aria-placeholder
-aria-posinset
-aria-pressed
-aria-readonly
-aria-relevant
-aria-required
-aria-roledescription
-aria-rowcount
-aria-rowindex
-aria-rowspan
-aria-selected
-aria-setsize
-aria-sort
-aria-valuemax
-aria-valuemin
-aria-valuenow
-aria-valuetext
-as
-async
-autocapitalize
-autocomplete
-autocorrect
-autofocus
-autoplay
-axis
-background
-behavior
-bgcolor
-border
-bordercolor
-capture
-cellpadding
-cellspacing
-char
-challenge
-charoff
-charset
-checked
-cite
-class
-classid
-clear
-code
-codebase
-codetype
-color
-cols
-colspan
-compact
-content
-contenteditable
-contextmenu
-controls
-coords
-crossorigin
-csp
-data
-datetime
-declare
-default
-defer
-dir
-direction
-dirname
-disabled
-disableremoteplayback
-download
-draggable
-webkitdropzone
-enctype
-end
-event
-face
-for
-form
-formaction
-formenctype
-formmethod
-formnovalidate
-formtarget
-frame
-frameborder
-headers
-height
-hidden
-high
-href
-hreflang
-hspace
-http-equiv
-icon
-id
-incremental
-inputmode
-integrity
-is
-ismap
-keytype
-kind
-label
-lang
-language
-leftmargin
-link
-list
-longdesc
-loop
-low
-lowsrc
-manifest
-marginheight
-marginwidth
-max
-maxlength
-mayscript
-media
-method
-min
-minlength
-multiple
-muted
-name
-nohref
-nonce
-noresize
-noshade
-novalidate
-nowrap
-object
-onabort
-onanimationstart
-onanimationiteration
-onanimationend
-onauxclick
-onbeforecopy
-onbeforecut
-onbeforepaste
-onbeforeunload
-onblur
-oncancel
-oncanplay
-oncanplaythrough
-onchange
-onclick
-onclose
-oncontextmenu
-oncopy
-oncuechange
-oncut
-ondblclick
-ondrag
-ondragend
-ondragenter
-ondragleave
-ondragover
-ondragstart
-ondrop
-ondurationchange
-onemptied
-onended
-onerror
-onfocus
-onfocusin
-onfocusout
-ongotpointercapture
-onhashchange
-oninput
-oninvalid
-onkeydown
-onkeypress
-onkeyup
-onlanguagechange
-onload
-onloadeddata
-onloadedmetadata
-onloadstart
-onlostpointercapture
-onmessage
-onmousedown
-onmouseenter
-onmouseleave
-onmousemove
-onmouseout
-onmouseover
-onmouseup
-onmousewheel
-ononline
-onoffline
-onorientationchange
-onpagehide
-onpageshow
-onpaste
-onpause
-onplay
-onplaying
-onpointercancel
-onpointerdown
-onpointerenter
-onpointerleave
-onpointermove
-onpointerout
-onpointerover
-onpointerup
-onpopstate
-onprogress
-onratechange
-onreset
-onresize
-onscroll
-onsearch
-onseeked
-onseeking
-onselect
-onselectstart
-onselectionchange
-onshow
-onstalled
-onstorage
-onsuspend
-onsubmit
-ontimeupdate
-ontoggle
-ontouchstart
-ontouchmove
-ontouchend
-ontouchcancel
-ontransitionend
-onunload
-onvolumechange
-onwaiting
-onwebkitanimationstart
-onwebkitanimationiteration
-onwebkitanimationend
-onwebkitfullscreenchange
-onwebkitfullscreenerror
-onwebkittransitionend
-onwheel
-open
-optimum
-pattern
-permissions
-placeholder
-ping
-poster
-preload
-pseudo
-radiogroup
-readonly
-referrerpolicy
-rel
-required
-rev
-reversed
-role
-rows
-rowspan
-rules
-sandbox
-scheme
-scope
-scrollamount
-scrolldelay
-scrolling
-select
-selected
-shape
-size
-sizes
-slot
-span
-spellcheck
-src
-srcset
-srcdoc
-srclang
-standby
-start
-step
-style
-summary
-tabindex
-target
-text
-title
-topmargin
-translate
-truespeed
-type
-usemap
-valign
-value
-valuetype
-version
-vlink
-vspace
-webkitdirectory
-width
-wrap
diff --git a/third_party/WebKit/Source/core/html/HTMLAttributeNames.json5 b/third_party/WebKit/Source/core/html/HTMLAttributeNames.json5
new file mode 100644
index 0000000..0ad4d65e
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/HTMLAttributeNames.json5
@@ -0,0 +1,354 @@
+{
+  metadata: {
+    namespace: "HTML",
+    namespacePrefix: "xhtml",
+    namespaceURI: "http://www.w3.org/1999/xhtml",
+    attrsNullNamespace: true,
+    export: "CORE_EXPORT",
+  },
+
+  data: [
+    "abbr",
+    "accept-charset",
+    "accept",
+    "accesskey",
+    "action",
+    "align",
+    "alink",
+    "allowfullscreen",
+    "allowpaymentrequest",
+    "alt",
+    "archive",
+    "aria-activedescendant",
+    "aria-atomic",
+    "aria-autocomplete",
+    "aria-busy",
+    "aria-checked",
+    "aria-colcount",
+    "aria-colindex",
+    "aria-colspan",
+    "aria-controls",
+    "aria-current",
+    "aria-describedby",
+    "aria-details",
+    "aria-disabled",
+    "aria-dropeffect",
+    "aria-errormessage",
+    "aria-expanded",
+    "aria-flowto",
+    "aria-grabbed",
+    "aria-haspopup",
+    "aria-help",
+    "aria-hidden",
+    "aria-invalid",
+    "aria-keyshortcuts",
+    "aria-label",
+    "aria-labeledby",
+    "aria-labelledby",
+    "aria-level",
+    "aria-live",
+    "aria-modal",
+    "aria-multiline",
+    "aria-multiselectable",
+    "aria-orientation",
+    "aria-owns",
+    "aria-placeholder",
+    "aria-posinset",
+    "aria-pressed",
+    "aria-readonly",
+    "aria-relevant",
+    "aria-required",
+    "aria-roledescription",
+    "aria-rowcount",
+    "aria-rowindex",
+    "aria-rowspan",
+    "aria-selected",
+    "aria-setsize",
+    "aria-sort",
+    "aria-valuemax",
+    "aria-valuemin",
+    "aria-valuenow",
+    "aria-valuetext",
+    "as",
+    "async",
+    "autocapitalize",
+    "autocomplete",
+    "autocorrect",
+    "autofocus",
+    "autoplay",
+    "axis",
+    "background",
+    "behavior",
+    "bgcolor",
+    "border",
+    "bordercolor",
+    "capture",
+    "cellpadding",
+    "cellspacing",
+    "char",
+    "challenge",
+    "charoff",
+    "charset",
+    "checked",
+    "cite",
+    "class",
+    "classid",
+    "clear",
+    "code",
+    "codebase",
+    "codetype",
+    "color",
+    "cols",
+    "colspan",
+    "compact",
+    "content",
+    "contenteditable",
+    "contextmenu",
+    "controls",
+    "coords",
+    "crossorigin",
+    "csp",
+    "data",
+    "datetime",
+    "declare",
+    "default",
+    "defer",
+    "dir",
+    "direction",
+    "dirname",
+    "disabled",
+    "disableremoteplayback",
+    "download",
+    "draggable",
+    "webkitdropzone",
+    "enctype",
+    "end",
+    "event",
+    "face",
+    "for",
+    "form",
+    "formaction",
+    "formenctype",
+    "formmethod",
+    "formnovalidate",
+    "formtarget",
+    "frame",
+    "frameborder",
+    "headers",
+    "height",
+    "hidden",
+    "high",
+    "href",
+    "hreflang",
+    "hspace",
+    "http-equiv",
+    "icon",
+    "id",
+    "incremental",
+    "inputmode",
+    "integrity",
+    "is",
+    "ismap",
+    "keytype",
+    "kind",
+    "label",
+    "lang",
+    "language",
+    "leftmargin",
+    "link",
+    "list",
+    "longdesc",
+    "loop",
+    "low",
+    "lowsrc",
+    "manifest",
+    "marginheight",
+    "marginwidth",
+    "max",
+    "maxlength",
+    "mayscript",
+    "media",
+    "method",
+    "min",
+    "minlength",
+    "multiple",
+    "muted",
+    "name",
+    "nohref",
+    "nonce",
+    "noresize",
+    "noshade",
+    "novalidate",
+    "nowrap",
+    "object",
+    "onabort",
+    "onanimationstart",
+    "onanimationiteration",
+    "onanimationend",
+    "onauxclick",
+    "onbeforecopy",
+    "onbeforecut",
+    "onbeforepaste",
+    "onbeforeunload",
+    "onblur",
+    "oncancel",
+    "oncanplay",
+    "oncanplaythrough",
+    "onchange",
+    "onclick",
+    "onclose",
+    "oncontextmenu",
+    "oncopy",
+    "oncuechange",
+    "oncut",
+    "ondblclick",
+    "ondrag",
+    "ondragend",
+    "ondragenter",
+    "ondragleave",
+    "ondragover",
+    "ondragstart",
+    "ondrop",
+    "ondurationchange",
+    "onemptied",
+    "onended",
+    "onerror",
+    "onfocus",
+    "onfocusin",
+    "onfocusout",
+    "ongotpointercapture",
+    "onhashchange",
+    "oninput",
+    "oninvalid",
+    "onkeydown",
+    "onkeypress",
+    "onkeyup",
+    "onlanguagechange",
+    "onload",
+    "onloadeddata",
+    "onloadedmetadata",
+    "onloadstart",
+    "onlostpointercapture",
+    "onmessage",
+    "onmousedown",
+    "onmouseenter",
+    "onmouseleave",
+    "onmousemove",
+    "onmouseout",
+    "onmouseover",
+    "onmouseup",
+    "onmousewheel",
+    "ononline",
+    "onoffline",
+    "onorientationchange",
+    "onpagehide",
+    "onpageshow",
+    "onpaste",
+    "onpause",
+    "onplay",
+    "onplaying",
+    "onpointercancel",
+    "onpointerdown",
+    "onpointerenter",
+    "onpointerleave",
+    "onpointermove",
+    "onpointerout",
+    "onpointerover",
+    "onpointerup",
+    "onpopstate",
+    "onprogress",
+    "onratechange",
+    "onreset",
+    "onresize",
+    "onscroll",
+    "onsearch",
+    "onseeked",
+    "onseeking",
+    "onselect",
+    "onselectstart",
+    "onselectionchange",
+    "onshow",
+    "onstalled",
+    "onstorage",
+    "onsuspend",
+    "onsubmit",
+    "ontimeupdate",
+    "ontoggle",
+    "ontouchstart",
+    "ontouchmove",
+    "ontouchend",
+    "ontouchcancel",
+    "ontransitionend",
+    "onunload",
+    "onvolumechange",
+    "onwaiting",
+    "onwebkitanimationstart",
+    "onwebkitanimationiteration",
+    "onwebkitanimationend",
+    "onwebkitfullscreenchange",
+    "onwebkitfullscreenerror",
+    "onwebkittransitionend",
+    "onwheel",
+    "open",
+    "optimum",
+    "pattern",
+    "permissions",
+    "placeholder",
+    "ping",
+    "poster",
+    "preload",
+    "pseudo",
+    "radiogroup",
+    "readonly",
+    "referrerpolicy",
+    "rel",
+    "required",
+    "rev",
+    "reversed",
+    "role",
+    "rows",
+    "rowspan",
+    "rules",
+    "sandbox",
+    "scheme",
+    "scope",
+    "scrollamount",
+    "scrolldelay",
+    "scrolling",
+    "select",
+    "selected",
+    "shape",
+    "size",
+    "sizes",
+    "slot",
+    "span",
+    "spellcheck",
+    "src",
+    "srcset",
+    "srcdoc",
+    "srclang",
+    "standby",
+    "start",
+    "step",
+    "style",
+    "summary",
+    "tabindex",
+    "target",
+    "text",
+    "title",
+    "topmargin",
+    "translate",
+    "truespeed",
+    "type",
+    "usemap",
+    "valign",
+    "value",
+    "valuetype",
+    "version",
+    "vlink",
+    "vspace",
+    "webkitdirectory",
+    "width",
+    "wrap",
+  ],
+}
diff --git a/third_party/WebKit/Source/core/html/HTMLTagNames.in b/third_party/WebKit/Source/core/html/HTMLTagNames.in
deleted file mode 100644
index 0c8b5137..0000000
--- a/third_party/WebKit/Source/core/html/HTMLTagNames.in
+++ /dev/null
@@ -1,145 +0,0 @@
-namespace="HTML"
-namespacePrefix="xhtml"
-namespaceURI="http://www.w3.org/1999/xhtml"
-fallbackInterfaceName="HTMLUnknownElement"
-export="CORE_EXPORT"
-
-a interfaceName=HTMLAnchorElement
-abbr interfaceName=HTMLElement
-acronym interfaceName=HTMLElement
-address interfaceName=HTMLElement
-applet interfaceName=HTMLUnknownElement
-area
-article interfaceName=HTMLElement
-aside interfaceName=HTMLElement
-audio
-b interfaceName=HTMLElement
-base
-basefont interfaceName=HTMLElement
-bdi interfaceName=HTMLBDIElement, JSInterfaceName=HTMLElement
-bdo interfaceName=HTMLElement
-bgsound interfaceName=HTMLUnknownElement
-big interfaceName=HTMLElement
-blockquote interfaceName=HTMLQuoteElement
-body
-br interfaceName=HTMLBRElement
-button
-canvas
-caption interfaceName=HTMLTableCaptionElement
-center interfaceName=HTMLElement
-cite interfaceName=HTMLElement
-code interfaceName=HTMLElement
-col interfaceName=HTMLTableColElement
-colgroup interfaceName=HTMLTableColElement
-command interfaceName=HTMLUnknownElement
-content interfaceName=HTMLContentElement
-datalist interfaceName=HTMLDataListElement
-dd interfaceName=HTMLElement
-del interfaceName=HTMLModElement
-details
-dfn interfaceName=HTMLElement
-dir interfaceName=HTMLDirectoryElement
-dialog
-div
-dl interfaceName=HTMLDListElement
-dt interfaceName=HTMLElement
-em interfaceName=HTMLElement
-embed constructorNeedsCreatedByParser
-fieldset interfaceName=HTMLFieldSetElement
-figcaption interfaceName=HTMLElement
-figure interfaceName=HTMLElement
-font
-footer interfaceName=HTMLElement
-form
-frame
-frameset interfaceName=HTMLFrameSetElement
-h1 interfaceName=HTMLHeadingElement
-h2 interfaceName=HTMLHeadingElement
-h3 interfaceName=HTMLHeadingElement
-h4 interfaceName=HTMLHeadingElement
-h5 interfaceName=HTMLHeadingElement
-h6 interfaceName=HTMLHeadingElement
-head
-header interfaceName=HTMLElement
-hgroup interfaceName=HTMLElement
-hr interfaceName=HTMLHRElement
-html
-i interfaceName=HTMLElement
-iframe interfaceName=HTMLIFrameElement
-image interfaceName=HTMLUnknownElement
-img interfaceName=HTMLImageElement, constructorNeedsCreatedByParser
-input constructorNeedsCreatedByParser
-ins interfaceName=HTMLModElement
-kbd interfaceName=HTMLElement
-keygen interfaceName=HTMLUnknownElement
-label
-layer interfaceName=HTMLElement
-legend
-li interfaceName=HTMLLIElement
-link constructorNeedsCreatedByParser
-listing interfaceName=HTMLPreElement
-main interfaceName=HTMLElement
-map
-mark interfaceName=HTMLElement
-marquee
-menu
-menuitem interfaceName=HTMLMenuItemElement, runtimeEnabled=contextMenu
-meta
-meter interfaceName=HTMLMeterElement
-nav interfaceName=HTMLElement
-nobr interfaceName=HTMLElement
-noembed interfaceName=HTMLNoEmbedElement, JSInterfaceName=HTMLElement
-noframes interfaceName=HTMLElement
-nolayer interfaceName=HTMLElement
-object constructorNeedsCreatedByParser
-ol interfaceName=HTMLOListElement
-optgroup interfaceName=HTMLOptGroupElement
-option
-output
-shadow interfaceName=HTMLShadowElement
-p interfaceName=HTMLParagraphElement
-param
-picture interfaceName=HTMLPictureElement
-plaintext interfaceName=HTMLElement
-pre
-progress interfaceName=HTMLProgressElement
-q interfaceName=HTMLQuoteElement
-rb interfaceName=HTMLElement
-rp interfaceName=HTMLElement
-rt interfaceName=HTMLRTElement, JSInterfaceName=HTMLElement
-rtc interfaceName=HTMLElement
-ruby interfaceName=HTMLRubyElement, JSInterfaceName=HTMLElement
-s interfaceName=HTMLElement
-samp interfaceName=HTMLElement
-script constructorNeedsCreatedByParser
-section interfaceName=HTMLElement
-select
-slot interfaceName=HTMLSlotElement
-small interfaceName=HTMLElement
-source
-span
-strike interfaceName=HTMLElement
-strong interfaceName=HTMLElement
-style constructorNeedsCreatedByParser
-sub interfaceName=HTMLElement
-summary interfaceName=HTMLSummaryElement, JSInterfaceName=HTMLElement
-sup interfaceName=HTMLElement
-table
-tbody interfaceName=HTMLTableSectionElement
-td interfaceName=HTMLTableCellElement
-template
-textarea interfaceName=HTMLTextAreaElement
-tfoot interfaceName=HTMLTableSectionElement
-th interfaceName=HTMLTableCellElement
-thead interfaceName=HTMLTableSectionElement
-title
-tr interfaceName=HTMLTableRowElement
-track
-tt interfaceName=HTMLElement
-u interfaceName=HTMLElement
-ul interfaceName=HTMLUListElement
-var interfaceName=HTMLElement
-video
-wbr interfaceName=HTMLWBRElement, JSInterfaceName=HTMLElement
-xmp interfaceName=HTMLPreElement
-noscript interfaceName=HTMLNoScriptElement, JSInterfaceName=HTMLElement
diff --git a/third_party/WebKit/Source/core/html/HTMLTagNames.json5 b/third_party/WebKit/Source/core/html/HTMLTagNames.json5
new file mode 100644
index 0000000..5d65b245
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/HTMLTagNames.json5
@@ -0,0 +1,481 @@
+{
+  metadata: {
+    namespace: "HTML",
+    namespacePrefix: "xhtml",
+    namespaceURI: "http://www.w3.org/1999/xhtml",
+    fallbackInterfaceName: "HTMLUnknownElement",
+    export: "CORE_EXPORT",
+  },
+
+  data: [
+    {
+      name: "a",
+      interfaceName: "HTMLAnchorElement",
+    },
+    {
+      name: "abbr",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "acronym",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "address",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "applet",
+      interfaceName: "HTMLUnknownElement",
+    },
+    "area",
+    {
+      name: "article",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "aside",
+      interfaceName: "HTMLElement",
+    },
+    "audio",
+    {
+      name: "b",
+      interfaceName: "HTMLElement",
+    },
+    "base",
+    {
+      name: "basefont",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "bdi",
+      JSInterfaceName: "HTMLElement",
+      interfaceName: "HTMLBDIElement",
+    },
+    {
+      name: "bdo",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "bgsound",
+      interfaceName: "HTMLUnknownElement",
+    },
+    {
+      name: "big",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "blockquote",
+      interfaceName: "HTMLQuoteElement",
+    },
+    "body",
+    {
+      name: "br",
+      interfaceName: "HTMLBRElement",
+    },
+    "button",
+    "canvas",
+    {
+      name: "caption",
+      interfaceName: "HTMLTableCaptionElement",
+    },
+    {
+      name: "center",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "cite",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "code",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "col",
+      interfaceName: "HTMLTableColElement",
+    },
+    {
+      name: "colgroup",
+      interfaceName: "HTMLTableColElement",
+    },
+    {
+      name: "command",
+      interfaceName: "HTMLUnknownElement",
+    },
+    {
+      name: "content",
+      interfaceName: "HTMLContentElement",
+    },
+    {
+      name: "datalist",
+      interfaceName: "HTMLDataListElement",
+    },
+    {
+      name: "dd",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "del",
+      interfaceName: "HTMLModElement",
+    },
+    "details",
+    {
+      name: "dfn",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "dir",
+      interfaceName: "HTMLDirectoryElement",
+    },
+    "dialog",
+    "div",
+    {
+      name: "dl",
+      interfaceName: "HTMLDListElement",
+    },
+    {
+      name: "dt",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "em",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "embed",
+      constructorNeedsCreatedByParser: true,
+    },
+    {
+      name: "fieldset",
+      interfaceName: "HTMLFieldSetElement",
+    },
+    {
+      name: "figcaption",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "figure",
+      interfaceName: "HTMLElement",
+    },
+    "font",
+    {
+      name: "footer",
+      interfaceName: "HTMLElement",
+    },
+    "form",
+    "frame",
+    {
+      name: "frameset",
+      interfaceName: "HTMLFrameSetElement",
+    },
+    {
+      name: "h1",
+      interfaceName: "HTMLHeadingElement",
+    },
+    {
+      name: "h2",
+      interfaceName: "HTMLHeadingElement",
+    },
+    {
+      name: "h3",
+      interfaceName: "HTMLHeadingElement",
+    },
+    {
+      name: "h4",
+      interfaceName: "HTMLHeadingElement",
+    },
+    {
+      name: "h5",
+      interfaceName: "HTMLHeadingElement",
+    },
+    {
+      name: "h6",
+      interfaceName: "HTMLHeadingElement",
+    },
+    "head",
+    {
+      name: "header",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "hgroup",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "hr",
+      interfaceName: "HTMLHRElement",
+    },
+    "html",
+    {
+      name: "i",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "iframe",
+      interfaceName: "HTMLIFrameElement",
+    },
+    {
+      name: "image",
+      interfaceName: "HTMLUnknownElement",
+    },
+    {
+      name: "img",
+      constructorNeedsCreatedByParser: true,
+      interfaceName: "HTMLImageElement",
+    },
+    {
+      name: "input",
+      constructorNeedsCreatedByParser: true,
+    },
+    {
+      name: "ins",
+      interfaceName: "HTMLModElement",
+    },
+    {
+      name: "kbd",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "keygen",
+      interfaceName: "HTMLUnknownElement",
+    },
+    "label",
+    {
+      name: "layer",
+      interfaceName: "HTMLElement",
+    },
+    "legend",
+    {
+      name: "li",
+      interfaceName: "HTMLLIElement",
+    },
+    {
+      name: "link",
+      constructorNeedsCreatedByParser: true,
+    },
+    {
+      name: "listing",
+      interfaceName: "HTMLPreElement",
+    },
+    {
+      name: "main",
+      interfaceName: "HTMLElement",
+    },
+    "map",
+    {
+      name: "mark",
+      interfaceName: "HTMLElement",
+    },
+    "marquee",
+    "menu",
+    {
+      name: "menuitem",
+      interfaceName: "HTMLMenuItemElement",
+      runtimeEnabled: "contextMenu",
+    },
+    "meta",
+    {
+      name: "meter",
+      interfaceName: "HTMLMeterElement",
+    },
+    {
+      name: "nav",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "nobr",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "noembed",
+      JSInterfaceName: "HTMLElement",
+      interfaceName: "HTMLNoEmbedElement",
+    },
+    {
+      name: "noframes",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "nolayer",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "object",
+      constructorNeedsCreatedByParser: true,
+    },
+    {
+      name: "ol",
+      interfaceName: "HTMLOListElement",
+    },
+    {
+      name: "optgroup",
+      interfaceName: "HTMLOptGroupElement",
+    },
+    "option",
+    "output",
+    {
+      name: "shadow",
+      interfaceName: "HTMLShadowElement",
+    },
+    {
+      name: "p",
+      interfaceName: "HTMLParagraphElement",
+    },
+    "param",
+    {
+      name: "picture",
+      interfaceName: "HTMLPictureElement",
+    },
+    {
+      name: "plaintext",
+      interfaceName: "HTMLElement",
+    },
+    "pre",
+    {
+      name: "progress",
+      interfaceName: "HTMLProgressElement",
+    },
+    {
+      name: "q",
+      interfaceName: "HTMLQuoteElement",
+    },
+    {
+      name: "rb",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "rp",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "rt",
+      JSInterfaceName: "HTMLElement",
+      interfaceName: "HTMLRTElement",
+    },
+    {
+      name: "rtc",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "ruby",
+      JSInterfaceName: "HTMLElement",
+      interfaceName: "HTMLRubyElement",
+    },
+    {
+      name: "s",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "samp",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "script",
+      constructorNeedsCreatedByParser: true,
+    },
+    {
+      name: "section",
+      interfaceName: "HTMLElement",
+    },
+    "select",
+    {
+      name: "slot",
+      interfaceName: "HTMLSlotElement",
+    },
+    {
+      name: "small",
+      interfaceName: "HTMLElement",
+    },
+    "source",
+    "span",
+    {
+      name: "strike",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "strong",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "style",
+      constructorNeedsCreatedByParser: true,
+    },
+    {
+      name: "sub",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "summary",
+      JSInterfaceName: "HTMLElement",
+      interfaceName: "HTMLSummaryElement",
+    },
+    {
+      name: "sup",
+      interfaceName: "HTMLElement",
+    },
+    "table",
+    {
+      name: "tbody",
+      interfaceName: "HTMLTableSectionElement",
+    },
+    {
+      name: "td",
+      interfaceName: "HTMLTableCellElement",
+    },
+    "template",
+    {
+      name: "textarea",
+      interfaceName: "HTMLTextAreaElement",
+    },
+    {
+      name: "tfoot",
+      interfaceName: "HTMLTableSectionElement",
+    },
+    {
+      name: "th",
+      interfaceName: "HTMLTableCellElement",
+    },
+    {
+      name: "thead",
+      interfaceName: "HTMLTableSectionElement",
+    },
+    "title",
+    {
+      name: "tr",
+      interfaceName: "HTMLTableRowElement",
+    },
+    "track",
+    {
+      name: "tt",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "u",
+      interfaceName: "HTMLElement",
+    },
+    {
+      name: "ul",
+      interfaceName: "HTMLUListElement",
+    },
+    {
+      name: "var",
+      interfaceName: "HTMLElement",
+    },
+    "video",
+    {
+      name: "wbr",
+      JSInterfaceName: "HTMLElement",
+      interfaceName: "HTMLWBRElement",
+    },
+    {
+      name: "xmp",
+      interfaceName: "HTMLPreElement",
+    },
+    {
+      name: "noscript",
+      JSInterfaceName: "HTMLElement",
+      interfaceName: "HTMLNoScriptElement",
+    },
+  ],
+}
diff --git a/third_party/WebKit/Source/core/html/parser/MathMLAttributeNames.in b/third_party/WebKit/Source/core/html/parser/MathMLAttributeNames.in
deleted file mode 100644
index 2277695..0000000
--- a/third_party/WebKit/Source/core/html/parser/MathMLAttributeNames.in
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace="MathML"
-namespaceURI="http://www.w3.org/1998/Math/MathML"
-attrsNullNamespace
-
-definitionURL
-encoding
diff --git a/third_party/WebKit/Source/core/html/parser/MathMLAttributeNames.json5 b/third_party/WebKit/Source/core/html/parser/MathMLAttributeNames.json5
new file mode 100644
index 0000000..464ce188
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/parser/MathMLAttributeNames.json5
@@ -0,0 +1,12 @@
+{
+  metadata: {
+    namespace: "MathML",
+    namespaceURI: "http://www.w3.org/1998/Math/MathML",
+    attrsNullNamespace: true,
+  },
+
+  data: [
+    "definitionURL",
+    "encoding",
+  ],
+}
diff --git a/third_party/WebKit/Source/core/html/parser/MathMLTagNames.in b/third_party/WebKit/Source/core/html/parser/MathMLTagNames.in
deleted file mode 100644
index 80d830f..0000000
--- a/third_party/WebKit/Source/core/html/parser/MathMLTagNames.in
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace="MathML"
-namespaceURI="http://www.w3.org/1998/Math/MathML"
-
-math
-mi
-mn
-mo
-mtext
-ms
-mglyph
-malignmark
-annotation-xml
diff --git a/third_party/WebKit/Source/core/html/parser/MathMLTagNames.json5 b/third_party/WebKit/Source/core/html/parser/MathMLTagNames.json5
new file mode 100644
index 0000000..4326dd7
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/parser/MathMLTagNames.json5
@@ -0,0 +1,18 @@
+{
+  metadata: {
+    namespace: "MathML",
+    namespaceURI: "http://www.w3.org/1998/Math/MathML",
+  },
+
+  data: [
+    "math",
+    "mi",
+    "mn",
+    "mo",
+    "mtext",
+    "ms",
+    "mglyph",
+    "malignmark",
+    "annotation-xml",
+  ],
+}
diff --git a/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h b/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h
index 6884ce8..496d5b6d 100644
--- a/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h
+++ b/third_party/WebKit/Source/core/html/track/LoadableTextTrack.h
@@ -33,6 +33,7 @@
 namespace blink {
 
 class HTMLTrackElement;
+class VTTRegion;
 
 class LoadableTextTrack final : public TextTrack {
  public:
diff --git a/third_party/WebKit/Source/core/html/track/TextTrack.cpp b/third_party/WebKit/Source/core/html/track/TextTrack.cpp
index ec558c2f..53ea365e8 100644
--- a/third_party/WebKit/Source/core/html/track/TextTrack.cpp
+++ b/third_party/WebKit/Source/core/html/track/TextTrack.cpp
@@ -301,57 +301,6 @@
   return nullptr;
 }
 
-void TextTrack::addRegion(VTTRegion* region) {
-  if (!region)
-    return;
-
-  VTTRegionList* regionList = ensureVTTRegionList();
-
-  // 1. If the given region is in a text track list of regions, then remove
-  // region from that text track list of regions.
-  TextTrack* regionTrack = region->track();
-  if (regionTrack && regionTrack != this)
-    regionTrack->removeRegion(region, ASSERT_NO_EXCEPTION);
-
-  // 2. If the method's TextTrack object's text track list of regions contains
-  // a region with the same identifier as region replace the values of that
-  // region's width, height, anchor point, viewport anchor point and scroll
-  // attributes with those of region.
-  VTTRegion* existingRegion = regionList->getRegionById(region->id());
-  if (existingRegion) {
-    existingRegion->updateParametersFromRegion(region);
-    return;
-  }
-
-  // Otherwise: add region to the method's TextTrack object's text track
-  // list of regions.
-  region->setTrack(this);
-  regionList->add(region);
-}
-
-void TextTrack::removeRegion(VTTRegion* region,
-                             ExceptionState& exceptionState) {
-  if (!region)
-    return;
-
-  // 1. If the given region is not currently listed in the method's TextTrack
-  // object's text track list of regions, then throw a NotFoundError exception.
-  if (region->track() != this) {
-    exceptionState.throwDOMException(NotFoundError,
-                                     "The specified region is not listed in "
-                                     "the TextTrack's list of regions.");
-    return;
-  }
-
-  if (!m_regions || !m_regions->remove(region)) {
-    exceptionState.throwDOMException(InvalidStateError,
-                                     "Failed to remove the specified region.");
-    return;
-  }
-
-  region->setTrack(0);
-}
-
 void TextTrack::cueWillChange(TextTrackCue* cue) {
   // The cue may need to be repositioned in the media element's interval tree,
   // may need to be re-rendered, etc, so remove it before the modification...
diff --git a/third_party/WebKit/Source/core/html/track/TextTrack.h b/third_party/WebKit/Source/core/html/track/TextTrack.h
index ccd7901a..ffca884 100644
--- a/third_party/WebKit/Source/core/html/track/TextTrack.h
+++ b/third_party/WebKit/Source/core/html/track/TextTrack.h
@@ -43,7 +43,6 @@
 class TextTrackCue;
 class TextTrackCueList;
 class TextTrackList;
-class VTTRegion;
 class VTTRegionList;
 
 class CORE_EXPORT TextTrack : public EventTargetWithInlineData,
@@ -102,8 +101,6 @@
   void removeCue(TextTrackCue*, ExceptionState&);
 
   VTTRegionList* regions();
-  void addRegion(VTTRegion*);
-  void removeRegion(VTTRegion*, ExceptionState&);
 
   void cueWillChange(TextTrackCue*);
   void cueDidChange(TextTrackCue*);
diff --git a/third_party/WebKit/Source/core/html/track/TextTrack.idl b/third_party/WebKit/Source/core/html/track/TextTrack.idl
index a174e74..4d1ea948 100644
--- a/third_party/WebKit/Source/core/html/track/TextTrack.idl
+++ b/third_party/WebKit/Source/core/html/track/TextTrack.idl
@@ -51,6 +51,4 @@
     // TODO(foolip): These WebVTT extensions have been removed from the spec:
     // https://www.w3.org/Bugs/Public/show_bug.cgi?id=24380
     [RuntimeEnabled=WebVTTRegions] readonly attribute VTTRegionList regions;
-    [RuntimeEnabled=WebVTTRegions] void addRegion(VTTRegion region);
-    [RaisesException, RuntimeEnabled=WebVTTRegions] void removeRegion(VTTRegion region);
 };
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.cpp b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
index 1d04ee4..6ca381f 100644
--- a/third_party/WebKit/Source/core/input/PointerEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
@@ -19,6 +19,7 @@
 #include "core/page/ChromeClient.h"
 #include "core/page/Page.h"
 #include "public/platform/WebTouchEvent.h"
+#include "wtf/AutoReset.h"
 
 namespace blink {
 
@@ -66,6 +67,7 @@
   m_nodeUnderPointer.clear();
   m_pointerCaptureTarget.clear();
   m_pendingPointerCaptureTarget.clear();
+  m_dispatchingPointerId = 0;
 }
 
 DEFINE_TRACE(PointerEventManager) {
@@ -143,6 +145,7 @@
 
   // Set whether node under pointer has received pointerover or not.
   const int pointerId = pointerEvent->pointerId();
+
   const AtomicString& eventType = pointerEvent->type();
   if ((eventType == EventTypeNames::pointerout ||
        eventType == EventTypeNames::pointerover) &&
@@ -159,11 +162,12 @@
   if (!RuntimeEnabledFeatures::pointerEventEnabled())
     return WebInputEventResult::NotHandled;
   if (!checkForListener || target->hasEventListeners(eventType)) {
-    UseCounter::count(m_frame->document(), UseCounter::PointerEventDispatch);
+    UseCounter::count(m_frame, UseCounter::PointerEventDispatch);
     if (eventType == EventTypeNames::pointerdown)
-      UseCounter::count(m_frame->document(),
-                        UseCounter::PointerEventDispatchPointerDown);
+      UseCounter::count(m_frame, UseCounter::PointerEventDispatchPointerDown);
 
+    DCHECK(!m_dispatchingPointerId);
+    AutoReset<int> dispatchHolder(&m_dispatchingPointerId, pointerId);
     DispatchEventResult dispatchResult = target->dispatchEvent(pointerEvent);
     return EventHandlingUtil::toWebInputEventResult(dispatchResult);
   }
@@ -629,9 +633,14 @@
 
 void PointerEventManager::setPointerCapture(int pointerId,
                                             EventTarget* target) {
-  UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture);
-  if (m_pointerEventFactory.isActiveButtonsState(pointerId))
+  UseCounter::count(m_frame, UseCounter::PointerEventSetCapture);
+  if (m_pointerEventFactory.isActiveButtonsState(pointerId)) {
+    if (pointerId != m_dispatchingPointerId) {
+      UseCounter::count(m_frame,
+                        UseCounter::PointerEventSetCaptureOutsideDispatch);
+    }
     m_pendingPointerCaptureTarget.set(pointerId, target);
+  }
 }
 
 void PointerEventManager::releasePointerCapture(int pointerId,
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.h b/third_party/WebKit/Source/core/input/PointerEventManager.h
index 0ba65f6..bc24fe9 100644
--- a/third_party/WebKit/Source/core/input/PointerEventManager.h
+++ b/third_party/WebKit/Source/core/input/PointerEventManager.h
@@ -223,6 +223,10 @@
   PointerEventFactory m_pointerEventFactory;
   Member<TouchEventManager> m_touchEventManager;
   Member<MouseEventManager> m_mouseEventManager;
+
+  // The pointerId of the PointerEvent currently being dispatched within this
+  // frame or 0 if none.
+  int m_dispatchingPointerId;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
index b4048d9..a9ac3b3 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
@@ -451,12 +451,13 @@
     layouter.setChildNeedsLayout(&section);
   if (!section.needsLayout())
     markChildForPaginationRelayoutIfNeeded(section, layouter);
-  section.layoutIfNeeded();
-  int sectionLogicalHeight = section.calcRowLogicalHeight();
-  section.setLogicalHeight(LayoutUnit(sectionLogicalHeight));
+  if (section.needsLayout()) {
+    section.layout();
+    section.setLogicalHeight(LayoutUnit(section.calcRowLogicalHeight()));
+  }
   if (view()->layoutState()->isPaginated())
     updateFragmentationInfoForChild(section);
-  setLogicalHeight(logicalHeight() + sectionLogicalHeight);
+  setLogicalHeight(logicalHeight() + section.logicalHeight());
 }
 
 LayoutUnit LayoutTable::logicalHeightFromStyle() const {
@@ -501,8 +502,8 @@
     extraLogicalHeight -=
         section->distributeExtraLogicalHeightToRows(extraLogicalHeight);
 
-  // FIXME: We really would like to enable this ASSERT to ensure that all the
-  // extra space has been distributed.
+  // crbug.com/690087: We really would like to enable this ASSERT to ensure that
+  // all the extra space has been distributed.
   // However our current distribution algorithm does not round properly and thus
   // we can have some remaining height.
   // ASSERT(!topSection() || !extraLogicalHeight);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.h b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
index f7d6d1d..0254244 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
@@ -329,6 +329,8 @@
 
   bool isRepeatingHeaderGroup() const;
 
+  void layout() override;
+
  protected:
   void styleDidChange(StyleDifference, const ComputedStyle* oldStyle) override;
   bool nodeAtPoint(HitTestResult&,
@@ -343,8 +345,6 @@
 
   void willBeRemovedFromTree() override;
 
-  void layout() override;
-
   int borderSpacingForRow(unsigned row) const {
     return m_grid[row].rowLayoutObject ? table()->vBorderSpacing() : 0;
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/PRESUBMIT.py b/third_party/WebKit/Source/core/layout/ng/PRESUBMIT.py
deleted file mode 100644
index 0d4f77d..0000000
--- a/third_party/WebKit/Source/core/layout/ng/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +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.
-
-"""Presubmit script for LayoutNG.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-    results = []
-    results.extend(input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
-    return results
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index c58908fa..3c182f02 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -44,12 +44,9 @@
 
 // Updates the fragment's BFC offset if it's not already set.
 void UpdateFragmentBfcOffset(const NGLogicalOffset& offset,
-                             const NGConstraintSpace& space,
                              NGFragmentBuilder* builder) {
-  NGLogicalOffset fragment_offset =
-      space.IsNewFormattingContext() ? space.BfcOffset() : offset;
   if (!builder->BfcOffset())
-    builder->SetBfcOffset(fragment_offset);
+    builder->SetBfcOffset(offset);
 }
 
 // Adjusts content_size to respect the CSS "clear" property.
@@ -325,13 +322,13 @@
   return sizes;
 }
 
-NGLogicalOffset NGBlockLayoutAlgorithm::CalculateRelativeOffset(
-    const NGBoxFragment& fragment) {
+NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
+    const WTF::Optional<NGLogicalOffset>& known_fragment_offset) {
   LayoutUnit inline_offset =
       border_and_padding_.inline_start + curr_child_margins_.inline_start;
   LayoutUnit block_offset = content_size_;
-  if (fragment.BfcOffset()) {
-    block_offset = fragment.BfcOffset().value().block_offset -
+  if (known_fragment_offset) {
+    block_offset = known_fragment_offset.value().block_offset -
                    builder_->BfcOffset().value().block_offset;
   }
   return {inline_offset, block_offset};
@@ -456,8 +453,7 @@
   // Non empty blocks always know their position in space:
   if (block_size) {
     curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
-    UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(),
-                            builder_.get());
+    UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get());
     PositionPendingFloats(curr_bfc_offset_, builder_.get());
   }
 
@@ -527,31 +523,39 @@
     return;
   }
 
-  // Fragment that knows its offset can be used to set parent's BFC position.
-  if (fragment.BfcOffset()) {
+  // Determine the fragment's position in the parent space either by using
+  // content_size_ or known fragment's BFC offset.
+  WTF::Optional<NGLogicalOffset> bfc_offset;
+  if (CurrentChildConstraintSpace().IsNewFormattingContext()) {
+    curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
+    bfc_offset = curr_bfc_offset_;
+  } else if (fragment.BfcOffset()) {
+    // Fragment that knows its offset can be used to set parent's BFC position.
     curr_bfc_offset_.block_offset = fragment.BfcOffset().value().block_offset;
-    UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(),
-                            builder_.get());
+    bfc_offset = curr_bfc_offset_;
+  }
+  if (bfc_offset) {
+    UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get());
     PositionPendingFloats(curr_bfc_offset_, builder_.get());
   }
-  NGLogicalOffset fragment_offset = CalculateRelativeOffset(fragment);
+  NGLogicalOffset logical_offset = CalculateLogicalOffset(bfc_offset);
 
   if (fragmentainer_mapper_)
-    fragmentainer_mapper_->ToVisualOffset(fragment_offset);
+    fragmentainer_mapper_->ToVisualOffset(logical_offset);
   else
-    fragment_offset.block_offset -= PreviousBreakOffset();
+    logical_offset.block_offset -= PreviousBreakOffset();
 
   // Update margin strut.
   curr_margin_strut_ = fragment.EndMarginStrut();
   curr_margin_strut_.Append(curr_child_margins_.block_end);
 
-  content_size_ = fragment.BlockSize() + fragment_offset.block_offset;
+  content_size_ = fragment.BlockSize() + logical_offset.block_offset;
   max_inline_size_ =
       std::max(max_inline_size_, fragment.InlineSize() +
                                      curr_child_margins_.InlineSum() +
                                      border_and_padding_.InlineSum());
 
-  builder_->AddChild(std::move(physical_fragment), fragment_offset);
+  builder_->AddChild(std::move(physical_fragment), logical_offset);
 }
 
 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling(
@@ -749,8 +753,7 @@
   // https://software.hixie.ch/utilities/js/live-dom-viewer/saved/4847
   if (current_child_style.clear() != EClear::kNone) {
     curr_bfc_offset_.block_offset += curr_margin_strut_.Sum();
-    UpdateFragmentBfcOffset(curr_bfc_offset_, ConstraintSpace(),
-                            builder_.get());
+    UpdateFragmentBfcOffset(curr_bfc_offset_, builder_.get());
     // Only collapse margins if it's an adjoining block with clearance.
     if (!content_size_) {
       curr_margin_strut_ = NGMarginStrut();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
index a9fe01b..d2962ed 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -18,7 +18,6 @@
 
 class ComputedStyle;
 class NGBlockBreakToken;
-class NGBoxFragment;
 class NGConstraintSpace;
 class NGConstraintSpaceBuilder;
 class NGInlineNode;
@@ -98,9 +97,13 @@
     return content_size_;
   }
 
-  // Calculates offset for the provided fragment which is relative to the
-  // fragment's parent.
-  NGLogicalOffset CalculateRelativeOffset(const NGBoxFragment& fragment);
+  // Calculates logical offset for the current fragment using either
+  // {@code content_size_} when the fragment doesn't know it's offset
+  // or {@code known_fragment_offset} if the fragment knows it's offset
+  // @return Fragment's offset relative to the fragment's parent.
+  NGLogicalOffset CalculateLogicalOffset(
+      const WTF::Optional<NGLogicalOffset>& known_fragment_offset);
+
   NGLogicalOffset GetChildSpaceOffset() const {
     return NGLogicalOffset(border_and_padding_.inline_start, content_size_);
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.h b/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
index 0306826f..6fb7ddd 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
@@ -59,9 +59,6 @@
     return fragment_ && !fragment_->BreakToken();
   }
 
-  // Used for debugging purposes only.
-  const LayoutBox* LegacyLayoutBox() const { return layout_box_; }
-
   DECLARE_VIRTUAL_TRACE();
 
   // Runs layout on layout_box_ and creates a fragment for the resulting
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
index b3edfc2..35622c7f 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space.h
@@ -110,7 +110,6 @@
 
   NGMarginStrut MarginStrut() const { return margin_strut_; }
 
-  // TODO(glebl): Rename to Offset() or AbsoluteOffset().
   NGLogicalOffset BfcOffset() const { return bfc_offset_; }
 
   DEFINE_INLINE_VIRTUAL_TRACE() {}
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
index 141a3d5..949178e 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_constraint_space_builder.cc
@@ -117,11 +117,18 @@
 }
 
 NGConstraintSpace* NGConstraintSpaceBuilder::ToConstraintSpace() {
+  // Exclusions do not pass the formatting context boundary.
+  std::shared_ptr<NGExclusions> exclusions(
+      is_new_fc_ ? std::make_shared<NGExclusions>() : exclusions_);
+
   // Whether the child and the containing block are parallel to each other.
   // Example: vertical-rl and vertical-lr
   bool is_in_parallel_flow = (parent_writing_mode_ == kHorizontalTopBottom) ==
                              (writing_mode_ == kHorizontalTopBottom);
 
+  NGLogicalOffset bfc_offset = is_new_fc_ ? NGLogicalOffset() : bfc_offset_;
+  NGMarginStrut margin_strut = is_new_fc_ ? NGMarginStrut() : margin_strut_;
+
   if (is_in_parallel_flow) {
     return new NGConstraintSpace(
         static_cast<NGWritingMode>(writing_mode_),
@@ -134,7 +141,7 @@
         is_inline_direction_triggers_scrollbar_,
         is_block_direction_triggers_scrollbar_,
         static_cast<NGFragmentationType>(fragmentation_type_), is_new_fc_,
-        margin_strut_, bfc_offset_, exclusions_);
+        margin_strut, bfc_offset, exclusions);
   }
 
   return new NGConstraintSpace(
@@ -148,7 +155,7 @@
       is_block_direction_triggers_scrollbar_,
       is_inline_direction_triggers_scrollbar_,
       static_cast<NGFragmentationType>(fragmentation_type_), is_new_fc_,
-      margin_strut_, bfc_offset_, exclusions_);
+      margin_strut, bfc_offset, exclusions);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index f773065..be2a44ff 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1195,6 +1195,14 @@
     return;
   }
 
+  // PlzNavigate
+  // If the loader classifies this navigation as a different document navigation
+  // while the browser intended the navigation to be same-document, it means
+  // that a different navigation must have committed while the IPC was sent.
+  // This navigation is no more same-document. The navigation is simply dropped.
+  if (request.resourceRequest().isSameDocumentNavigation())
+    return;
+
   startLoad(request, newLoadType, policy);
 }
 
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
index aa01a1e0..4e87f14 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
@@ -30,6 +30,7 @@
 
 #include "core/loader/resource/ImageResource.h"
 
+#include <memory>
 #include "core/loader/resource/MockImageResourceClient.h"
 #include "core/loader/resource/MockImageResourceObserver.h"
 #include "platform/SharedBuffer.h"
@@ -44,8 +45,8 @@
 #include "platform/loader/fetch/ResourceLoader.h"
 #include "platform/loader/fetch/UniqueIdentifier.h"
 #include "platform/scheduler/test/fake_web_task_runner.h"
+#include "platform/testing/ScopedMockedURL.h"
 #include "platform/testing/TestingPlatformSupport.h"
-#include "platform/testing/URLTestHelpers.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebCachePolicy.h"
@@ -55,14 +56,15 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "wtf/PtrUtil.h"
 #include "wtf/text/Base64.h"
-#include <memory>
 
 namespace blink {
 
+using testing::ScopedMockedURLLoad;
+
 namespace {
 
 // An image of size 1x1.
-const unsigned char kJpegImage[] = {
+constexpr unsigned char kJpegImage[] = {
     0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
     0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x13,
     0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68,
@@ -111,7 +113,7 @@
 }
 
 // An image of size 50x50.
-const unsigned char kJpegImage2[] = {
+constexpr unsigned char kJpegImage2[] = {
     0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
     0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
     0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -141,18 +143,24 @@
 
 constexpr int kJpegImage2Width = 50;
 
-const char kSvgImage[] =
+constexpr char kSvgImage[] =
     "<svg width=\"200\" height=\"200\" xmlns=\"http://www.w3.org/2000/svg\" "
     "xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
     "<rect x=\"0\" y=\"0\" width=\"100px\" height=\"100px\" fill=\"red\"/>"
     "</svg>";
 
-const char kSvgImage2[] =
+constexpr char kSvgImage2[] =
     "<svg width=\"300\" height=\"300\" xmlns=\"http://www.w3.org/2000/svg\" "
     "xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
     "<rect x=\"0\" y=\"0\" width=\"200px\" height=\"200px\" fill=\"green\"/>"
     "</svg>";
 
+constexpr char kTestURL[] = "http://www.test.com/cancelTest.html";
+
+String GetTestFilePath() {
+  return testing::webTestDataPath("cancelTest.html");
+}
+
 void receiveResponse(ImageResource* imageResource,
                      const KURL& url,
                      const AtomicString& mimeType,
@@ -197,30 +205,6 @@
   RefPtr<scheduler::FakeWebTaskRunner> m_runner;
 };
 
-// Convenience class that registers a mocked URL load on construction, and
-// unregisters it on destruction. This allows for a test to use constructs like
-// ASSERT_TRUE() without needing to worry about unregistering the mocked URL
-// load to avoid putting other tests into inconsistent states in case the
-// assertion fails.
-// TODO(toyoshim): Generalize and move to platform/testing/URLTestHelpers.
-class ScopedRegisteredURL {
- public:
-  ScopedRegisteredURL(const KURL& url,
-                      const String& fileName = "cancelTest.html",
-                      const String& mimeType = "text/html")
-      : m_url(url) {
-    URLTestHelpers::registerMockedURLLoad(
-        m_url, testing::webTestDataPath(fileName.utf8().data()), mimeType);
-  }
-
-  ~ScopedRegisteredURL() {
-    Platform::current()->getURLLoaderMockFactory()->unregisterURL(m_url);
-  }
-
- private:
-  KURL m_url;
-};
-
 AtomicString buildContentRange(size_t rangeLength, size_t totalLength) {
   return AtomicString(String("bytes 0-" + String::number(rangeLength) + "/" +
                              String::number(totalLength)));
@@ -229,8 +213,8 @@
 TEST(ImageResourceTest, MultipartImage) {
   ResourceFetcher* fetcher =
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   // Emulate starting a real load, but don't expect any "real"
   // WebURLLoaderClient callbacks.
@@ -308,8 +292,8 @@
 }
 
 TEST(ImageResourceTest, CancelOnRemoveObserver) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   ResourceFetcher* fetcher =
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
@@ -404,8 +388,8 @@
 }
 
 TEST(ImageResourceTest, ReloadIfLoFiOrPlaceholderAfterFinished) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
   ResourceRequest request = ResourceRequest(testURL);
   request.setPreviewsState(WebURLRequest::ServerLoFiOn);
   ImageResource* imageResource = ImageResource::create(request);
@@ -468,8 +452,8 @@
 }
 
 TEST(ImageResourceTest, ReloadIfLoFiOrPlaceholderDuringFetch) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   ResourceRequest request(testURL);
   request.setPreviewsState(WebURLRequest::ServerLoFiOn);
@@ -537,8 +521,8 @@
 }
 
 TEST(ImageResourceTest, ReloadIfLoFiOrPlaceholderForPlaceholder) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   ResourceFetcher* fetcher =
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
@@ -844,8 +828,8 @@
 }
 
 TEST(ImageResourceTest, CancelOnDecodeError) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   ResourceFetcher* fetcher =
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
@@ -872,8 +856,8 @@
 }
 
 TEST(ImageResourceTest, DecodeErrorWithEmptyBody) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   ResourceFetcher* fetcher =
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
@@ -902,8 +886,8 @@
 }
 
 TEST(ImageResourceTest, FetchDisallowPlaceholder) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   FetchRequest request(testURL, FetchInitiatorInfo());
   ImageResource* imageResource = ImageResource::fetch(
@@ -956,8 +940,8 @@
 }
 
 TEST(ImageResourceTest, FetchAllowPlaceholderPostRequest) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
   ResourceRequest resourceRequest(testURL);
   resourceRequest.setHTTPMethod("POST");
   FetchRequest request(resourceRequest, FetchInitiatorInfo());
@@ -975,8 +959,8 @@
 }
 
 TEST(ImageResourceTest, FetchAllowPlaceholderExistingRangeHeader) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
   ResourceRequest resourceRequest(testURL);
   resourceRequest.setHTTPHeaderField("range", "bytes=128-255");
   FetchRequest request(resourceRequest, FetchInitiatorInfo());
@@ -994,8 +978,8 @@
 }
 
 TEST(ImageResourceTest, FetchAllowPlaceholderSuccessful) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   FetchRequest request(testURL, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
@@ -1042,8 +1026,8 @@
 }
 
 TEST(ImageResourceTest, FetchAllowPlaceholderUnsuccessful) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   FetchRequest request(testURL, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
@@ -1101,8 +1085,8 @@
 }
 
 TEST(ImageResourceTest, FetchAllowPlaceholderThenDisallowPlaceholder) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   ResourceFetcher* fetcher =
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
@@ -1131,8 +1115,8 @@
 
 TEST(ImageResourceTest,
      FetchAllowPlaceholderThenDisallowPlaceholderAfterLoaded) {
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   ResourceFetcher* fetcher =
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
@@ -1183,8 +1167,8 @@
 TEST(ImageResourceTest, PeriodicFlushTest) {
   ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
       platform;
-  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
-  ScopedRegisteredURL scopedRegisteredURL(testURL);
+  KURL testURL(ParsedURLString, kTestURL);
+  ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
   ResourceRequest request = ResourceRequest(testURL);
   ImageResource* imageResource = ImageResource::create(request);
   imageResource->setStatus(ResourceStatus::Pending);
diff --git a/third_party/WebKit/Source/core/mojo/BUILD.gn b/third_party/WebKit/Source/core/mojo/BUILD.gn
new file mode 100644
index 0000000..d28d6fe
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/WebKit/Source/core/core.gni")
+
+blink_core_sources("mojo") {
+  sources = [
+    "Mojo.cpp",
+    "Mojo.h",
+    "MojoHandle.cpp",
+    "MojoHandle.h",
+    "MojoWatcher.cpp",
+    "MojoWatcher.h",
+  ]
+
+  deps = [
+    "//mojo/public/cpp/system",
+  ]
+}
diff --git a/third_party/WebKit/Source/core/mojo/DEPS b/third_party/WebKit/Source/core/mojo/DEPS
new file mode 100644
index 0000000..a3ad469
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+mojo/public/cpp/system",
+]
diff --git a/third_party/WebKit/Source/core/mojo/Mojo.cpp b/third_party/WebKit/Source/core/mojo/Mojo.cpp
new file mode 100644
index 0000000..8cddb11
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/Mojo.cpp
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/mojo/Mojo.h"
+
+#include "core/mojo/MojoCreateMessagePipeResult.h"
+#include "core/mojo/MojoHandle.h"
+
+namespace blink {
+
+// static
+void Mojo::createMessagePipe(MojoCreateMessagePipeResult& resultDict) {
+  MojoCreateMessagePipeOptions options = {0};
+  options.struct_size = sizeof(::MojoCreateMessagePipeOptions);
+  options.flags = MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE;
+
+  mojo::ScopedMessagePipeHandle handle0, handle1;
+  MojoResult result = mojo::CreateMessagePipe(&options, &handle0, &handle1);
+
+  resultDict.setResult(result);
+  if (result == MOJO_RESULT_OK) {
+    resultDict.setHandle0(
+        MojoHandle::create(mojo::ScopedHandle::From(std::move(handle0))));
+    resultDict.setHandle1(
+        MojoHandle::create(mojo::ScopedHandle::From(std::move(handle1))));
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/mojo/Mojo.h b/third_party/WebKit/Source/core/mojo/Mojo.h
new file mode 100644
index 0000000..0000bb3
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/Mojo.h
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Mojo_h
+#define Mojo_h
+
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace blink {
+
+class MojoCreateMessagePipeResult;
+
+class Mojo final : public GarbageCollected<Mojo>, public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  // MojoResult
+  static const MojoResult kResultOk = MOJO_RESULT_OK;
+  static const MojoResult kResultCancelled = MOJO_RESULT_CANCELLED;
+  static const MojoResult kResultUnknown = MOJO_RESULT_UNKNOWN;
+  static const MojoResult kResultInvalidArgument = MOJO_RESULT_INVALID_ARGUMENT;
+  static const MojoResult kResultDeadlineExceeded =
+      MOJO_RESULT_DEADLINE_EXCEEDED;
+  static const MojoResult kResultNotFound = MOJO_RESULT_NOT_FOUND;
+  static const MojoResult kResultAlreadyExists = MOJO_RESULT_ALREADY_EXISTS;
+  static const MojoResult kResultPermissionDenied =
+      MOJO_RESULT_PERMISSION_DENIED;
+  static const MojoResult kResultResourceExhausted =
+      MOJO_RESULT_RESOURCE_EXHAUSTED;
+  static const MojoResult kResultFailedPrecondition =
+      MOJO_RESULT_FAILED_PRECONDITION;
+  static const MojoResult kResultAborted = MOJO_RESULT_ABORTED;
+  static const MojoResult kResultOutOfRange = MOJO_RESULT_OUT_OF_RANGE;
+  static const MojoResult kResultUnimplemented = MOJO_RESULT_UNIMPLEMENTED;
+  static const MojoResult kResultInternal = MOJO_RESULT_INTERNAL;
+  static const MojoResult kResultUnavailable = MOJO_RESULT_UNAVAILABLE;
+  static const MojoResult kResultDataLoss = MOJO_RESULT_DATA_LOSS;
+  static const MojoResult kResultBusy = MOJO_RESULT_BUSY;
+  static const MojoResult kResultShouldWait = MOJO_RESULT_SHOULD_WAIT;
+
+  static void createMessagePipe(MojoCreateMessagePipeResult&);
+
+  DEFINE_INLINE_TRACE() {}
+};
+
+}  // namespace blink
+
+#endif  // Mojo_h
diff --git a/third_party/WebKit/Source/core/mojo/Mojo.idl b/third_party/WebKit/Source/core/mojo/Mojo.idl
new file mode 100644
index 0000000..55d0e477
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/Mojo.idl
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IDL for mojo core module. This is not a specced IDL.
+
+typedef unsigned long MojoResult;
+
+[
+    RuntimeEnabled=MojoJS,
+] interface Mojo {
+    const MojoResult RESULT_OK = 0;
+    const MojoResult RESULT_CANCELLED = 1;
+    const MojoResult RESULT_UNKNOWN = 2;
+    const MojoResult RESULT_INVALID_ARGUMENT = 3;
+    const MojoResult RESULT_DEADLINE_EXCEEDED = 4;
+    const MojoResult RESULT_NOT_FOUND = 5;
+    const MojoResult RESULT_ALREADY_EXISTS = 6;
+    const MojoResult RESULT_PERMISSION_DENIED = 7;
+    const MojoResult RESULT_RESOURCE_EXHAUSTED = 8;
+    const MojoResult RESULT_FAILED_PRECONDITION = 9;
+    const MojoResult RESULT_ABORTED = 10;
+    const MojoResult RESULT_OUT_OF_RANGE = 11;
+    const MojoResult RESULT_UNIMPLEMENTED = 12;
+    const MojoResult RESULT_INTERNAL = 13;
+    const MojoResult RESULT_UNAVAILABLE = 14;
+    const MojoResult RESULT_DATA_LOSS = 15;
+    const MojoResult RESULT_BUSY = 16;
+    const MojoResult RESULT_SHOULD_WAIT = 17;
+
+    static MojoCreateMessagePipeResult createMessagePipe();
+};
diff --git a/third_party/WebKit/Source/core/mojo/MojoCreateMessagePipeResult.idl b/third_party/WebKit/Source/core/mojo/MojoCreateMessagePipeResult.idl
new file mode 100644
index 0000000..eb2d1b0
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoCreateMessagePipeResult.idl
@@ -0,0 +1,10 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+dictionary MojoCreateMessagePipeResult {
+    // TODO(alokp): Consider raising exception for error.
+    required MojoResult result;
+    MojoHandle handle0;
+    MojoHandle handle1;
+};
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandle.cpp b/third_party/WebKit/Source/core/mojo/MojoHandle.cpp
new file mode 100644
index 0000000..0ae4277
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoHandle.cpp
@@ -0,0 +1,95 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/mojo/MojoHandle.h"
+
+#include "bindings/core/v8/ArrayBufferOrArrayBufferView.h"
+#include "bindings/core/v8/ScriptState.h"
+#include "core/dom/DOMArrayBuffer.h"
+#include "core/dom/DOMArrayBufferView.h"
+#include "core/mojo/MojoReadMessageFlags.h"
+#include "core/mojo/MojoReadMessageResult.h"
+#include "core/mojo/MojoWatcher.h"
+
+// Mojo messages typically do not contain many handles. In fact most
+// messages do not contain any handle. An inline capacity of 4 should avoid
+// heap allocation in vast majority of cases.
+static const size_t kHandleVectorInlineCapacity = 4;
+
+namespace blink {
+
+MojoHandle* MojoHandle::create(mojo::ScopedHandle handle) {
+  return new MojoHandle(std::move(handle));
+}
+
+MojoHandle::MojoHandle(mojo::ScopedHandle handle)
+    : m_handle(std::move(handle)) {}
+
+void MojoHandle::close() {
+  m_handle.reset();
+}
+
+MojoWatcher* MojoHandle::watch(ScriptState* scriptState,
+                               const MojoHandleSignals& signals,
+                               MojoWatchCallback* callback) {
+  return MojoWatcher::create(m_handle.get(), signals, callback,
+                             scriptState->getExecutionContext());
+}
+
+MojoResult MojoHandle::writeMessage(
+    ArrayBufferOrArrayBufferView& buffer,
+    const HeapVector<Member<MojoHandle>>& handles) {
+  // MojoWriteMessage takes ownership of the handles, so release them here.
+  Vector<::MojoHandle, kHandleVectorInlineCapacity> rawHandles(handles.size());
+  std::transform(
+      handles.begin(), handles.end(), rawHandles.begin(),
+      [](MojoHandle* handle) { return handle->m_handle.release().value(); });
+
+  const void* bytes = nullptr;
+  uint32_t numBytes = 0;
+  if (buffer.isArrayBuffer()) {
+    DOMArrayBuffer* array = buffer.getAsArrayBuffer();
+    bytes = array->data();
+    numBytes = array->byteLength();
+  } else {
+    DOMArrayBufferView* view = buffer.getAsArrayBufferView();
+    bytes = view->baseAddress();
+    numBytes = view->byteLength();
+  }
+
+  return MojoWriteMessage(m_handle->value(), bytes, numBytes, rawHandles.data(),
+                          rawHandles.size(), MOJO_WRITE_MESSAGE_FLAG_NONE);
+}
+
+void MojoHandle::readMessage(const MojoReadMessageFlags& flagsDict,
+                             MojoReadMessageResult& resultDict) {
+  ::MojoReadMessageFlags flags = MOJO_READ_MESSAGE_FLAG_NONE;
+  if (flagsDict.mayDiscard())
+    flags |= MOJO_READ_MESSAGE_FLAG_MAY_DISCARD;
+
+  uint32_t numBytes = 0, numHandles = 0;
+  MojoResult result = MojoReadMessage(m_handle->value(), nullptr, &numBytes,
+                                      nullptr, &numHandles, flags);
+  if (result != MOJO_RESULT_RESOURCE_EXHAUSTED) {
+    resultDict.setResult(result);
+    return;
+  }
+
+  DOMArrayBuffer* buffer = DOMArrayBuffer::createUninitialized(numBytes, 1);
+  Vector<::MojoHandle, kHandleVectorInlineCapacity> rawHandles(numHandles);
+  result = MojoReadMessage(m_handle->value(), buffer->data(), &numBytes,
+                           rawHandles.data(), &numHandles, flags);
+
+  HeapVector<Member<MojoHandle>> handles(numHandles);
+  for (size_t i = 0; i < numHandles; ++i) {
+    handles[i] =
+        MojoHandle::create(mojo::MakeScopedHandle(mojo::Handle(rawHandles[i])));
+  }
+
+  resultDict.setResult(result);
+  resultDict.setBuffer(buffer);
+  resultDict.setHandles(handles);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandle.h b/third_party/WebKit/Source/core/mojo/MojoHandle.h
new file mode 100644
index 0000000..78fa9138
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoHandle.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MojoHandle_h
+#define MojoHandle_h
+
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace blink {
+
+class ArrayBufferOrArrayBufferView;
+class MojoHandleSignals;
+class MojoReadMessageFlags;
+class MojoReadMessageResult;
+class MojoWatchCallback;
+class MojoWatcher;
+class ScriptState;
+
+class MojoHandle final : public GarbageCollectedFinalized<MojoHandle>,
+                         public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  CORE_EXPORT static MojoHandle* create(mojo::ScopedHandle);
+
+  void close();
+  MojoWatcher* watch(ScriptState*,
+                     const MojoHandleSignals&,
+                     MojoWatchCallback*);
+  MojoResult writeMessage(ArrayBufferOrArrayBufferView&,
+                          const HeapVector<Member<MojoHandle>>&);
+  void readMessage(const MojoReadMessageFlags&, MojoReadMessageResult&);
+
+  DEFINE_INLINE_TRACE() {}
+
+ private:
+  explicit MojoHandle(mojo::ScopedHandle);
+
+  mojo::ScopedHandle m_handle;
+};
+
+}  // namespace blink
+
+#endif  // MojoHandle_h
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandle.idl b/third_party/WebKit/Source/core/mojo/MojoHandle.idl
new file mode 100644
index 0000000..34b1dfc
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoHandle.idl
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+callback MojoWatchCallback = void (MojoResult result);
+
+[
+    RuntimeEnabled=MojoJS,
+] interface MojoHandle {
+    void close();
+    [CallWith=ScriptState] MojoWatcher watch(MojoHandleSignals signals, MojoWatchCallback callback);
+    MojoResult writeMessage(BufferSource buffer, sequence<MojoHandle> handles);
+    MojoReadMessageResult readMessage(optional MojoReadMessageFlags flags);
+};
diff --git a/third_party/WebKit/Source/core/mojo/MojoHandleSignals.idl b/third_party/WebKit/Source/core/mojo/MojoHandleSignals.idl
new file mode 100644
index 0000000..fe0f02d
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoHandleSignals.idl
@@ -0,0 +1,9 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+dictionary MojoHandleSignals {
+  boolean readable = false;
+  boolean writable = false;
+  boolean peerClosed = false;
+};
diff --git a/third_party/WebKit/Source/core/mojo/MojoReadMessageFlags.idl b/third_party/WebKit/Source/core/mojo/MojoReadMessageFlags.idl
new file mode 100644
index 0000000..3ab6e77
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoReadMessageFlags.idl
@@ -0,0 +1,7 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+dictionary MojoReadMessageFlags {
+  boolean mayDiscard = false;
+};
diff --git a/third_party/WebKit/Source/core/mojo/MojoReadMessageResult.idl b/third_party/WebKit/Source/core/mojo/MojoReadMessageResult.idl
new file mode 100644
index 0000000..f08503cd
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoReadMessageResult.idl
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+dictionary MojoReadMessageResult {
+  // TODO(alokp): Consider raising exception for read error.
+  required MojoResult result;
+
+  // TODO(alokp): Check if returning DataView makes sense.
+  // It would require some changes in mojo/js/public/[buffer,codec].js.
+  ArrayBuffer buffer;
+
+  sequence<MojoHandle> handles;
+};
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
new file mode 100644
index 0000000..804536d
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
@@ -0,0 +1,128 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/mojo/MojoWatcher.h"
+
+#include "bindings/core/v8/MojoWatchCallback.h"
+#include "bindings/core/v8/ScriptState.h"
+#include "core/dom/ExecutionContext.h"
+#include "core/dom/ExecutionContextTask.h"
+#include "core/dom/TaskRunnerHelper.h"
+#include "core/mojo/MojoHandleSignals.h"
+#include "platform/WebTaskRunner.h"
+
+namespace blink {
+
+static void runWatchCallback(MojoWatchCallback* callback,
+                             ScriptWrappable* wrappable,
+                             MojoResult result) {
+  callback->call(wrappable, result);
+}
+
+MojoWatcher* MojoWatcher::create(mojo::Handle handle,
+                                 const MojoHandleSignals& signalsDict,
+                                 MojoWatchCallback* callback,
+                                 ExecutionContext* context) {
+  MojoWatcher* watcher = new MojoWatcher(context, callback);
+  MojoResult result = watcher->watch(handle, signalsDict);
+  // TODO(alokp): Consider raising an exception.
+  // Current clients expect to recieve the initial error returned by MojoWatch
+  // via watch callback.
+  //
+  // Note that the usage of wrapPersistent is intentional so that the intial
+  // error is guaranteed to be reported to the client in case where the given
+  // handle is invalid and garbage collection happens before the callback
+  // is scheduled.
+  if (result != MOJO_RESULT_OK) {
+    watcher->m_taskRunner->postTask(
+        BLINK_FROM_HERE, WTF::bind(&runWatchCallback, wrapPersistent(callback),
+                                   wrapPersistent(watcher), result));
+  }
+  return watcher;
+}
+
+MojoWatcher::MojoWatcher(ExecutionContext* context, MojoWatchCallback* callback)
+    : ContextLifecycleObserver(context),
+      m_taskRunner(TaskRunnerHelper::get(TaskType::UnspecedTimer, context)),
+      m_callback(this, callback) {}
+
+MojoWatcher::~MojoWatcher() {
+  DCHECK(!m_handle.is_valid());
+}
+
+MojoResult MojoWatcher::watch(mojo::Handle handle,
+                              const MojoHandleSignals& signalsDict) {
+  ::MojoHandleSignals signals = MOJO_HANDLE_SIGNAL_NONE;
+  if (signalsDict.readable())
+    signals |= MOJO_HANDLE_SIGNAL_READABLE;
+  if (signalsDict.writable())
+    signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
+  if (signalsDict.peerClosed())
+    signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
+
+  MojoResult result =
+      MojoWatch(handle.value(), signals, &MojoWatcher::onHandleReady,
+                reinterpret_cast<uintptr_t>(this));
+  if (result == MOJO_RESULT_OK) {
+    m_handle = handle;
+  }
+  return result;
+}
+
+MojoResult MojoWatcher::cancel() {
+  if (!m_handle.is_valid())
+    return MOJO_RESULT_OK;
+
+  MojoResult result =
+      MojoCancelWatch(m_handle.value(), reinterpret_cast<uintptr_t>(this));
+  m_handle = mojo::Handle();
+  return result;
+}
+
+DEFINE_TRACE(MojoWatcher) {
+  visitor->trace(m_callback);
+  ContextLifecycleObserver::trace(visitor);
+}
+
+DEFINE_TRACE_WRAPPERS(MojoWatcher) {
+  visitor->traceWrappers(m_callback);
+}
+
+bool MojoWatcher::hasPendingActivity() const {
+  return m_handle.is_valid();
+}
+
+void MojoWatcher::contextDestroyed(ExecutionContext*) {
+  cancel();
+}
+
+void MojoWatcher::onHandleReady(uintptr_t context,
+                                MojoResult result,
+                                MojoHandleSignalsState,
+                                MojoWatchNotificationFlags) {
+  // It is safe to assume the MojoWatcher still exists because this
+  // callback will never be run after MojoWatcher destructor,
+  // which cancels the watch.
+  MojoWatcher* watcher = reinterpret_cast<MojoWatcher*>(context);
+  watcher->m_taskRunner->postTask(
+      BLINK_FROM_HERE,
+      crossThreadBind(&MojoWatcher::runReadyCallback,
+                      wrapCrossThreadWeakPersistent(watcher), result));
+}
+
+void MojoWatcher::runReadyCallback(MojoResult result) {
+  // Ignore callbacks if not watching.
+  if (!m_handle.is_valid())
+    return;
+
+  // MOJO_RESULT_CANCELLED indicates that the handle has been closed, in which
+  // case watch has been implicitly cancelled. There is no need to explicitly
+  // cancel the watch.
+  if (result == MOJO_RESULT_CANCELLED)
+    m_handle = mojo::Handle();
+
+  runWatchCallback(m_callback, this, result);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.h b/third_party/WebKit/Source/core/mojo/MojoWatcher.h
new file mode 100644
index 0000000..fe6e193
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.h
@@ -0,0 +1,64 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MojoWatcher_h
+#define MojoWatcher_h
+
+#include "bindings/core/v8/ActiveScriptWrappable.h"
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "bindings/core/v8/TraceWrapperMember.h"
+#include "core/dom/ContextLifecycleObserver.h"
+#include "mojo/public/cpp/system/handle.h"
+
+namespace blink {
+
+class ExecutionContext;
+class MojoHandleSignals;
+class MojoWatchCallback;
+
+class MojoWatcher final : public GarbageCollectedFinalized<MojoWatcher>,
+                          public ActiveScriptWrappable<MojoWatcher>,
+                          public ScriptWrappable,
+                          public ContextLifecycleObserver {
+  DEFINE_WRAPPERTYPEINFO();
+  USING_GARBAGE_COLLECTED_MIXIN(MojoWatcher);
+
+ public:
+  static MojoWatcher* create(mojo::Handle,
+                             const MojoHandleSignals&,
+                             MojoWatchCallback*,
+                             ExecutionContext*);
+  ~MojoWatcher();
+
+  MojoResult cancel();
+
+  DECLARE_TRACE();
+  DECLARE_TRACE_WRAPPERS();
+
+  // ActiveScriptWrappable
+  bool hasPendingActivity() const final;
+
+  // ContextLifecycleObserver
+  void contextDestroyed(ExecutionContext*) final;
+
+ private:
+  friend class V8MojoWatcher;
+
+  MojoWatcher(ExecutionContext*, MojoWatchCallback*);
+  MojoResult watch(mojo::Handle, const MojoHandleSignals&);
+
+  static void onHandleReady(uintptr_t context,
+                            MojoResult,
+                            MojoHandleSignalsState,
+                            MojoWatchNotificationFlags);
+  void runReadyCallback(MojoResult);
+
+  RefPtr<WebTaskRunner> m_taskRunner;
+  TraceWrapperMember<MojoWatchCallback> m_callback;
+  mojo::Handle m_handle;
+};
+
+}  // namespace blink
+
+#endif  // MojoWatcher_h
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.idl b/third_party/WebKit/Source/core/mojo/MojoWatcher.idl
new file mode 100644
index 0000000..0c66d3f
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.idl
@@ -0,0 +1,11 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+    ActiveScriptWrappable,
+    DependentLifetime,
+    RuntimeEnabled=MojoJS,
+] interface MojoWatcher {
+    MojoResult cancel();
+};
diff --git a/third_party/WebKit/Source/core/mojo/README.md b/third_party/WebKit/Source/core/mojo/README.md
new file mode 100644
index 0000000..c1b40ef
--- /dev/null
+++ b/third_party/WebKit/Source/core/mojo/README.md
@@ -0,0 +1,6 @@
+# `Source/core/mojo`
+
+This directory contains implementation of JavaScript bindings for mojo core
+module. Refer to
+[mojo/public/c/system/core.h](https://chromium.googlesource.com/chromium/src/+/master/mojo/public/c/system/core.h)
+for more detailed documentation of equivalent methods.
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h
index f43673f..dda0997 100644
--- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h
+++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h
@@ -25,7 +25,7 @@
 // context.  This class is not for direct use by feature implementers.
 // Instead, the OriginTrials generated namespace provides a method for each
 // trial to check if it is enabled. Experimental features must be defined in
-// RuntimeEnabledFeatures.in, which is used to generate OriginTrials.h/cpp.
+// RuntimeEnabledFeatures.json5, which is used to generate OriginTrials.h/cpp.
 //
 // Origin trials are defined by string names, provided by the implementers. The
 // framework does not maintain an enum or constant list for trial names.
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index 42d8e245..51b10e2 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -487,9 +487,9 @@
   WebLayer* containerLayer = toWebLayer(scrollableArea->layerForContainer());
   if (webLayer) {
     webLayer->setScrollClipLayer(containerLayer);
-    DoublePoint scrollPosition(FloatPoint(scrollableArea->scrollOrigin()) +
-                               scrollableArea->getScrollOffset());
-    webLayer->setScrollPositionDouble(scrollPosition);
+    FloatPoint scrollPosition(scrollableArea->scrollOrigin() +
+                              scrollableArea->getScrollOffset());
+    webLayer->setScrollPosition(scrollPosition);
 
     webLayer->setBounds(scrollableArea->contentsSize());
     bool canScrollX = scrollableArea->userInputScrollable(HorizontalScrollbar);
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
index c8b484ff..d66ee85 100644
--- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -36,6 +36,40 @@
 }
 }
 
+enum class ResolvedUnderlinePosition { Roman, Under, Over };
+
+static ResolvedUnderlinePosition resolveUnderlinePosition(
+    const ComputedStyle& style,
+    const InlineTextBox* inlineTextBox) {
+  // |auto| should resolve to |under| to avoid drawing through glyphs in
+  // scripts where it would not be appropriate (e.g., ideographs.)
+  // However, this has performance implications. For now, we only work with
+  // vertical text.
+  switch (inlineTextBox->root().baselineType()) {
+    default:
+      NOTREACHED();
+    // Fall though.
+    case AlphabeticBaseline:
+      switch (style.getTextUnderlinePosition()) {
+        default:
+          NOTREACHED();
+        // Fall though.
+        case TextUnderlinePositionAuto:
+          return ResolvedUnderlinePosition::Roman;
+        case TextUnderlinePositionUnder:
+          return ResolvedUnderlinePosition::Under;
+      }
+      break;
+    case IdeographicBaseline:
+      // Compute language-appropriate default underline position.
+      // https://drafts.csswg.org/css-text-decor-3/#default-stylesheet
+      UScriptCode script = style.getFontDescription().script();
+      if (script == USCRIPT_KATAKANA_OR_HIRAGANA || script == USCRIPT_HANGUL)
+        return ResolvedUnderlinePosition::Over;
+      return ResolvedUnderlinePosition::Under;
+  }
+}
+
 static LineLayoutItem enclosingUnderlineObject(
     const InlineTextBox* inlineTextBox) {
   bool firstLine = inlineTextBox->isFirstLineStyle();
@@ -61,20 +95,30 @@
   }
 }
 
-static LayoutUnit computeUnderlineOffsetForUnder(
-    const ComputedStyle& style,
-    const InlineTextBox* inlineTextBox) {
+static int computeUnderlineOffsetForUnder(const ComputedStyle& style,
+                                          const InlineTextBox* inlineTextBox,
+                                          bool isOverline = false) {
   const RootInlineBox& root = inlineTextBox->root();
   LineLayoutItem decorationObject = enclosingUnderlineObject(inlineTextBox);
+  LayoutUnit offset;
   if (style.isFlippedLinesWritingMode()) {
     LayoutUnit position = inlineTextBox->logicalTop();
-    return position -
-           root.minLogicalTopForUnderline(decorationObject, position);
+    offset =
+        position - root.minLogicalTopForUnderline(decorationObject, position);
   } else {
     LayoutUnit position = inlineTextBox->logicalBottom();
-    return root.maxLogicalBottomForUnderline(decorationObject, position) -
-           position;
+    offset = root.maxLogicalBottomForUnderline(decorationObject, position) -
+             position;
   }
+  if (isOverline)
+    return std::min(-offset, LayoutUnit()).toInt();
+  return (inlineTextBox->logicalHeight() + std::max(offset, LayoutUnit()))
+      .toInt();
+}
+
+static int computeOverlineOffset(const ComputedStyle& style,
+                                 const InlineTextBox* inlineTextBox) {
+  return computeUnderlineOffsetForUnder(style, inlineTextBox, true);
 }
 
 static int computeUnderlineOffsetForRoman(const FontMetrics& fontMetrics,
@@ -98,25 +142,22 @@
   return fontMetrics.ascent() + gap;
 }
 
-static int computeUnderlineOffset(const ComputedStyle& style,
+static int computeUnderlineOffset(ResolvedUnderlinePosition underlinePosition,
+                                  const ComputedStyle& style,
                                   const FontMetrics& fontMetrics,
                                   const InlineTextBox* inlineTextBox,
                                   const float textDecorationThickness) {
-  // FIXME: We support only horizontal text for now.
-  switch (style.getTextUnderlinePosition()) {
+  switch (underlinePosition) {
     default:
       NOTREACHED();
     // Fall through.
-    case TextUnderlinePositionAuto:
+    case ResolvedUnderlinePosition::Roman:
       return computeUnderlineOffsetForRoman(fontMetrics,
                                             textDecorationThickness);
-    case TextUnderlinePositionUnder: {
+    case ResolvedUnderlinePosition::Under:
       // Position underline at the under edge of the lowest element's
       // content box.
-      LayoutUnit offset = computeUnderlineOffsetForUnder(style, inlineTextBox);
-      offset = inlineTextBox->logicalHeight() + std::max(offset, LayoutUnit());
-      return offset.toInt();
-    }
+      return computeUnderlineOffsetForUnder(style, inlineTextBox);
   }
 }
 
@@ -604,8 +645,10 @@
     selectionEnd = textRun.length();
 
   bool ltr = m_inlineTextBox.isLeftToRightDirection();
-  bool flowIsLTR =
-      m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection();
+  bool flowIsLTR = m_inlineTextBox.getLineLayoutItem()
+                       .containingBlock()
+                       .style()
+                       ->isLeftToRightDirection();
   if (m_inlineTextBox.truncation() != cNoTruncation) {
     // In a mixed-direction flow the ellipsis is at the start of the text
     // rather than at the end of it.
@@ -995,8 +1038,10 @@
   unsigned start = m_inlineTextBox.start();
   int length = m_inlineTextBox.len();
   bool ltr = m_inlineTextBox.isLeftToRightDirection();
-  bool flowIsLTR =
-      m_inlineTextBox.getLineLayoutItem().style()->isLeftToRightDirection();
+  bool flowIsLTR = m_inlineTextBox.getLineLayoutItem()
+                       .containingBlock()
+                       .style()
+                       ->isLeftToRightDirection();
   if (m_inlineTextBox.truncation() != cNoTruncation) {
     // In a mixed-direction flow the ellipsis is at the start of the text
     // so we need to start after it. Otherwise we just need to make sure
@@ -1141,12 +1186,25 @@
   bool skipIntercepts =
       styleToUse.getTextDecorationSkip() & TextDecorationSkipInk;
 
+  // text-underline-position may flip underline and overline.
+  ResolvedUnderlinePosition underlinePosition =
+      resolveUnderlinePosition(styleToUse, &m_inlineTextBox);
+  bool flipUnderlineAndOverline = false;
+  if (underlinePosition == ResolvedUnderlinePosition::Over) {
+    flipUnderlineAndOverline = true;
+    underlinePosition = ResolvedUnderlinePosition::Under;
+  }
+
   for (const AppliedTextDecoration& decoration : decorations) {
     TextDecoration lines = decoration.lines();
+    if (flipUnderlineAndOverline) {
+      lines = static_cast<TextDecoration>(
+          lines ^ (TextDecorationUnderline | TextDecorationOverline));
+    }
     if ((lines & TextDecorationUnderline) && fontData) {
-      const int underlineOffset =
-          computeUnderlineOffset(styleToUse, fontData->getFontMetrics(),
-                                 &m_inlineTextBox, textDecorationThickness);
+      const int underlineOffset = computeUnderlineOffset(
+          underlinePosition, styleToUse, fontData->getFontMetrics(),
+          &m_inlineTextBox, textDecorationThickness);
       AppliedDecorationPainter decorationPainter(
           context, FloatPoint(localOrigin) + FloatPoint(0, underlineOffset),
           width.toFloat(), decoration, textDecorationThickness, doubleOffset, 1,
@@ -1161,9 +1219,12 @@
       decorationPainter.paint();
     }
     if (lines & TextDecorationOverline) {
+      const int overlineOffset =
+          computeOverlineOffset(styleToUse, &m_inlineTextBox);
       AppliedDecorationPainter decorationPainter(
-          context, FloatPoint(localOrigin), width.toFloat(), decoration,
-          textDecorationThickness, -doubleOffset, 1, antialiasDecoration);
+          context, FloatPoint(localOrigin) + FloatPoint(0, overlineOffset),
+          width.toFloat(), decoration, textDecorationThickness, -doubleOffset,
+          1, antialiasDecoration);
       if (skipIntercepts) {
         textPainter.clipDecorationsStripe(
             -baseline + decorationPainter.decorationBounds().y() -
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
index ab809a3..64c4f599 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
@@ -335,8 +335,8 @@
     context.forcedSubtreeInvalidationFlags |=
         PaintInvalidatorContext::ForcedSubtreeInvalidationChecking;
 
-  // TODO(crbug.com/637313): This is temporary before we support filters in
-  // GeometryMapper.
+  // TODO(crbug.com/637313): Use GeometryMapper which now supports filter
+  // geometry effects, after skia optimizes filter's mapRect operation.
   // TODO(crbug.com/648274): This is a workaround for multi-column contents.
   if (object.hasFilterInducingProperty() || object.isLayoutFlowThread()) {
     context.forcedSubtreeInvalidationFlags |=
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index 7284419..786449f 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -922,7 +922,7 @@
 
 PaintLayer* PaintLayer::compositingContainer() const {
   if (!stackingNode()->isStacked())
-    return containingLayer();
+    return isSelfPaintingLayer() ? parent() : containingLayer();
   if (PaintLayerStackingNode* ancestorStackingNode =
           stackingNode()->ancestorStackingContextNode())
     return ancestorStackingNode->layer();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
index e0fd7c42..d952793 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
@@ -663,6 +663,28 @@
   }
 }
 
+TEST_P(PaintLayerTest, CompositingContainerSelfPaintingNonStackedFloat) {
+  setBodyInnerHTML(
+      "<div id='container' style='position: relative'>"
+      "  <span id='span' style='opacity: 0.9'>"
+      "    <div id='target' style='columns: 1; float: left'></div>"
+      "  </span>"
+      "</div>");
+
+  // The target layer is self-painting, but not stacked.
+  PaintLayer* target =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer();
+  EXPECT_TRUE(target->isSelfPaintingLayer());
+  EXPECT_FALSE(target->stackingNode()->isStacked());
+
+  PaintLayer* container =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("container"))->layer();
+  PaintLayer* span =
+      toLayoutBoxModelObject(getLayoutObjectByElementId("span"))->layer();
+  EXPECT_EQ(container, target->containingLayer());
+  EXPECT_EQ(span, target->compositingContainer());
+}
+
 TEST_P(PaintLayerTest, ColumnSpanLayerUnderExtraLayerScrolled) {
   setBodyInnerHTML(
       "<div id='columns' style='overflow: hidden; width: 80px; height: 80px; "
diff --git a/third_party/WebKit/Source/core/style/StyleVisualData.cpp b/third_party/WebKit/Source/core/style/StyleVisualData.cpp
index c4ea3d0f..55a9a72a 100644
--- a/third_party/WebKit/Source/core/style/StyleVisualData.cpp
+++ b/third_party/WebKit/Source/core/style/StyleVisualData.cpp
@@ -37,6 +37,8 @@
       clip(o.clip),
       hasAutoClip(o.hasAutoClip),
       textDecoration(o.textDecoration),
-      m_zoom(ComputedStyle::initialZoom()) {}
+      m_zoom(ComputedStyle::initialZoom()) {
+  DCHECK(m_zoom == o.m_zoom);  // crbug.com/689330
+}
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGAttributeNames.in b/third_party/WebKit/Source/core/svg/SVGAttributeNames.in
deleted file mode 100644
index 7952490..0000000
--- a/third_party/WebKit/Source/core/svg/SVGAttributeNames.in
+++ /dev/null
@@ -1,243 +0,0 @@
-namespace="SVG"
-namespaceURI="http://www.w3.org/2000/svg"
-attrsNullNamespace
-export="CORE_EXPORT"
-
-accent-height
-accumulate
-additive
-alignment-baseline
-alphabetic
-amplitude
-animate
-arabic-form
-ascent
-attributeName
-attributeType
-azimuth
-baseFrequency
-baseline-shift
-baseProfile
-bbox
-begin
-bias
-buffered-rendering
-by
-calcMode
-cap-height
-clip
-clip-path
-clip-rule
-clipPathUnits
-color
-color-interpolation
-color-interpolation-filters
-color-rendering
-cursor
-cx
-cy
-d
-descent
-diffuseConstant
-direction
-display
-divisor
-dominant-baseline
-dur
-dx
-dy
-edgeMode
-elevation
-end
-exponent
-fill
-fill-opacity
-fill-rule
-filter
-filterUnits
-flood-color
-flood-opacity
-font-family
-font-size
-font-size-adjust
-font-stretch
-font-style
-font-variant
-font-weight
-format
-from
-fx
-fy
-fr
-g1
-g2
-glyph-name
-glyphRef
-gradientTransform
-gradientUnits
-hanging
-height
-horiz-adv-x
-horiz-origin-x
-horiz-origin-y
-href
-ideographic
-image-rendering
-in
-in2
-intercept
-k
-k1
-k2
-k3
-k4
-kernelMatrix
-kernelUnitLength
-keyPoints
-keySplines
-keyTimes
-lang
-lengthAdjust
-letter-spacing
-lighting-color
-limitingConeAngle
-local
-marker-end
-marker-mid
-marker-start
-markerHeight
-markerUnits
-markerWidth
-mask
-mask-type
-maskContentUnits
-maskUnits
-mathematical
-max
-media
-method
-min
-mode
-name
-numOctaves
-offset
-onactivate
-onbegin
-onend
-onfocusin
-onfocusout
-onrepeat
-opacity
-operator
-order
-orient
-orientation
-origin
-overflow
-overline-position
-overline-thickness
-paint-order
-panose-1
-path
-pathLength
-patternContentUnits
-patternTransform
-patternUnits
-pointer-events
-points
-pointsAtX
-pointsAtY
-pointsAtZ
-preserveAlpha
-preserveAspectRatio
-primitiveUnits
-r
-radius
-refX
-refY
-rendering-intent
-repeatCount
-repeatDur
-requiredExtensions
-requiredFeatures
-restart
-result
-rotate
-rx
-ry
-scale
-seed
-shape-rendering
-slope
-spacing
-specularConstant
-specularExponent
-spreadMethod
-startOffset
-stdDeviation
-stemh
-stemv
-stitchTiles
-stop-color
-stop-opacity
-strikethrough-position
-strikethrough-thickness
-stroke
-stroke-dasharray
-stroke-dashoffset
-stroke-linecap
-stroke-linejoin
-stroke-miterlimit
-stroke-opacity
-stroke-width
-style
-surfaceScale
-systemLanguage
-tableValues
-target
-targetX
-targetY
-text-anchor
-text-decoration
-text-rendering
-textLength
-title
-to
-transform
-transform-origin
-type
-u1
-u2
-underline-position
-underline-thickness
-unicode
-unicode-bidi
-unicode-range
-units-per-em
-v-alphabetic
-v-hanging
-v-ideographic
-v-mathematical
-values
-vector-effect
-version
-vert-adv-y
-vert-origin-x
-vert-origin-y
-viewBox
-visibility
-width
-widths
-word-spacing
-writing-mode
-x
-x-height
-x1
-x2
-xChannelSelector
-y
-y1
-y2
-yChannelSelector
-z
-zoomAndPan
diff --git a/third_party/WebKit/Source/core/svg/SVGAttributeNames.json5 b/third_party/WebKit/Source/core/svg/SVGAttributeNames.json5
new file mode 100644
index 0000000..5e5121d3
--- /dev/null
+++ b/third_party/WebKit/Source/core/svg/SVGAttributeNames.json5
@@ -0,0 +1,249 @@
+{
+  metadata: {
+    namespace: "SVG",
+    namespaceURI: "http://www.w3.org/2000/svg",
+    attrsNullNamespace: true,
+    export: "CORE_EXPORT",
+  },
+
+  data: [
+    "accent-height",
+    "accumulate",
+    "additive",
+    "alignment-baseline",
+    "alphabetic",
+    "amplitude",
+    "animate",
+    "arabic-form",
+    "ascent",
+    "attributeName",
+    "attributeType",
+    "azimuth",
+    "baseFrequency",
+    "baseline-shift",
+    "baseProfile",
+    "bbox",
+    "begin",
+    "bias",
+    "buffered-rendering",
+    "by",
+    "calcMode",
+    "cap-height",
+    "clip",
+    "clip-path",
+    "clip-rule",
+    "clipPathUnits",
+    "color",
+    "color-interpolation",
+    "color-interpolation-filters",
+    "color-rendering",
+    "cursor",
+    "cx",
+    "cy",
+    "d",
+    "descent",
+    "diffuseConstant",
+    "direction",
+    "display",
+    "divisor",
+    "dominant-baseline",
+    "dur",
+    "dx",
+    "dy",
+    "edgeMode",
+    "elevation",
+    "end",
+    "exponent",
+    "fill",
+    "fill-opacity",
+    "fill-rule",
+    "filter",
+    "filterUnits",
+    "flood-color",
+    "flood-opacity",
+    "font-family",
+    "font-size",
+    "font-size-adjust",
+    "font-stretch",
+    "font-style",
+    "font-variant",
+    "font-weight",
+    "format",
+    "from",
+    "fx",
+    "fy",
+    "fr",
+    "g1",
+    "g2",
+    "glyph-name",
+    "glyphRef",
+    "gradientTransform",
+    "gradientUnits",
+    "hanging",
+    "height",
+    "horiz-adv-x",
+    "horiz-origin-x",
+    "horiz-origin-y",
+    "href",
+    "ideographic",
+    "image-rendering",
+    "in",
+    "in2",
+    "intercept",
+    "k",
+    "k1",
+    "k2",
+    "k3",
+    "k4",
+    "kernelMatrix",
+    "kernelUnitLength",
+    "keyPoints",
+    "keySplines",
+    "keyTimes",
+    "lang",
+    "lengthAdjust",
+    "letter-spacing",
+    "lighting-color",
+    "limitingConeAngle",
+    "local",
+    "marker-end",
+    "marker-mid",
+    "marker-start",
+    "markerHeight",
+    "markerUnits",
+    "markerWidth",
+    "mask",
+    "mask-type",
+    "maskContentUnits",
+    "maskUnits",
+    "mathematical",
+    "max",
+    "media",
+    "method",
+    "min",
+    "mode",
+    "name",
+    "numOctaves",
+    "offset",
+    "onactivate",
+    "onbegin",
+    "onend",
+    "onfocusin",
+    "onfocusout",
+    "onrepeat",
+    "opacity",
+    "operator",
+    "order",
+    "orient",
+    "orientation",
+    "origin",
+    "overflow",
+    "overline-position",
+    "overline-thickness",
+    "paint-order",
+    "panose-1",
+    "path",
+    "pathLength",
+    "patternContentUnits",
+    "patternTransform",
+    "patternUnits",
+    "pointer-events",
+    "points",
+    "pointsAtX",
+    "pointsAtY",
+    "pointsAtZ",
+    "preserveAlpha",
+    "preserveAspectRatio",
+    "primitiveUnits",
+    "r",
+    "radius",
+    "refX",
+    "refY",
+    "rendering-intent",
+    "repeatCount",
+    "repeatDur",
+    "requiredExtensions",
+    "requiredFeatures",
+    "restart",
+    "result",
+    "rotate",
+    "rx",
+    "ry",
+    "scale",
+    "seed",
+    "shape-rendering",
+    "slope",
+    "spacing",
+    "specularConstant",
+    "specularExponent",
+    "spreadMethod",
+    "startOffset",
+    "stdDeviation",
+    "stemh",
+    "stemv",
+    "stitchTiles",
+    "stop-color",
+    "stop-opacity",
+    "strikethrough-position",
+    "strikethrough-thickness",
+    "stroke",
+    "stroke-dasharray",
+    "stroke-dashoffset",
+    "stroke-linecap",
+    "stroke-linejoin",
+    "stroke-miterlimit",
+    "stroke-opacity",
+    "stroke-width",
+    "style",
+    "surfaceScale",
+    "systemLanguage",
+    "tableValues",
+    "target",
+    "targetX",
+    "targetY",
+    "text-anchor",
+    "text-decoration",
+    "text-rendering",
+    "textLength",
+    "title",
+    "to",
+    "transform",
+    "transform-origin",
+    "type",
+    "u1",
+    "u2",
+    "underline-position",
+    "underline-thickness",
+    "unicode",
+    "unicode-bidi",
+    "unicode-range",
+    "units-per-em",
+    "v-alphabetic",
+    "v-hanging",
+    "v-ideographic",
+    "v-mathematical",
+    "values",
+    "vector-effect",
+    "version",
+    "vert-adv-y",
+    "vert-origin-x",
+    "vert-origin-y",
+    "viewBox",
+    "visibility",
+    "width",
+    "widths",
+    "word-spacing",
+    "writing-mode",
+    "x",
+    "x-height",
+    "x1",
+    "x2",
+    "xChannelSelector",
+    "y",
+    "y1",
+    "y2",
+    "yChannelSelector",
+    "z",
+    "zoomAndPan",
+  ],
+}
diff --git a/third_party/WebKit/Source/core/svg/SVGTagNames.in b/third_party/WebKit/Source/core/svg/SVGTagNames.in
deleted file mode 100644
index 23f5ad8..0000000
--- a/third_party/WebKit/Source/core/svg/SVGTagNames.in
+++ /dev/null
@@ -1,71 +0,0 @@
-namespace="SVG"
-namespaceURI="http://www.w3.org/2000/svg"
-fallbackInterfaceName="SVGUnknownElement"
-fallbackJSInterfaceName="SVGElement"
-export="CORE_EXPORT"
-
-a
-animate runtimeEnabled=smil, noTypeHelpers
-animateColor runtimeEnabled=smil, interfaceName=SVGUnknownElement, JSInterfaceName=SVGElement, noConstructor
-animateMotion runtimeEnabled=smil
-animateTransform runtimeEnabled=smil
-set runtimeEnabled=smil
-circle
-clipPath
-defs
-desc
-discard runtimeEnabled=smil
-ellipse
-feBlend
-feColorMatrix
-feComponentTransfer
-feComposite
-feConvolveMatrix
-feDiffuseLighting
-feDisplacementMap
-feDistantLight
-feDropShadow
-feFlood
-feFuncA
-feFuncB
-feFuncG
-feFuncR
-feGaussianBlur
-feImage
-feMerge
-feMergeNode
-feMorphology
-feOffset
-fePointLight
-feSpecularLighting
-feSpotLight
-feTile
-feTurbulence
-filter
-foreignObject
-g
-image
-line
-linearGradient
-marker
-mask
-metadata
-mpath runtimeEnabled=smil, interfaceName=SVGMPathElement
-path
-pattern
-polygon
-polyline
-radialGradient
-rect
-script constructorNeedsCreatedByParser
-stop
-style constructorNeedsCreatedByParser
-svg interfaceName=SVGSVGElement
-switch
-symbol
-text
-textPath
-title
-tspan interfaceName=SVGTSpanElement
-use
-view
diff --git a/third_party/WebKit/Source/core/svg/SVGTagNames.json5 b/third_party/WebKit/Source/core/svg/SVGTagNames.json5
new file mode 100644
index 0000000..bc54ea7c
--- /dev/null
+++ b/third_party/WebKit/Source/core/svg/SVGTagNames.json5
@@ -0,0 +1,115 @@
+{
+  metadata: {
+    namespace: "SVG",
+    namespaceURI: "http://www.w3.org/2000/svg",
+    fallbackInterfaceName: "SVGUnknownElement",
+    fallbackJSInterfaceName: "SVGElement",
+    export: "CORE_EXPORT",
+  },
+
+  data: [
+    "a",
+    {
+      name: "animate",
+      noTypeHelpers: true,
+      runtimeEnabled: "smil",
+    },
+    {
+      name: "animateColor",
+      JSInterfaceName: "SVGElement",
+      interfaceName: "SVGUnknownElement",
+      noConstructor: true,
+      runtimeEnabled: "smil",
+    },
+    {
+      name: "animateMotion",
+      runtimeEnabled: "smil",
+    },
+    {
+      name: "animateTransform",
+      runtimeEnabled: "smil",
+    },
+    {
+      name: "set",
+      runtimeEnabled: "smil",
+    },
+    "circle",
+    "clipPath",
+    "defs",
+    "desc",
+    {
+      name: "discard",
+      runtimeEnabled: "smil",
+    },
+    "ellipse",
+    "feBlend",
+    "feColorMatrix",
+    "feComponentTransfer",
+    "feComposite",
+    "feConvolveMatrix",
+    "feDiffuseLighting",
+    "feDisplacementMap",
+    "feDistantLight",
+    "feDropShadow",
+    "feFlood",
+    "feFuncA",
+    "feFuncB",
+    "feFuncG",
+    "feFuncR",
+    "feGaussianBlur",
+    "feImage",
+    "feMerge",
+    "feMergeNode",
+    "feMorphology",
+    "feOffset",
+    "fePointLight",
+    "feSpecularLighting",
+    "feSpotLight",
+    "feTile",
+    "feTurbulence",
+    "filter",
+    "foreignObject",
+    "g",
+    "image",
+    "line",
+    "linearGradient",
+    "marker",
+    "mask",
+    "metadata",
+    {
+      name: "mpath",
+      interfaceName: "SVGMPathElement",
+      runtimeEnabled: "smil",
+    },
+    "path",
+    "pattern",
+    "polygon",
+    "polyline",
+    "radialGradient",
+    "rect",
+    {
+      name: "script",
+      constructorNeedsCreatedByParser: true,
+    },
+    "stop",
+    {
+      name: "style",
+      constructorNeedsCreatedByParser: true,
+    },
+    {
+      name: "svg",
+      interfaceName: "SVGSVGElement",
+    },
+    "switch",
+    "symbol",
+    "text",
+    "textPath",
+    "title",
+    {
+      name: "tspan",
+      interfaceName: "SVGTSpanElement",
+    },
+    "use",
+    "view",
+  ],
+}
diff --git a/third_party/WebKit/Source/core/svg/SVGTransformList.cpp b/third_party/WebKit/Source/core/svg/SVGTransformList.cpp
index 016cf90f..434641e 100644
--- a/third_party/WebKit/Source/core/svg/SVGTransformList.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTransformList.cpp
@@ -43,7 +43,7 @@
 SVGTransform* SVGTransformList::consolidate() {
   AffineTransform matrix;
   if (!concatenate(matrix))
-    return SVGTransform::create();
+    return nullptr;
 
   return initialize(SVGTransform::create(matrix));
 }
diff --git a/third_party/WebKit/Source/core/svg/xlinkattrs.in b/third_party/WebKit/Source/core/svg/xlinkattrs.in
deleted file mode 100644
index e3e0c33..0000000
--- a/third_party/WebKit/Source/core/svg/xlinkattrs.in
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace="XLink"
-namespaceURI="http://www.w3.org/1999/xlink"
-export="CORE_EXPORT"
-
-actuate
-arcrole
-href
-role
-show
-title
-type
diff --git a/third_party/WebKit/Source/core/svg/xlinkattrs.json5 b/third_party/WebKit/Source/core/svg/xlinkattrs.json5
new file mode 100644
index 0000000..70ac0534
--- /dev/null
+++ b/third_party/WebKit/Source/core/svg/xlinkattrs.json5
@@ -0,0 +1,17 @@
+{
+  metadata: {
+    namespace: "XLink",
+    namespaceURI: "http://www.w3.org/1999/xlink",
+    export: "CORE_EXPORT",
+  },
+
+  data: [
+    "actuate",
+    "arcrole",
+    "href",
+    "role",
+    "show",
+    "title",
+    "type",
+  ],
+}
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 96e8343..6b29676 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -2997,11 +2997,11 @@
   return new InternalsIterationSource();
 }
 
-bool Internals::isUseCounted(Document* document, int useCounterId) {
-  if (useCounterId < 0 || useCounterId >= UseCounter::NumberOfFeatures)
+bool Internals::isUseCounted(Document* document, uint32_t feature) {
+  if (feature >= UseCounter::NumberOfFeatures)
     return false;
   return UseCounter::isCounted(*document,
-                               static_cast<UseCounter::Feature>(useCounterId));
+                               static_cast<UseCounter::Feature>(feature));
 }
 
 bool Internals::isCSSPropertyUseCounted(Document* document,
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h
index 1d5f541..e05a5b6 100644
--- a/third_party/WebKit/Source/core/testing/Internals.h
+++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -489,8 +489,8 @@
   float visualViewportScrollY();
 
   // Return true if the given use counter exists for the given document.
-  // |useCounterId| must be one of the values from the UseCounter::Feature enum.
-  bool isUseCounted(Document*, int useCounterId);
+  // |feature| must be one of the values from the UseCounter::Feature enum.
+  bool isUseCounted(Document*, uint32_t feature);
   bool isCSSPropertyUseCounted(Document*, const String&);
 
   String unscopableAttribute();
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl
index 827dd408..0cb74b3 100644
--- a/third_party/WebKit/Source/core/testing/Internals.idl
+++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -328,7 +328,7 @@
 
     bool magnifyScaleAroundAnchor(float offset, float x, float y);
 
-    boolean isUseCounted(Document document, long useCounterId);
+    boolean isUseCounted(Document document, unsigned long feature);
     boolean isCSSPropertyUseCounted(Document document, DOMString propertyName);
 
     iterable<long>;
diff --git a/third_party/WebKit/Source/core/testing/WorkerInternals.cpp b/third_party/WebKit/Source/core/testing/WorkerInternals.cpp
index 6d6d19b..7263097 100644
--- a/third_party/WebKit/Source/core/testing/WorkerInternals.cpp
+++ b/third_party/WebKit/Source/core/testing/WorkerInternals.cpp
@@ -4,6 +4,9 @@
 
 #include "core/testing/WorkerInternals.h"
 
+#include "bindings/core/v8/ScriptState.h"
+#include "core/frame/Deprecation.h"
+#include "core/frame/UseCounter.h"
 #include "core/testing/OriginTrialsTest.h"
 
 namespace blink {
@@ -16,4 +19,15 @@
   return OriginTrialsTest::create();
 }
 
+void WorkerInternals::countFeature(ScriptState* scriptState, uint32_t feature) {
+  UseCounter::count(scriptState->getExecutionContext(),
+                    static_cast<UseCounter::Feature>(feature));
+}
+
+void WorkerInternals::countDeprecation(ScriptState* scriptState,
+                                       uint32_t feature) {
+  Deprecation::countDeprecation(scriptState->getExecutionContext(),
+                                static_cast<UseCounter::Feature>(feature));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/testing/WorkerInternals.h b/third_party/WebKit/Source/core/testing/WorkerInternals.h
index 8669efd..e2f3f08 100644
--- a/third_party/WebKit/Source/core/testing/WorkerInternals.h
+++ b/third_party/WebKit/Source/core/testing/WorkerInternals.h
@@ -11,6 +11,7 @@
 namespace blink {
 
 class OriginTrialsTest;
+class ScriptState;
 
 class WorkerInternals final : public GarbageCollectedFinalized<WorkerInternals>,
                               public ScriptWrappable {
@@ -19,7 +20,10 @@
  public:
   static WorkerInternals* create() { return new WorkerInternals(); }
   virtual ~WorkerInternals();
+
   OriginTrialsTest* originTrialsTest() const;
+  void countFeature(ScriptState*, uint32_t feature);
+  void countDeprecation(ScriptState*, uint32_t feature);
 
   DEFINE_INLINE_TRACE() {}
 
diff --git a/third_party/WebKit/Source/core/testing/WorkerInternals.idl b/third_party/WebKit/Source/core/testing/WorkerInternals.idl
index 02866e69..7db9eff 100644
--- a/third_party/WebKit/Source/core/testing/WorkerInternals.idl
+++ b/third_party/WebKit/Source/core/testing/WorkerInternals.idl
@@ -4,4 +4,9 @@
 
 interface WorkerInternals {
     OriginTrialsTest originTrialsTest();
+
+    // Records |feature| in worker's use counter. |feature| must be one of the
+    // values from the UseCounter::Feature enum.
+    [CallWith=ScriptState] void countFeature(unsigned long feature);
+    [CallWith=ScriptState] void countDeprecation(unsigned long feature);
 };
diff --git a/third_party/WebKit/Source/core/xml/xmlattrs.in b/third_party/WebKit/Source/core/xml/xmlattrs.in
deleted file mode 100644
index ae6ab01..0000000
--- a/third_party/WebKit/Source/core/xml/xmlattrs.in
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace="XML"
-namespacePrefix="xml"
-namespaceURI="http://www.w3.org/XML/1998/namespace"
-
-lang
-space
diff --git a/third_party/WebKit/Source/core/xml/xmlattrs.json5 b/third_party/WebKit/Source/core/xml/xmlattrs.json5
new file mode 100644
index 0000000..6fa47033
--- /dev/null
+++ b/third_party/WebKit/Source/core/xml/xmlattrs.json5
@@ -0,0 +1,12 @@
+{
+  metadata: {
+    namespace: "XML",
+    namespacePrefix: "xml",
+    namespaceURI: "http://www.w3.org/XML/1998/namespace",
+  },
+
+  data: [
+    "lang",
+    "space",
+  ],
+}
diff --git a/third_party/WebKit/Source/core/xml/xmlnsattrs.in b/third_party/WebKit/Source/core/xml/xmlnsattrs.in
deleted file mode 100644
index 7ac415a..0000000
--- a/third_party/WebKit/Source/core/xml/xmlnsattrs.in
+++ /dev/null
@@ -1,4 +0,0 @@
-namespace="XMLNS"
-namespaceURI="http://www.w3.org/2000/xmlns/"
-
-xmlns
diff --git a/third_party/WebKit/Source/core/xml/xmlnsattrs.json5 b/third_party/WebKit/Source/core/xml/xmlnsattrs.json5
new file mode 100644
index 0000000..81f1684
--- /dev/null
+++ b/third_party/WebKit/Source/core/xml/xmlnsattrs.json5
@@ -0,0 +1,10 @@
+{
+  metadata: {
+    namespace: "XMLNS",
+    namespaceURI: "http://www.w3.org/2000/xmlns/",
+  },
+
+  data: [
+    "xmlns",
+  ],
+}
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 9957410..1675bf7 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -558,6 +558,7 @@
   "front_end/timeline/EventsTimelineTreeView.js",
   "front_end/timeline/invalidationsTree.css",
   "front_end/timeline/module.json",
+  "front_end/timeline/PerformanceModel.js",
   "front_end/timeline/TimelineController.js",
   "front_end/timeline/TimelineDetailsView.js",
   "front_end/timeline/TimelineEventOverview.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/Tests.js b/third_party/WebKit/Source/devtools/front_end/Tests.js
index 6ae3a55..21e7322 100644
--- a/third_party/WebKit/Source/devtools/front_end/Tests.js
+++ b/third_party/WebKit/Source/devtools/front_end/Tests.js
@@ -744,7 +744,7 @@
 
     function onTimelineDone() {
       captureFilmStripSetting.set(false);
-      var filmStripModel = new SDK.FilmStripModel(UI.panels.timeline._tracingModel);
+      var filmStripModel = UI.panels.timeline._performanceModel.filmStripModel();
       var frames = filmStripModel.frames();
       test.assertTrue(frames.length > 4 && typeof frames.length === 'number');
       loadFrameImages(frames);
@@ -963,7 +963,7 @@
 
   TestSuite.prototype.checkInputEventsPresent = function() {
     var expectedEvents = new Set(arguments);
-    var model = UI.panels.timeline._model;
+    var model = UI.panels.timeline._performanceModel.timelineModel();
     var asyncEvents = model.mainThreadAsyncEvents();
     var input = asyncEvents.get(TimelineModel.TimelineModel.AsyncEventGroup.input) || [];
     var prefix = 'InputLatency::';
diff --git a/third_party/WebKit/Source/devtools/front_end/common/Settings.js b/third_party/WebKit/Source/devtools/front_end/common/Settings.js
index 6c822c45..ffa709e9 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/Settings.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/Settings.js
@@ -710,12 +710,7 @@
   }
 
   _updateVersionFrom22To23() {
-    var oldSetting = Common.settings.createSetting('consoleTimestampsEnabled', false);
-    var newSetting = Common.settings.createSetting('consoleTimestampFormat', 'none');
-    var oldValue = oldSetting.get();
-    if (oldValue)
-      newSetting.set('short');
-    oldSetting.remove();
+    // This update is no-op.
   }
 
   _migrateSettingsFromLocalStorage() {
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
index 97f701c..c39376af 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -150,7 +150,7 @@
     this._consoleHistoryAutocompleteChanged();
 
     this._updateFilterStatus();
-    Common.moduleSetting('consoleTimestampFormat').addChangeListener(this._consoleTimestampsSettingChanged, this);
+    Common.moduleSetting('consoleTimestampsEnabled').addChangeListener(this._consoleTimestampsSettingChanged, this);
 
     this._registerWithMessageSink();
     SDK.targetManager.observeTargets(this);
@@ -676,8 +676,7 @@
    * @return {boolean}
    */
   _tryToCollapseMessages(lastMessage, viewMessage) {
-    var timestampFormat = Common.moduleSetting('consoleTimestampFormat').get();
-    var timestampsShown = timestampFormat !== Console.ConsoleViewMessage.TimestampFormat.None;
+    var timestampsShown = Common.moduleSetting('consoleTimestampsEnabled').get();
     if (!timestampsShown && viewMessage && !lastMessage.consoleMessage().isGroupMessage() &&
         lastMessage.consoleMessage().isEqual(viewMessage.consoleMessage())) {
       viewMessage.incrementRepeatCount();
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
index 9cd71c1..801c698f 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -834,13 +834,11 @@
     if (!this._contentElement)
       return;
 
-    var format = Common.moduleSetting('consoleTimestampFormat').get();
-    if (format !== Console.ConsoleViewMessage.TimestampFormat.None) {
-      var timestampText = formatTimestamp(this._message.timestamp, format);
+    if (Common.moduleSetting('consoleTimestampsEnabled').get()) {
       if (!this._timestampElement)
         this._timestampElement = createElementWithClass('span', 'console-timestamp');
-      this._timestampElement.textContent = timestampText + ' ';
-      this._timestampElement.title = timestampText;
+      this._timestampElement.textContent = formatTimestamp(this._message.timestamp, false) + ' ';
+      this._timestampElement.title = formatTimestamp(this._message.timestamp, true);
       this._contentElement.insertBefore(this._timestampElement, this._contentElement.firstChild);
     } else if (this._timestampElement) {
       this._timestampElement.remove();
@@ -849,17 +847,15 @@
 
     /**
      * @param {number} timestamp
-     * @param {!Console.ConsoleViewMessage.TimestampFormat} format
+     * @param {boolean} full
      * @return {string}
      */
-    function formatTimestamp(timestamp, format) {
+    function formatTimestamp(timestamp, full) {
       var date = new Date(timestamp);
       var yymmdd = date.getFullYear() + '-' + leadZero(date.getMonth() + 1, 2) + '-' + leadZero(date.getDate(), 2);
       var hhmmssfff = leadZero(date.getHours(), 2) + ':' + leadZero(date.getMinutes(), 2) + ':' +
           leadZero(date.getSeconds(), 2) + '.' + leadZero(date.getMilliseconds(), 3);
-      if (format === Console.ConsoleViewMessage.TimestampFormat.Full)
-        return yymmdd + ' ' + hhmmssfff;
-      return hhmmssfff;
+      return full ? (yymmdd + ' ' + hhmmssfff) : hhmmssfff;
 
       /**
        * @param {number} value
@@ -1212,15 +1208,6 @@
 };
 
 /**
- * @enum {string}
- */
-Console.ConsoleViewMessage.TimestampFormat = {
-  None: 'none',
-  Full: 'full',
-  Short: 'short'
-};
-
-/**
  * @unrestricted
  */
 Console.ConsoleGroupViewMessage = class extends Console.ConsoleViewMessage {
diff --git a/third_party/WebKit/Source/devtools/front_end/console/module.json b/third_party/WebKit/Source/devtools/front_end/console/module.json
index 63642bd3..9c0ba5a39 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/console/module.json
@@ -88,25 +88,18 @@
         {
             "type": "setting",
             "category": "Console",
-            "title": "Timestamps:",
-            "settingName": "consoleTimestampFormat",
-            "settingType": "enum",
-            "defaultValue": "none",
+            "title": "Show timestamps",
+            "settingName": "consoleTimestampsEnabled",
+            "settingType": "boolean",
+            "defaultValue": false,
             "options": [
                 {
-                    "title": "Hide timestamps",
-                    "text": "None",
-                    "value": "none"
+                    "value": true,
+                    "title": "Show timestamps"
                 },
                 {
-                    "title": "Full (yyyy-MM-dd HH:mm:ss.fff)",
-                    "text": "Full",
-                    "value": "full"
-                },
-                {
-                    "title": "Short (HH:mm:ss.fff)",
-                    "text": "Short",
-                    "value": "short"
+                    "value": false,
+                    "title": "Hide timestamps"
                 }
             ]
         },
diff --git a/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js b/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js
index 6d413311..f9adfcc 100644
--- a/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js
+++ b/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js
@@ -1585,7 +1585,7 @@
    * @return {number}
    */
   nodeSelfHeight() {
-    return 16;
+    return 20;
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/data_grid/ShowMoreDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/data_grid/ShowMoreDataGridNode.js
index 3873307..857ffadf 100644
--- a/third_party/WebKit/Source/devtools/front_end/data_grid/ShowMoreDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/data_grid/ShowMoreDataGridNode.js
@@ -135,7 +135,7 @@
    * @return {number}
    */
   nodeSelfHeight() {
-    return 32;
+    return 40;
   }
 
   dispose() {
diff --git a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
index 316f2bf..acf15e9 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -234,7 +234,7 @@
    * @return {number}
    */
   nodeSelfHeight() {
-    return 17;
+    return 21;
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
index edee9e06..3cf42ff 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
@@ -34,15 +34,13 @@
 Timeline.CountersGraph = class extends UI.VBox {
   /**
    * @param {!Timeline.TimelineModeViewDelegate} delegate
-   * @param {!TimelineModel.TimelineModel} model
    */
-  constructor(delegate, model) {
+  constructor(delegate) {
     super();
     this.element.id = 'memory-graphs-container';
 
     this._delegate = delegate;
-    this._model = model;
-    this._calculator = new Timeline.CountersGraph.Calculator(this._model);
+    this._calculator = new Timeline.CountersGraph.Calculator();
 
     // Create selectors
     this._infoWidget = new UI.HBox();
@@ -87,10 +85,18 @@
 
   /**
    * @override
+   * @param {?Timeline.PerformanceModel} model
    */
-  refreshRecords() {
-    this.reset();
-    var events = this._model.mainThreadEvents();
+  setModel(model) {
+    this._calculator.setZeroTime(model ? model.timelineModel().minimumRecordTime() : 0);
+    for (var i = 0; i < this._counters.length; ++i) {
+      this._counters[i].reset();
+      this._counterUI[i].reset();
+    }
+    this.scheduleRefresh();
+    if (!model)
+      return;
+    var events = model.timelineModel().mainThreadEvents();
     for (var i = 0; i < events.length; ++i) {
       var event = events[i];
       if (event.name !== TimelineModel.TimelineModel.RecordType.UpdateCounters)
@@ -109,13 +115,6 @@
       if (gpuMemoryLimitCounterName in counters)
         this._gpuMemoryCounter.setLimit(counters[gpuMemoryLimitCounterName]);
     }
-    this.scheduleRefresh();
-  }
-
-  /**
-   * @override
-   */
-  extensionDataAdded() {
   }
 
   _createCurrentValuesBar() {
@@ -148,23 +147,6 @@
 
   /**
    * @override
-   */
-  dispose() {
-  }
-
-  /**
-   * @override
-   */
-  reset() {
-    for (var i = 0; i < this._counters.length; ++i) {
-      this._counters[i].reset();
-      this._counterUI[i].reset();
-    }
-    this.refresh();
-  }
-
-  /**
-   * @override
    * @return {?Element}
    */
   resizerElement() {
@@ -550,10 +532,10 @@
  */
 Timeline.CountersGraph.Calculator = class {
   /**
-   * @param {!TimelineModel.TimelineModel} model
+   * @param {number} time
    */
-  constructor(model) {
-    this._model = model;
+  setZeroTime(time) {
+    this._zeroTime = time;
   }
 
 
@@ -609,7 +591,7 @@
    * @return {number}
    */
   zeroTime() {
-    return this._model.minimumRecordTime();
+    return this._zeroTime;
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js
index 8ae6fb358..6c69dd36 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js
@@ -7,16 +7,15 @@
  */
 Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView {
   /**
-   * @param {!TimelineModel.TimelineModel} model
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    * @param {!Timeline.TimelineModeViewDelegate} delegate
    */
-  constructor(model, filters, delegate) {
+  constructor(filters, delegate) {
     super();
     this._filtersControl = new Timeline.EventsTimelineTreeView.Filters();
     this._filtersControl.addEventListener(
         Timeline.EventsTimelineTreeView.Filters.Events.FilterChanged, this._onFilterChanged, this);
-    this.init(model, filters);
+    this.init(filters);
     this._delegate = delegate;
     this._filters.push.apply(this._filters, this._filtersControl.filters());
     this._dataGrid.markColumnAsSortedBy('startTime', DataGrid.DataGrid.Order.Ascending);
@@ -115,7 +114,7 @@
     if (!traceEvent)
       return false;
     Timeline.TimelineUIUtils.buildTraceEventDetails(
-        traceEvent, this._model, this._linkifier, false, showDetails.bind(this));
+        traceEvent, this.model().timelineModel(), this._linkifier, false, showDetails.bind(this));
     return true;
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/ExtensionTracingSession.js b/third_party/WebKit/Source/devtools/front_end/timeline/ExtensionTracingSession.js
index de108a8..64375d7 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/ExtensionTracingSession.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/ExtensionTracingSession.js
@@ -4,23 +4,21 @@
 
 /**
  * @implements {Extensions.TracingSession}
- * @implements {Timeline.LoaderClient}
+ * @implements {Timeline.TimelineLoader.Client}
  */
 Timeline.ExtensionTracingSession = class {
   /**
    * @param {!Extensions.ExtensionTraceProvider} provider
-   * @param {!Timeline.TimelineLifecycleDelegate} delegate
+   * @param {!Timeline.PerformanceModel} performanceModel
    */
-  constructor(provider, delegate) {
+  constructor(provider, performanceModel) {
     this._provider = provider;
-    this._delegate = delegate;
-    this._sessionGeneration = delegate.sessionGeneration();
+    this._performanceModel = performanceModel;
     /** @type {function()} */
     this._completionCallback;
-    this._completionPromise = new Promise(fulfill => {this._completionCallback = fulfill;});
-    /** @type {?SDK.TracingModel} */
-    this._tracingModel = null;
-    /** @type {number} */
+    this._completionPromise = new Promise(fulfill => {
+      this._completionCallback = fulfill;
+    });
     this._timeOffset = 0;
   }
 
@@ -37,16 +35,13 @@
 
   /**
    * @override
-   * @param {boolean} success
+   * @param {?SDK.TracingModel} tracingModel
+   * @param {?Bindings.TempFileBackingStorage} storage
    */
-  loadingComplete(success) {
-    if (!success || this._sessionGeneration !== this._delegate.sessionGeneration()) {
-      this._tracingModel.reset();
-    } else {
-      this._delegate.addExtensionEvents(
-          this._provider.longDisplayName(),
-          /** @type {!SDK.TracingModel} */ (this._tracingModel), this._timeOffset);
-    }
+  loadingComplete(tracingModel, storage) {
+    if (!tracingModel)
+      return;
+    this._performanceModel.addExtensionEvents(this._provider.longDisplayName(), tracingModel, this._timeOffset);
     this._completionCallback();
   }
 
@@ -56,14 +51,12 @@
    * @param {number} timeOffsetMicroseconds
    */
   complete(url, timeOffsetMicroseconds) {
-    if (!url || this._sessionGeneration !== this._delegate.sessionGeneration()) {
+    if (!url) {
       this._completionCallback();
       return;
     }
-    var storage = new Bindings.TempFileBackingStorage('tracing');
-    this._tracingModel = new SDK.TracingModel(storage);
     this._timeOffset = timeOffsetMicroseconds;
-    Timeline.TimelineLoader.loadFromURL(this._tracingModel, url, this);
+    Timeline.TimelineLoader.loadFromURL(url, this);
   }
 
   start() {
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/PerformanceModel.js b/third_party/WebKit/Source/devtools/front_end/timeline/PerformanceModel.js
new file mode 100644
index 0000000..f01d5b0
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/PerformanceModel.js
@@ -0,0 +1,143 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Timeline.PerformanceModel = class extends Common.Object {
+  constructor() {
+    super();
+    /** @type {?SDK.Target} */
+    this._mainTarget = null;
+    /** @type {?SDK.TracingModel} */
+    this._tracingModel = null;
+
+    this._timelineModel = new TimelineModel.TimelineModel();
+    this._frameModel =
+        new TimelineModel.TimelineFrameModel(event => Timeline.TimelineUIUtils.eventStyle(event).category.name);
+    /** @type {?SDK.FilmStripModel} */
+    this._filmStripModel = null;
+    /** @type {?TimelineModel.TimelineIRModel} */
+    this._irModel = new TimelineModel.TimelineIRModel();
+
+    /** @type {!Array<!{title: string, model: !SDK.TracingModel, timeOffset: number}>} */
+    this._extensionTracingModels = [];
+    /** @type {number|undefined} */
+    this._recordStartTime = undefined;
+  }
+
+  /**
+   * @param {!SDK.Target} target
+   */
+  setMainTarget(target) {
+    this._mainTarget = target;
+  }
+
+  /**
+   * @param {number} time
+   */
+  setRecordStartTime(time) {
+    this._recordStartTime = time;
+  }
+
+  /**
+   * @param {!SDK.TracingModel} model
+   */
+  setTracingModel(model) {
+    this._tracingModel = model;
+    this._timelineModel.setEvents(model, !this._mainTarget);
+
+    var groups = TimelineModel.TimelineModel.AsyncEventGroup;
+    var asyncEventsByGroup = this._timelineModel.mainThreadAsyncEvents();
+    this._irModel.populate(asyncEventsByGroup.get(groups.input), asyncEventsByGroup.get(groups.animation));
+
+    this._frameModel.addTraceEvents(
+        this._mainTarget, this._timelineModel.inspectedTargetEvents(), this._timelineModel.sessionId() || '');
+
+    for (var entry of this._extensionTracingModels) {
+      entry.model.adjustTime(
+          this._tracingModel.minimumRecordTime() + (entry.timeOffset / 1000) - this._recordStartTime);
+    }
+  }
+
+  /**
+   * @param {string} title
+   * @param {!SDK.TracingModel} model
+   * @param {number} timeOffset
+   */
+  addExtensionEvents(title, model, timeOffset) {
+    this._extensionTracingModels.push({model: model, title: title, timeOffset: timeOffset});
+    if (!this._tracingModel)
+      return;
+    model.adjustTime(this._tracingModel.minimumRecordTime() + (timeOffset / 1000) - this._recordStartTime);
+    this.dispatchEventToListeners(Timeline.PerformanceModel.Events.ExtensionDataAdded);
+  }
+
+  /**
+   * @return {!SDK.TracingModel}
+   */
+  tracingModel() {
+    if (!this._tracingModel)
+      throw 'call setTracingModel before accessing PerformanceModel';
+    return this._tracingModel;
+  }
+
+  /**
+   * @return {!TimelineModel.TimelineModel}
+   */
+  timelineModel() {
+    return this._timelineModel;
+  }
+
+  /**
+   * @return {!SDK.FilmStripModel} filmStripModel
+   */
+  filmStripModel() {
+    if (this._filmStripModel)
+      return this._filmStripModel;
+    if (!this._tracingModel)
+      throw 'call setTracingModel before accessing PerformanceModel';
+    this._filmStripModel = new SDK.FilmStripModel(this._tracingModel);
+    return this._filmStripModel;
+  }
+
+  /**
+   * @return {!Array<!TimelineModel.TimelineFrame>} frames
+   */
+  frames() {
+    return this._frameModel.frames();
+  }
+
+  /**
+   * @return {!TimelineModel.TimelineFrameModel} frames
+   */
+  frameModel() {
+    return this._frameModel;
+  }
+
+  /**
+   * @return {!Array<!Common.Segment>}
+   */
+  interactionRecords() {
+    return this._irModel.interactionRecords();
+  }
+
+  /**
+   * @return {!Array<!{title: string, model: !SDK.TracingModel}>}
+   */
+  extensionInfo() {
+    return this._extensionTracingModels;
+  }
+
+  dispose() {
+    if (this._tracingModel)
+      this._tracingModel.reset();
+    for (var extensionEntry of this._extensionTracingModels)
+      extensionEntry.model.reset();
+  }
+};
+
+/**
+ * @enum {symbol}
+ */
+Timeline.PerformanceModel.Events = {
+  ExtensionDataAdded: Symbol('ExtensionDataAdded')
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js
index d6769e7..6dae0d95 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js
@@ -10,13 +10,20 @@
 Timeline.TimelineController = class {
   /**
    * @param {!SDK.Target} target
-   * @param {!Timeline.TimelineLifecycleDelegate} delegate
-   * @param {!SDK.TracingModel} tracingModel
+   * @param {!Timeline.PerformanceModel} performanceModel
+   * @param {!Timeline.TimelineController.Client} client
    */
-  constructor(target, delegate, tracingModel) {
-    this._delegate = delegate;
+  constructor(target, performanceModel, client) {
     this._target = target;
-    this._tracingModel = tracingModel;
+    this._performanceModel = performanceModel;
+    this._client = client;
+
+    this._tracingModelBackingStorage = new Bindings.TempFileBackingStorage('tracing');
+    this._tracingModel = new SDK.TracingModel(this._tracingModelBackingStorage);
+
+    this._performanceModel.setMainTarget(target);
+
+    /** @type {!Array<!SDK.Target>} */
     this._targets = [];
     /** @type {!Array<!Timeline.ExtensionTracingSession>} */
     this._extensionSessions = [];
@@ -62,9 +69,11 @@
     if (options.captureFilmStrip)
       categoriesArray.push(disabledByDefault('devtools.screenshot'));
 
-    this._extensionSessions = providers.map(provider => new Timeline.ExtensionTracingSession(provider, this._delegate));
+    this._extensionSessions =
+        providers.map(provider => new Timeline.ExtensionTracingSession(provider, this._performanceModel));
     this._extensionSessions.forEach(session => session.start());
     this._startRecordingWithCategories(categoriesArray.join(','), options.enableJSSampling);
+    this._performanceModel.setRecordStartTime(Date.now());
   }
 
   stopRecording() {
@@ -72,10 +81,9 @@
     tracingStoppedPromises.push(new Promise(resolve => this._tracingCompleteCallback = resolve));
     tracingStoppedPromises.push(this._stopProfilingOnAllTargets());
     this._target.tracingManager.stop();
-
     tracingStoppedPromises.push(SDK.targetManager.resumeAllTargets());
 
-    this._delegate.loadingStarted();
+    this._client.loadingStarted();
 
     var extensionCompletionPromises = this._extensionSessions.map(session => session.stop());
     if (extensionCompletionPromises.length) {
@@ -188,8 +196,7 @@
    * @override
    */
   tracingStarted() {
-    this._tracingModel.reset();
-    this._delegate.recordingStarted();
+    this._client.recordingStarted();
   }
 
   /**
@@ -211,7 +218,7 @@
   _allSourcesFinished() {
     this._injectCpuProfileEvents();
     this._tracingModel.tracingComplete();
-    this._delegate.loadingComplete(true);
+    this._client.loadingComplete(this._tracingModel, this._tracingModelBackingStorage);
   }
 
   /**
@@ -266,7 +273,7 @@
    * @override
    */
   tracingBufferUsage(usage) {
-    this._delegate.recordingProgress(usage);
+    this._client.recordingProgress(usage);
   }
 
   /**
@@ -274,11 +281,26 @@
    * @override
    */
   eventsRetrievalProgress(progress) {
-    this._delegate.loadingProgress(progress);
+    this._client.loadingProgress(progress);
   }
 };
 
 /**
+ * @interface
+ * @extends {Timeline.TimelineLoader.Client}
+ */
+Timeline.TimelineController.Client = function() {};
+
+Timeline.TimelineController.Client.prototype = {
+  recordingStarted() {},
+
+  /**
+   * @param {number} usage
+   */
+  recordingProgress(usage) {},
+};
+
+/**
  * @typedef {!{
  *   enableJSSampling: (boolean|undefined),
  *   capturePictures: (boolean|undefined),
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineDetailsView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineDetailsView.js
index d55caf4..74c2ebb 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineDetailsView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineDetailsView.js
@@ -7,19 +7,13 @@
  */
 Timeline.TimelineDetailsView = class extends UI.VBox {
   /**
-   * @param {!TimelineModel.TimelineModel} timelineModel
-   * @param {!TimelineModel.TimelineFrameModel} frameModel
-   * @param {!SDK.FilmStripModel} filmStripModel
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    * @param {!Timeline.TimelineModeViewDelegate} delegate
    */
-  constructor(timelineModel, frameModel, filmStripModel, filters, delegate) {
+  constructor(filters, delegate) {
     super();
     this.element.classList.add('timeline-details');
 
-    this._model = timelineModel;
-    this._frameModel = frameModel;
-    this._filmStripModel = filmStripModel;
     this._detailsLinkifier = new Components.Linkifier();
 
     this._tabbedPane = new UI.TabbedPane();
@@ -39,15 +33,15 @@
     this._rangeDetailViews = new Map();
 
     if (!Runtime.experiments.isEnabled('timelineMultipleMainViews')) {
-      const bottomUpView = new Timeline.BottomUpTimelineTreeView(timelineModel, filters);
+      const bottomUpView = new Timeline.BottomUpTimelineTreeView(filters);
       this._appendTab(tabIds.BottomUp, Common.UIString('Bottom-Up'), bottomUpView);
       this._rangeDetailViews.set(tabIds.BottomUp, bottomUpView);
 
-      const callTreeView = new Timeline.CallTreeTimelineTreeView(timelineModel, filters);
+      const callTreeView = new Timeline.CallTreeTimelineTreeView(filters);
       this._appendTab(tabIds.CallTree, Common.UIString('Call Tree'), callTreeView);
       this._rangeDetailViews.set(tabIds.CallTree, callTreeView);
 
-      const eventsView = new Timeline.EventsTimelineTreeView(timelineModel, filters, delegate);
+      const eventsView = new Timeline.EventsTimelineTreeView(filters, delegate);
       this._appendTab(tabIds.Events, Common.UIString('Event Log'), eventsView);
       this._rangeDetailViews.set(tabIds.Events, eventsView);
     }
@@ -56,6 +50,17 @@
   }
 
   /**
+   * @param {?Timeline.PerformanceModel} model
+   */
+  setModel(model) {
+    this._model = model;
+    this._tabbedPane.closeTabs(
+        [Timeline.TimelineDetailsView.Tab.PaintProfiler, Timeline.TimelineDetailsView.Tab.LayerViewer], false);
+    this._lazyPaintProfilerView = null;
+    this._lazyLayersView = null;
+  }
+
+  /**
    * @param {!Node} node
    */
   _setContent(node) {
@@ -110,7 +115,7 @@
       case Timeline.TimelineSelection.Type.TraceEvent:
         var event = /** @type {!SDK.TracingModel.Event} */ (this._selection.object());
         Timeline.TimelineUIUtils.buildTraceEventDetails(
-            event, this._model, this._detailsLinkifier, true,
+            event, this._model.timelineModel(), this._detailsLinkifier, true,
             this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event));
         break;
       case Timeline.TimelineSelection.Type.Frame:
@@ -118,11 +123,10 @@
         var screenshotTime = frame.idle ?
             frame.startTime :
             frame.endTime;  // For idle frames, look at the state at the beginning of the frame.
-        var filmStripFrame = filmStripFrame = this._filmStripModel.frameByTimestamp(screenshotTime);
+        var filmStripFrame = this._model.filmStripModel().frameByTimestamp(screenshotTime);
         if (filmStripFrame && filmStripFrame.timestamp - frame.endTime > 10)
           filmStripFrame = null;
-        this._setContent(
-            Timeline.TimelineUIUtils.generateDetailsContentForFrame(this._frameModel, frame, filmStripFrame));
+        this._setContent(Timeline.TimelineUIUtils.generateDetailsContentForFrame(frame, filmStripFrame));
         if (frame.layerTree) {
           var layersView = this._layersView();
           layersView.showLayerTree(frame.layerTree);
@@ -132,7 +136,8 @@
         break;
       case Timeline.TimelineSelection.Type.NetworkRequest:
         var request = /** @type {!TimelineModel.TimelineModel.NetworkRequest} */ (this._selection.object());
-        Timeline.TimelineUIUtils.buildNetworkRequestDetails(request, this._model, this._detailsLinkifier)
+        Timeline.TimelineUIUtils
+            .buildNetworkRequestDetails(request, this._model.timelineModel(), this._detailsLinkifier)
             .then(this._setContent.bind(this));
         break;
       case Timeline.TimelineSelection.Type.Range:
@@ -159,7 +164,8 @@
   _layersView() {
     if (this._lazyLayersView)
       return this._lazyLayersView;
-    this._lazyLayersView = new Timeline.TimelineLayersView(this._model, this._showSnapshotInPaintProfiler.bind(this));
+    this._lazyLayersView =
+        new Timeline.TimelineLayersView(this._model.timelineModel(), this._showSnapshotInPaintProfiler.bind(this));
     return this._lazyLayersView;
   }
 
@@ -169,7 +175,7 @@
   _paintProfilerView() {
     if (this._lazyPaintProfilerView)
       return this._lazyPaintProfilerView;
-    this._lazyPaintProfilerView = new Timeline.TimelinePaintProfilerView(this._frameModel);
+    this._lazyPaintProfilerView = new Timeline.TimelinePaintProfilerView(this._model.frameModel());
     return this._lazyPaintProfilerView;
   }
 
@@ -219,7 +225,8 @@
    * @param {number} endTime
    */
   _updateSelectedRangeStats(startTime, endTime) {
-    this._setContent(Timeline.TimelineUIUtils.buildRangeStats(this._model, startTime, endTime));
+    if (this._model)
+      this._setContent(Timeline.TimelineUIUtils.buildRangeStats(this._model.timelineModel(), startTime, endTime));
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
index f984496..c28b7969 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
@@ -35,14 +35,21 @@
   /**
    * @param {string} id
    * @param {?string} title
-   * @param {!TimelineModel.TimelineModel} model
    */
-  constructor(id, title, model) {
+  constructor(id, title) {
     super();
     this.element.id = 'timeline-overview-' + id;
     this.element.classList.add('overview-strip');
+    /** @type {?Timeline.PerformanceModel} */
+    this._model = null;
     if (title)
       this.element.createChild('div', 'timeline-overview-strip-title').textContent = title;
+  }
+
+  /**
+   * @param {?Timeline.PerformanceModel} model
+   */
+  setModel(model) {
     this._model = model;
   }
 
@@ -66,11 +73,8 @@
  * @unrestricted
  */
 Timeline.TimelineEventOverviewInput = class extends Timeline.TimelineEventOverview {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   */
-  constructor(model) {
-    super('input', null, model);
+  constructor() {
+    super('input', null);
   }
 
   /**
@@ -78,7 +82,9 @@
    */
   update() {
     super.update();
-    var events = this._model.mainThreadEvents();
+    if (!this._model)
+      return;
+    var events = this._model.timelineModel().mainThreadEvents();
     var height = this.height();
     var descriptors = Timeline.TimelineUIUtils.eventDispatchDesciptors();
     /** @type {!Map.<string,!Timeline.TimelineUIUtils.EventDispatchTypeDescriptor>} */
@@ -91,8 +97,8 @@
     }
 
     var /** @const */ minWidth = 2 * window.devicePixelRatio;
-    var timeOffset = this._model.minimumRecordTime();
-    var timeSpan = this._model.maximumRecordTime() - timeOffset;
+    var timeOffset = this._model.timelineModel().minimumRecordTime();
+    var timeSpan = this._model.timelineModel().maximumRecordTime() - timeOffset;
     var canvasWidth = this.width();
     var scale = canvasWidth / timeSpan;
 
@@ -117,11 +123,8 @@
  * @unrestricted
  */
 Timeline.TimelineEventOverviewNetwork = class extends Timeline.TimelineEventOverview {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   */
-  constructor(model) {
-    super('network', Common.UIString('NET'), model);
+  constructor() {
+    super('network', Common.UIString('NET'));
   }
 
   /**
@@ -129,16 +132,19 @@
    */
   update() {
     super.update();
+    if (!this._model)
+      return;
+    var timelineModel = this._model.timelineModel();
     var bandHeight = this.height() / 2;
-    var timeOffset = this._model.minimumRecordTime();
-    var timeSpan = this._model.maximumRecordTime() - timeOffset;
+    var timeOffset = timelineModel.minimumRecordTime();
+    var timeSpan = timelineModel.maximumRecordTime() - timeOffset;
     var canvasWidth = this.width();
     var scale = canvasWidth / timeSpan;
     var highPath = new Path2D();
     var lowPath = new Path2D();
     var priorities = Protocol.Network.ResourcePriority;
     var highPrioritySet = new Set([priorities.VeryHigh, priorities.High, priorities.Medium]);
-    for (var request of this._model.networkRequests()) {
+    for (var request of timelineModel.networkRequests()) {
       var path = highPrioritySet.has(request.priority) ? highPath : lowPath;
       var s = Math.max(Math.floor((request.startTime - timeOffset) * scale), 0);
       var e = Math.min(Math.ceil((request.endTime - timeOffset) * scale + 1), canvasWidth);
@@ -159,11 +165,8 @@
  * @unrestricted
  */
 Timeline.TimelineEventOverviewCPUActivity = class extends Timeline.TimelineEventOverview {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   */
-  constructor(model) {
-    super('cpu-activity', Common.UIString('CPU'), model);
+  constructor() {
+    super('cpu-activity', Common.UIString('CPU'));
     this._backgroundCanvas = this.element.createChild('canvas', 'fill background');
   }
 
@@ -181,12 +184,15 @@
    */
   update() {
     super.update();
+    if (!this._model)
+      return;
+    var timelineModel = this._model.timelineModel();
     var /** @const */ quantSizePx = 4 * window.devicePixelRatio;
     var width = this.width();
     var height = this.height();
     var baseLine = height;
-    var timeOffset = this._model.minimumRecordTime();
-    var timeSpan = this._model.maximumRecordTime() - timeOffset;
+    var timeOffset = timelineModel.minimumRecordTime();
+    var timeSpan = timelineModel.maximumRecordTime() - timeOffset;
     var scale = width / timeSpan;
     var quantTime = quantSizePx / scale;
     var categories = Timeline.TimelineUIUtils.categories();
@@ -198,10 +204,10 @@
       categories[categoryOrder[i]]._overviewIndex = i;
 
     var backgroundContext = this._backgroundCanvas.getContext('2d');
-    for (var thread of this._model.virtualThreads())
+    for (var thread of timelineModel.virtualThreads())
       drawThreadEvents(backgroundContext, thread.events);
     applyPattern(backgroundContext);
-    drawThreadEvents(this.context(), this._model.mainThreadEvents());
+    drawThreadEvents(this.context(), timelineModel.mainThreadEvents());
 
     /**
      * @param {!CanvasRenderingContext2D} ctx
@@ -280,13 +286,8 @@
  * @unrestricted
  */
 Timeline.TimelineEventOverviewResponsiveness = class extends Timeline.TimelineEventOverview {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   * @param {!TimelineModel.TimelineFrameModel} frameModel
-   */
-  constructor(model, frameModel) {
-    super('responsiveness', null, model);
-    this._frameModel = frameModel;
+  constructor() {
+    super('responsiveness', null);
   }
 
   /**
@@ -294,11 +295,14 @@
    */
   update() {
     super.update();
+    if (!this._model)
+      return;
     var height = this.height();
-    var timeOffset = this._model.minimumRecordTime();
-    var timeSpan = this._model.maximumRecordTime() - timeOffset;
+
+    var timeOffset = this._model.timelineModel().minimumRecordTime();
+    var timeSpan = this._model.timelineModel().maximumRecordTime() - timeOffset;
     var scale = this.width() / timeSpan;
-    var frames = this._frameModel.frames();
+    var frames = this._model.frames();
     // This is due to usage of new signatures of fill() and storke() that closure compiler does not recognize.
     var ctx = /** @type {!Object} */ (this.context());
     var fillPath = new Path2D();
@@ -310,7 +314,7 @@
       paintWarningDecoration(frame.startTime, frame.duration);
     }
 
-    var events = this._model.mainThreadEvents();
+    var events = this._model.timelineModel().mainThreadEvents();
     for (var i = 0; i < events.length; ++i) {
       if (!TimelineModel.TimelineData.forEvent(events[i]).warning)
         continue;
@@ -341,13 +345,8 @@
  * @unrestricted
  */
 Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOverview {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   * @param {!SDK.FilmStripModel} filmStripModel
-   */
-  constructor(model, filmStripModel) {
-    super('filmstrip', null, model);
-    this._filmStripModel = filmStripModel;
+  constructor() {
+    super('filmstrip', null);
     this.reset();
   }
 
@@ -356,7 +355,7 @@
    */
   update() {
     super.update();
-    var frames = this._filmStripModel.frames();
+    var frames = this._model ? this._model.filmStripModel().frames() : [];
     if (!frames.length)
       return;
 
@@ -412,14 +411,15 @@
    * @param {number} imageHeight
    */
   _drawFrames(imageWidth, imageHeight) {
-    if (!imageWidth)
+    if (!imageWidth || !this._model)
       return;
-    if (!this._filmStripModel.frames().length)
+    var filmStripModel = this._model.filmStripModel();
+    if (!filmStripModel.frames().length)
       return;
     var padding = Timeline.TimelineFilmStripOverview.Padding;
     var width = this.width();
-    var zeroTime = this._filmStripModel.zeroTime();
-    var spanTime = this._filmStripModel.spanTime();
+    var zeroTime = filmStripModel.zeroTime();
+    var spanTime = filmStripModel.spanTime();
     var scale = spanTime / width;
     var context = this.context();
     var drawGeneration = this._drawGeneration;
@@ -427,7 +427,7 @@
     context.beginPath();
     for (var x = padding; x < width; x += imageWidth + 2 * padding) {
       var time = zeroTime + (x + imageWidth / 2) * scale;
-      var frame = this._filmStripModel.frameByTimestamp(time);
+      var frame = filmStripModel.frameByTimestamp(time);
       if (!frame)
         continue;
       context.rect(x - 0.5, 0.5, imageWidth + 1, imageHeight + 1);
@@ -455,11 +455,11 @@
    * @return {!Promise<?Element>}
    */
   popoverElementPromise(x) {
-    if (!this._filmStripModel.frames().length)
+    if (!this._model || !this._model.filmStripModel().frames().length)
       return Promise.resolve(/** @type {?Element} */ (null));
 
     var time = this.calculator().positionToTime(x);
-    var frame = this._filmStripModel.frameByTimestamp(time);
+    var frame = this._model.filmStripModel().frameByTimestamp(time);
     if (frame === this._lastFrame)
       return Promise.resolve(this._lastElement);
     var imagePromise = frame ? this._imageByFrame(frame) : Promise.resolve(this._emptyImage);
@@ -498,13 +498,8 @@
  * @unrestricted
  */
 Timeline.TimelineEventOverviewFrames = class extends Timeline.TimelineEventOverview {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   * @param {!TimelineModel.TimelineFrameModel} frameModel
-   */
-  constructor(model, frameModel) {
-    super('framerate', Common.UIString('FPS'), model);
-    this._frameModel = frameModel;
+  constructor() {
+    super('framerate', Common.UIString('FPS'));
   }
 
   /**
@@ -512,21 +507,23 @@
    */
   update() {
     super.update();
+    if (!this._model)
+      return;
+    var frames = this._model.frames();
+    if (!frames.length)
+      return;
     var height = this.height();
     var /** @const */ padding = 1 * window.devicePixelRatio;
     var /** @const */ baseFrameDurationMs = 1e3 / 60;
     var visualHeight = height - 2 * padding;
-    var timeOffset = this._model.minimumRecordTime();
-    var timeSpan = this._model.maximumRecordTime() - timeOffset;
+    var timeOffset = this._model.timelineModel().minimumRecordTime();
+    var timeSpan = this._model.timelineModel().maximumRecordTime() - timeOffset;
     var scale = this.width() / timeSpan;
-    var frames = this._frameModel.frames();
     var baseY = height - padding;
     var ctx = this.context();
     var bottomY = baseY + 10 * window.devicePixelRatio;
     var x = 0;
     var y = bottomY;
-    if (!frames.length)
-      return;
 
     var lineWidth = window.devicePixelRatio;
     var offset = lineWidth & 1 ? 0.5 : 0;
@@ -543,11 +540,9 @@
       ctx.lineTo(x, y + tickDepth);
       ctx.lineTo(x, y);
     }
-    if (frames.length) {
-      var lastFrame = frames.peekLast();
-      x = Math.round((lastFrame.startTime + lastFrame.duration - timeOffset) * scale) + offset;
-      ctx.lineTo(x, y);
-    }
+    var lastFrame = frames.peekLast();
+    x = Math.round((lastFrame.startTime + lastFrame.duration - timeOffset) * scale) + offset;
+    ctx.lineTo(x, y);
     ctx.lineTo(x, bottomY);
     ctx.fillStyle = 'hsl(110, 50%, 88%)';
     ctx.strokeStyle = 'hsl(110, 50%, 60%)';
@@ -561,11 +556,8 @@
  * @unrestricted
  */
 Timeline.TimelineEventOverviewMemory = class extends Timeline.TimelineEventOverview {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   */
-  constructor(model) {
-    super('memory', Common.UIString('HEAP'), model);
+  constructor() {
+    super('memory', Common.UIString('HEAP'));
     this._heapSizeLabel = this.element.createChild('div', 'memory-graph-label');
   }
 
@@ -580,7 +572,7 @@
     super.update();
     var ratio = window.devicePixelRatio;
 
-    var events = this._model.mainThreadEvents();
+    var events = this._model ? this._model.timelineModel().mainThreadEvents() : [];
     if (!events.length) {
       this.resetHeapSizeLabels();
       return;
@@ -589,8 +581,8 @@
     var lowerOffset = 3 * ratio;
     var maxUsedHeapSize = 0;
     var minUsedHeapSize = 100000000000;
-    var minTime = this._model.minimumRecordTime();
-    var maxTime = this._model.maximumRecordTime();
+    var minTime = this._model.timelineModel().minimumRecordTime();
+    var maxTime = this._model.timelineModel().maximumRecordTime();
     /**
      * @param {!SDK.TracingModel.Event} event
      * @return {boolean}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
index 447380ad..48293ea1 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
@@ -34,21 +34,20 @@
  */
 Timeline.TimelineFlameChartDataProvider = class {
   /**
-   * @param {!TimelineModel.TimelineModel} model
-   * @param {!TimelineModel.TimelineFrameModel} frameModel
-   * @param {!TimelineModel.TimelineIRModel} irModel
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    */
-  constructor(model, frameModel, irModel, filters) {
+  constructor(filters) {
     this.reset();
     this._font = '11px ' + Host.fontFamily();
-    this._model = model;
     this._filters = filters;
     /** @type {?PerfUI.FlameChart.TimelineData} */
     this._timelineData = null;
     this._currentLevel = 0;
-    this._frameModel = frameModel;
-    this._irModel = irModel;
+    /** @type {?Timeline.PerformanceModel} */
+    this._performanceModel = null;
+    /** @type {?TimelineModel.TimelineModel} */
+    this._model = null;
+
     this._consoleColorGenerator =
         new PerfUI.FlameChart.ColorGenerator({min: 30, max: 55}, {min: 70, max: 100, count: 6}, 50, 0.7);
     this._extensionColorGenerator =
@@ -78,6 +77,15 @@
   }
 
   /**
+   * @param {?Timeline.PerformanceModel} performanceModel
+   */
+  setModel(performanceModel) {
+    this.reset();
+    this._performanceModel = performanceModel;
+    this._model = performanceModel && performanceModel.timelineModel();
+  }
+
+  /**
    * @override
    * @param {number} entryIndex
    * @return {?string}
@@ -164,13 +172,15 @@
       return this._timelineData;
 
     this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []);
+    if (!this._model)
+      return this._timelineData;
 
     this._minimumBoundary = this._model.minimumRecordTime();
     this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTime() - this._minimumBoundary;
     this._currentLevel = 0;
 
     this._appendHeader(Common.UIString('Frames'), this._staticHeader);
-    this._appendFrameBars(this._frameModel.frames());
+    this._appendFrameBars(this._performanceModel.frames());
 
     this._appendHeader(Common.UIString('Interactions'), this._interactionsHeaderLevel1);
     this._appendInteractionRecords();
@@ -408,7 +418,7 @@
   }
 
   _appendInteractionRecords() {
-    this._irModel.interactionRecords().forEach(this._appendSegment, this);
+    this._performanceModel.interactionRecords().forEach(this._appendSegment, this);
     this._entryTypeByLevel[this._currentLevel++] = Timeline.TimelineFlameChartEntryType.InteractionRecord;
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js
index bf75d60..e4729621 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js
@@ -102,23 +102,18 @@
 Timeline.TimelineFlameChartView = class extends UI.VBox {
   /**
    * @param {!Timeline.TimelineModeViewDelegate} delegate
-   * @param {!TimelineModel.TimelineModel} timelineModel
-   * @param {!TimelineModel.TimelineFrameModel} frameModel
-   * @param {!SDK.FilmStripModel} filmStripModel
-   * @param {!TimelineModel.TimelineIRModel} irModel
-   * @param {!Array<!{title: string, model: !SDK.TracingModel}>} extensionModels
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    */
-  constructor(delegate, timelineModel, frameModel, filmStripModel, irModel, extensionModels, filters) {
+  constructor(delegate, filters) {
     super();
     this.element.classList.add('timeline-flamechart');
     this._delegate = delegate;
-    this._model = timelineModel;
-    this._extensionModels = extensionModels;
+    /** @type {?Timeline.PerformanceModel} */
+    this._model = null;
 
     this._splitWidget = new UI.SplitWidget(false, false, 'timelineFlamechartMainView', 150);
 
-    this._dataProvider = new Timeline.TimelineFlameChartDataProvider(this._model, frameModel, irModel, filters);
+    this._dataProvider = new Timeline.TimelineFlameChartDataProvider(filters);
     var mainViewGroupExpansionSetting = Common.settings.createSetting('timelineFlamechartMainViewGroupExpansion', {});
     this._mainView = new PerfUI.FlameChart(this._dataProvider, this, mainViewGroupExpansionSetting);
     this._mainView.alwaysShowVerticalScroll();
@@ -126,27 +121,26 @@
 
     var networkViewGroupExpansionSetting =
         Common.settings.createSetting('timelineFlamechartNetworkViewGroupExpansion', {});
-    this._networkDataProvider = new Timeline.TimelineFlameChartNetworkDataProvider(this._model);
+    this._networkDataProvider = new Timeline.TimelineFlameChartNetworkDataProvider();
     this._networkView = new PerfUI.FlameChart(this._networkDataProvider, this, networkViewGroupExpansionSetting);
     this._networkView.alwaysShowVerticalScroll();
     networkViewGroupExpansionSetting.addChangeListener(this.resizeToPreferredHeights.bind(this));
 
-    const networkPane = new UI.VBox();
-    networkPane.setMinimumSize(23, 23);
-    this._networkView.show(networkPane.element);
-    this._splitResizer = networkPane.element.createChild('div', 'timeline-flamechart-resizer');
-    this._splitWidget.hideDefaultResizer();
+    this._networkPane = new UI.VBox();
+    this._networkPane.setMinimumSize(23, 23);
+    this._networkView.show(this._networkPane.element);
+    this._splitResizer = this._networkPane.element.createChild('div', 'timeline-flamechart-resizer');
+    this._splitWidget.hideDefaultResizer(true);
     this._splitWidget.installResizer(this._splitResizer);
 
     this._splitWidget.setMainWidget(this._mainView);
-    this._splitWidget.setSidebarWidget(networkPane);
+    this._splitWidget.setSidebarWidget(this._networkPane);
 
     if (Runtime.experiments.isEnabled('timelineMultipleMainViews')) {
       // Create top level properties splitter.
       this._detailsSplitWidget = new UI.SplitWidget(false, true, 'timelinePanelDetailsSplitViewState');
       this._detailsSplitWidget.element.classList.add('timeline-details-split');
-      this._detailsView =
-          new Timeline.TimelineDetailsView(timelineModel, frameModel, filmStripModel, filters, delegate);
+      this._detailsView = new Timeline.TimelineDetailsView(filters, delegate);
       this._detailsSplitWidget.installResizer(this._detailsView.headerElement());
       this._detailsSplitWidget.setMainWidget(this._splitWidget);
       this._detailsSplitWidget.setSidebarWidget(this._detailsView);
@@ -161,18 +155,9 @@
     this._networkView.addEventListener(PerfUI.FlameChart.Events.EntrySelected, this._onNetworkEntrySelected, this);
     this._nextExtensionIndex = 0;
 
-    this._boundRefresh = this.refreshRecords.bind(this);
-    Bindings.blackboxManager.addChangeListener(this._boundRefresh);
+    this._boundRefresh = this._refresh.bind(this);
   }
 
-  /**
-   * @override
-   */
-  dispose() {
-    this._mainView.removeEventListener(PerfUI.FlameChart.Events.EntrySelected, this._onMainEntrySelected, this);
-    this._networkView.removeEventListener(PerfUI.FlameChart.Events.EntrySelected, this._onNetworkEntrySelected, this);
-    Bindings.blackboxManager.removeChangeListener(this._boundRefresh);
-  }
 
   /**
    * @override
@@ -202,11 +187,29 @@
 
   /**
    * @override
+   * @param {?Timeline.PerformanceModel} model
    */
-  refreshRecords() {
-    this._dataProvider.reset();
+  setModel(model) {
+    var extensionDataAdded = Timeline.PerformanceModel.Events.ExtensionDataAdded;
+    if (this._model)
+      this._model.removeEventListener(extensionDataAdded, this._appendExtensionData, this);
+    this._model = model;
+    if (this._model)
+      this._model.addEventListener(extensionDataAdded, this._appendExtensionData, this);
+    this._refresh();
+  }
+
+  _refresh() {
+    this._dataProvider.setModel(this._model);
+    this._mainView.reset();
+
+    this._networkDataProvider.setModel(this._model);
+    this._networkView.reset();
+
+    this._detailsView.setModel(this._model);
+
     this._nextExtensionIndex = 0;
-    this.extensionDataAdded();
+    this._appendExtensionData();
     this._mainView.scheduleUpdate();
 
     this._networkDataProvider.reset();
@@ -221,12 +224,12 @@
     this._networkView.scheduleUpdate();
   }
 
-  /**
-   * @override
-   */
-  extensionDataAdded() {
-    while (this._nextExtensionIndex < this._extensionModels.length)
-      this._dataProvider.appendExtensionEvents(this._extensionModels[this._nextExtensionIndex++]);
+  _appendExtensionData() {
+    if (!this._model)
+      return;
+    var extensions = this._model.extensionInfo();
+    while (this._nextExtensionIndex < extensions.length)
+      this._dataProvider.appendExtensionEvents(extensions[this._nextExtensionIndex++]);
     this._mainView.scheduleUpdate();
   }
 
@@ -246,7 +249,15 @@
   /**
    * @override
    */
+  willHide() {
+    Bindings.blackboxManager.removeChangeListener(this._boundRefresh);
+  }
+
+  /**
+   * @override
+   */
   wasShown() {
+    Bindings.blackboxManager.addChangeListener(this._boundRefresh);
     this._mainView.scheduleUpdate();
     this._networkView.scheduleUpdate();
   }
@@ -261,18 +272,6 @@
 
   /**
    * @override
-   */
-  reset() {
-    this._dataProvider.reset();
-    this._mainView.reset();
-    this._mainView.setWindowTimes(0, Infinity);
-    this._networkDataProvider.reset();
-    this._networkView.reset();
-    this._networkView.setWindowTimes(0, Infinity);
-  }
-
-  /**
-   * @override
    * @param {number} startTime
    * @param {number} endTime
    */
@@ -321,9 +320,11 @@
   }
 
   resizeToPreferredHeights() {
+    this._networkPane.element.classList.toggle(
+        'timeline-network-resizer-disabled', !this._networkDataProvider.isExpanded());
     this._splitWidget.setSidebarSize(
         this._networkDataProvider.preferredHeight() + this._splitResizer.clientHeight + PerfUI.FlameChart.HeaderHeight +
-        3);
+        2);
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js
index 8ad5a4698..0dfc8e0 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js
@@ -8,16 +8,16 @@
  */
 Timeline.TimelineLoader = class {
   /**
-   * @param {!SDK.TracingModel} model
-   * @param {!Timeline.LoaderClient} delegate
+   * @param {!Timeline.TimelineLoader.Client} client
    */
-  constructor(model, delegate) {
-    this._model = model;
-    this._delegate = delegate;
+  constructor(client) {
+    this._client = client;
+
+    this._backingStorage = new Bindings.TempFileBackingStorage('tracing');
+    this._tracingModel = new SDK.TracingModel(this._backingStorage);
 
     /** @type {?function()} */
     this._canceledCallback = null;
-
     this._state = Timeline.TimelineLoader.State.Initial;
     this._buffer = '';
     this._firstChunk = true;
@@ -29,13 +29,12 @@
   }
 
   /**
-   * @param {!SDK.TracingModel} model
    * @param {!File} file
-   * @param {!Timeline.TimelineLifecycleDelegate} delegate
+   * @param {!Timeline.TimelineLoader.Client} client
    * @return {!Timeline.TimelineLoader}
    */
-  static loadFromFile(model, file, delegate) {
-    var loader = new Timeline.TimelineLoader(model, delegate);
+  static loadFromFile(file, client) {
+    var loader = new Timeline.TimelineLoader(client);
     var fileReader = Timeline.TimelineLoader._createFileReader(file, loader);
     loader._canceledCallback = fileReader.cancel.bind(fileReader);
     loader._totalSize = file.size;
@@ -44,13 +43,12 @@
   }
 
   /**
-   * @param {!SDK.TracingModel} model
    * @param {string} url
-   * @param {!Timeline.LoaderClient} delegate
+   * @param {!Timeline.TimelineLoader.Client} client
    * @return {!Timeline.TimelineLoader}
    */
-  static loadFromURL(model, url, delegate) {
-    var stream = new Timeline.TimelineLoader(model, delegate);
+  static loadFromURL(url, client) {
+    var stream = new Timeline.TimelineLoader(client);
     Host.ResourceLoader.loadAsStream(url, null, stream);
     return stream;
   }
@@ -65,9 +63,10 @@
   }
 
   cancel() {
-    this._model.reset();
-    this._delegate.loadingComplete(false);
-    this._delegate = null;
+    this._tracingModel = null;
+    this._backingStorage.reset();
+    this._client.loadingComplete(null, null);
+    this._client = null;
     if (this._canceledCallback)
       this._canceledCallback();
   }
@@ -77,11 +76,11 @@
    * @param {string} chunk
    */
   write(chunk) {
-    if (!this._delegate)
+    if (!this._client)
       return;
     this._loadedBytes += chunk.length;
     if (!this._firstChunk)
-      this._delegate.loadingProgress(this._totalSize ? this._loadedBytes / this._totalSize : undefined);
+      this._client.loadingProgress(this._totalSize ? this._loadedBytes / this._totalSize : undefined);
 
     if (this._state === Timeline.TimelineLoader.State.Initial) {
       if (chunk[0] === '{') {
@@ -123,7 +122,7 @@
     var json = data + ']';
 
     if (this._firstChunk) {
-      this._delegate.loadingStarted();
+      this._client.loadingStarted();
     } else {
       var commaIndex = json.indexOf(',');
       if (commaIndex !== -1)
@@ -141,7 +140,6 @@
 
     if (this._firstChunk) {
       this._firstChunk = false;
-      this._model.reset();
       if (this._looksLikeAppVersion(items[0])) {
         this._reportErrorAndCancelLoading(Common.UIString('Legacy Timeline format is not supported.'));
         return;
@@ -149,7 +147,7 @@
     }
 
     try {
-      this._model.addEvents(items);
+      this._tracingModel.addEvents(items);
     } catch (e) {
       this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline data: %s', e.toString()));
       return;
@@ -177,9 +175,10 @@
    * @override
    */
   close() {
-    this._model.tracingComplete();
-    if (this._delegate)
-      this._delegate.loadingComplete(true);
+    if (!this._client)
+      return;
+    this._tracingModel.tracingComplete();
+    this._client.loadingComplete(this._tracingModel, this._backingStorage);
   }
 
   /**
@@ -226,6 +225,25 @@
 
 Timeline.TimelineLoader.TransferChunkLengthBytes = 5000000;
 
+/**
+ * @interface
+ */
+Timeline.TimelineLoader.Client = function() {};
+
+Timeline.TimelineLoader.Client.prototype = {
+  loadingStarted() {},
+
+  /**
+   * @param {number=} progress
+   */
+  loadingProgress(progress) {},
+
+  /**
+   * @param {?SDK.TracingModel} tracingModel
+   * @param {?Bindings.TempFileBackingStorage} backingStorage
+   */
+  loadingComplete(tracingModel, backingStorage) {},
+};
 
 /**
  * @enum {symbol}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js
index 36ef2aa..308cb20 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineNetworkFlameChart.js
@@ -7,12 +7,10 @@
  * @unrestricted
  */
 Timeline.TimelineFlameChartNetworkDataProvider = class {
-  /**
-   * @param {!TimelineModel.TimelineModel} model
-   */
-  constructor(model) {
+  constructor() {
     this._font = '11px ' + Host.fontFamily();
-    this._model = model;
+    /** @type {?TimelineModel.TimelineModel} */
+    this._model = null;
     this.reset();
     this._style = {
       padding: 4,
@@ -30,6 +28,13 @@
   }
 
   /**
+   * @param {?Timeline.PerformanceModel} performanceModel
+   */
+  setModel(performanceModel) {
+    this._model = performanceModel && performanceModel.timelineModel();
+  }
+
+  /**
    * @return {boolean}
    */
   isEmpty() {
@@ -55,7 +60,8 @@
     /** @type {!Array<!TimelineModel.TimelineModel.NetworkRequest>} */
     this._requests = [];
     this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []);
-    this._appendTimelineData(this._model.mainThreadEvents());
+    if (this._model)
+      this._appendTimelineData(this._model.mainThreadEvents());
     return this._timelineData;
   }
 
@@ -367,6 +373,13 @@
   }
 
   /**
+   * @return {boolean}
+   */
+  isExpanded() {
+    return this._group.expanded;
+  }
+
+  /**
    * @override
    * @param {number} value
    * @param {number=} precision
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index 6a8f6d6a..57e5e602 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -30,7 +30,7 @@
  */
 
 /**
- * @implements {Timeline.TimelineLifecycleDelegate}
+ * @implements {Timeline.TimelineController.Client}
  * @implements {Timeline.TimelineModeViewDelegate}
  * @implements {UI.Searchable}
  * @unrestricted
@@ -60,16 +60,11 @@
       this._filters.push(new TimelineModel.ExcludeTopLevelFilter());
     }
 
-    // Create models.
-    this._tracingModelBackingStorage = new Bindings.TempFileBackingStorage('tracing');
-    this._tracingModel = new SDK.TracingModel(this._tracingModelBackingStorage);
-    this._model = new TimelineModel.TimelineModel();
-    this._frameModel =
-        new TimelineModel.TimelineFrameModel(event => Timeline.TimelineUIUtils.eventStyle(event).category.name);
-    this._filmStripModel = new SDK.FilmStripModel(this._tracingModel);
-    this._irModel = new TimelineModel.TimelineIRModel();
-    /** @type {!Array<!{title: string, model: !SDK.TracingModel}>} */
-    this._extensionTracingModels = [];
+    /** @type {?Timeline.PerformanceModel} */
+    this._performanceModel = null;
+    /** @type {?Timeline.PerformanceModel} */
+    this._pendingPerformanceModel = null;
+
     this._cpuThrottlingManager = new Components.CPUThrottlingManager();
 
     /** @type {!Array<!Timeline.TimelineModeView>} */
@@ -100,6 +95,9 @@
     this._overviewPane.addEventListener(
         PerfUI.TimelineOverviewPane.Events.WindowChanged, this._onWindowChanged.bind(this));
     this._overviewPane.show(topPaneElement);
+    /** @type {!Array<!Timeline.TimelineEventOverview>} */
+    this._overviewControls = [];
+
     this._statusPaneContainer = this._timelinePane.element.createChild('div', 'status-pane-container fill');
 
     this._createFileSelector();
@@ -129,8 +127,7 @@
       // Create top level properties splitter.
       this._detailsSplitWidget = new UI.SplitWidget(false, true, 'timelinePanelDetailsSplitViewState', 400);
       this._detailsSplitWidget.element.classList.add('timeline-details-split');
-      this._detailsView =
-          new Timeline.TimelineDetailsView(this._model, this._frameModel, this._filmStripModel, this._filters, this);
+      this._detailsView = new Timeline.TimelineDetailsView(this._filters, this);
       this._detailsSplitWidget.installResizer(this._detailsView.headerElement());
       this._detailsSplitWidget.setSidebarWidget(this._detailsView);
       this._detailsSplitWidget.setMainWidget(this._searchableView);
@@ -151,10 +148,6 @@
     this._selectedSearchResult;
     /** @type {!Array<!SDK.TracingModel.Event>}|undefined */
     this._searchResults;
-    /** @type {?symbol} */
-    this._sessionGeneration = null;
-    /** @type {number} */
-    this._recordingStartTime = 0;
   }
 
   /**
@@ -187,24 +180,6 @@
   }
 
   /**
-   * @return {number}
-   */
-  windowStartTime() {
-    if (this._windowStartTime)
-      return this._windowStartTime;
-    return this._model.minimumRecordTime();
-  }
-
-  /**
-   * @return {number}
-   */
-  windowEndTime() {
-    if (this._windowEndTime < Infinity)
-      return this._windowEndTime;
-    return this._model.maximumRecordTime() || Infinity;
-  }
-
-  /**
    * @param {!Common.Event} event
    */
   _onWindowChanged(event) {
@@ -244,8 +219,8 @@
    * @param {!Timeline.TimelineModeView} modeView
    */
   _addModeView(modeView) {
-    modeView.setWindowTimes(this.windowStartTime(), this.windowEndTime());
-    modeView.refreshRecords();
+    modeView.setModel(this._performanceModel);
+    modeView.setWindowTimes(this._windowStartTime, this._windowEndTime);
     var splitWidget =
         this._stackView.appendView(modeView.view(), 'timelinePanelTimelineStackSplitViewState', undefined, 112);
     var resizer = modeView.resizerElement();
@@ -257,7 +232,6 @@
   }
 
   _removeAllModeViews() {
-    this._currentViews.forEach(view => view.dispose());
     this._currentViews = [];
     this._stackView.detachChildWidgets();
   }
@@ -388,6 +362,7 @@
   _prepareToLoadTimeline() {
     console.assert(this._state === Timeline.TimelinePanel.State.Idle);
     this._setState(Timeline.TimelinePanel.State.Loading);
+    this._pendingPerformanceModel = new Timeline.PerformanceModel();
   }
 
   _createFileSelector() {
@@ -412,7 +387,7 @@
   _saveToFile() {
     if (this._state !== Timeline.TimelinePanel.State.Idle)
       return true;
-    if (this._model.isEmpty())
+    if (!this._performanceModel)
       return true;
 
     var now = new Date();
@@ -427,7 +402,7 @@
       if (!accepted)
         return;
       var saver = new Timeline.TracingTimelineSaver();
-      this._tracingModelBackingStorage.writeToStream(stream, saver);
+      this._backingStorage.writeToStream(stream, saver);
     }
     stream.open(fileName, callback.bind(this));
     return true;
@@ -448,7 +423,7 @@
     if (this._state !== Timeline.TimelinePanel.State.Idle)
       return;
     this._prepareToLoadTimeline();
-    this._loader = Timeline.TimelineLoader.loadFromFile(this._tracingModel, file, this);
+    this._loader = Timeline.TimelineLoader.loadFromFile(file, this);
     this._createFileSelector();
   }
 
@@ -459,29 +434,27 @@
     if (this._state !== Timeline.TimelinePanel.State.Idle)
       return;
     this._prepareToLoadTimeline();
-    this._loader = Timeline.TimelineLoader.loadFromURL(this._tracingModel, url, this);
-  }
-
-  _refreshViews() {
-    this._currentViews.forEach(view => view.refreshRecords());
+    this._loader = Timeline.TimelineLoader.loadFromURL(url, this);
   }
 
   _onModeChanged() {
     const showMemory = this._showMemorySetting.get();
     const showScreenshots = this._showScreenshotsSetting.get();
     // Set up overview controls.
-    var overviewControls = [];
-    overviewControls.push(new Timeline.TimelineEventOverviewResponsiveness(this._model, this._frameModel));
+    this._overviewControls = [];
+    this._overviewControls.push(new Timeline.TimelineEventOverviewResponsiveness());
     if (Runtime.experiments.isEnabled('inputEventsOnTimelineOverview'))
-      overviewControls.push(new Timeline.TimelineEventOverviewInput(this._model));
-    overviewControls.push(new Timeline.TimelineEventOverviewFrames(this._model, this._frameModel));
-    overviewControls.push(new Timeline.TimelineEventOverviewCPUActivity(this._model));
-    overviewControls.push(new Timeline.TimelineEventOverviewNetwork(this._model));
+      this._overviewControls.push(new Timeline.TimelineEventOverviewInput());
+    this._overviewControls.push(new Timeline.TimelineEventOverviewFrames());
+    this._overviewControls.push(new Timeline.TimelineEventOverviewCPUActivity());
+    this._overviewControls.push(new Timeline.TimelineEventOverviewNetwork());
     if (showScreenshots)
-      overviewControls.push(new Timeline.TimelineFilmStripOverview(this._model, this._filmStripModel));
+      this._overviewControls.push(new Timeline.TimelineFilmStripOverview());
     if (showMemory)
-      overviewControls.push(new Timeline.TimelineEventOverviewMemory(this._model));
-    this._overviewPane.setOverviewControls(overviewControls);
+      this._overviewControls.push(new Timeline.TimelineEventOverviewMemory());
+    for (var control of this._overviewControls)
+      control.setModel(this._performanceModel);
+    this._overviewPane.setOverviewControls(this._overviewControls);
 
     // Set up the main view.
     this._removeAllModeViews();
@@ -494,23 +467,21 @@
       this._stackView.show(this._tabbedPane.visibleView.element);
     }
     if (viewMode === Timeline.TimelinePanel.ViewMode.FlameChart) {
-      this._flameChart = new Timeline.TimelineFlameChartView(
-          this, this._model, this._frameModel, this._filmStripModel, this._irModel, this._extensionTracingModels,
-          this._filters);
+      this._flameChart = new Timeline.TimelineFlameChartView(this, this._filters);
       this._addModeView(this._flameChart);
       if (showMemory)
-        this._addModeView(new Timeline.CountersGraph(this, this._model));
+        this._addModeView(new Timeline.CountersGraph(this));
     } else {
       var innerView;
       switch (viewMode) {
         case Timeline.TimelinePanel.ViewMode.CallTree:
-          innerView = new Timeline.CallTreeTimelineTreeView(this._model, this._filters);
+          innerView = new Timeline.CallTreeTimelineTreeView(this._filters);
           break;
         case Timeline.TimelinePanel.ViewMode.EventLog:
-          innerView = new Timeline.EventsTimelineTreeView(this._model, this._filters, this);
+          innerView = new Timeline.EventsTimelineTreeView(this._filters, this);
           break;
         default:
-          innerView = new Timeline.BottomUpTimelineTreeView(this._model, this._filters);
+          innerView = new Timeline.BottomUpTimelineTreeView(this._filters);
           break;
       }
       const treeView = new Timeline.TimelineTreeModeView(this, innerView);
@@ -571,7 +542,6 @@
     this._setState(Timeline.TimelinePanel.State.StartPending);
     this._showRecordingStarted();
 
-    this._sessionGeneration = Symbol('timelineSessionGeneration');
     this._autoRecordGeneration = userInitiated ? null : Symbol('Generation');
     var enabledTraceProviders = Extensions.extensionServer.traceProviders().filter(
         provider => Timeline.TimelinePanel._settingForTraceProvider(provider).get());
@@ -582,9 +552,9 @@
       captureFilmStrip: this._showScreenshotsSetting.get()
     };
 
-    this._controller = new Timeline.TimelineController(mainTarget, this, this._tracingModel);
+    this._pendingPerformanceModel = new Timeline.PerformanceModel();
+    this._controller = new Timeline.TimelineController(mainTarget, this._pendingPerformanceModel, this);
     this._controller.startRecording(recordingOptions, enabledTraceProviders);
-    this._recordingStartTime = Date.now();
 
     Host.userMetrics.actionTaken(
         userInitiated ? Host.UserMetrics.Action.TimelineStarted : Host.UserMetrics.Action.TimelinePageReloadStarted);
@@ -628,27 +598,42 @@
     this._showLandingPage();
     if (this._detailsSplitWidget)
       this._detailsSplitWidget.hideSidebar();
-    this._sessionGeneration = null;
-    this._recordingStartTime = 0;
     this._reset();
   }
 
   _reset() {
     PerfUI.LineLevelProfile.instance().reset();
-    this._tracingModel.reset();
-    this._model.reset();
-    for (let extensionEntry of this._extensionTracingModels)
-      extensionEntry.model.reset();
-    this._extensionTracingModels.splice(0);
-
-    this.requestWindowTimes(0, Infinity);
+    this._setModel(null);
     delete this._selection;
-    this._frameModel.reset();
-    this._filmStripModel.reset(this._tracingModel);
+  }
+
+  /**
+   * @param {?Timeline.PerformanceModel} model
+   */
+  _setModel(model) {
+    if (this._performanceModel)
+      this._performanceModel.dispose();
+    this._performanceModel = model;
+    this._currentViews.forEach(view => view.setModel(this._performanceModel));
     this._overviewPane.reset();
-    this._currentViews.forEach(view => view.reset());
-    this._overviewPane.reset();
+    if (model) {
+      this._overviewPane.setBounds(
+          model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime());
+    }
+    for (var control of this._overviewControls)
+      control.setModel(model);
+    if (model) {
+      var cpuProfiles = model.timelineModel().cpuProfiles();
+      cpuProfiles.forEach(profile => PerfUI.LineLevelProfile.instance().appendCPUProfile(profile));
+
+      this._setAutoWindowTimes(model.timelineModel());
+      this._setMarkers(model.timelineModel());
+    } else {
+      this.requestWindowTimes(0, Infinity);
+    }
+    this._overviewPane.scheduleUpdate();
     this.select(null);
+    this._updateSearchHighlight(false, true);
   }
 
   /**
@@ -672,29 +657,6 @@
     this._statusPane.updateProgressBar(Common.UIString('Buffer usage'), usage * 100);
   }
 
-  /**
-   * @override
-   * @param {string} title
-   * @param {!SDK.TracingModel} tracingModel
-   * @param {number} timeOffset
-   */
-  addExtensionEvents(title, tracingModel, timeOffset) {
-    this._extensionTracingModels.push({title: title, model: tracingModel, timeOffset: timeOffset});
-    if (this._state !== Timeline.TimelinePanel.State.Idle)
-      return;
-    tracingModel.adjustTime(this._model.minimumRecordTime() + (timeOffset / 1000) - this._recordingStartTime);
-    for (let view of this._currentViews)
-      view.extensionDataAdded();
-  }
-
-  /**
-   * @override
-   * @return {?symbol}
-   */
-  sessionGeneration() {
-    return this._sessionGeneration;
-  }
-
   _showLandingPage() {
     if (this._landingPage) {
       this._landingPage.show(this._statusPaneContainer);
@@ -783,47 +745,32 @@
 
   /**
    * @override
-   * @param {boolean} success
+   * @param {?SDK.TracingModel} tracingModel
+   * @param {?Bindings.TempFileBackingStorage} backingStorage
    */
-  loadingComplete(success) {
-    var loadedFromFile = !!this._loader;
+  loadingComplete(tracingModel, backingStorage) {
     delete this._loader;
     this._setState(Timeline.TimelinePanel.State.Idle);
+    var performanceModel = this._pendingPerformanceModel;
+    this._pendingPerformanceModel = null;
+    this._backingStorage = backingStorage;
 
-    if (!success) {
-      this._statusPane.hide();
-      delete this._statusPane;
-      this._clear();
-      return;
-    }
-
-    if (this._statusPane)
-      this._statusPane.updateStatus(Common.UIString('Processing profile\u2026'));
-    this._model.setEvents(this._tracingModel, loadedFromFile);
-    this._frameModel.reset();
-    this._frameModel.addTraceEvents(
-        SDK.targetManager.mainTarget(), this._model.inspectedTargetEvents(), this._model.sessionId() || '');
-    this._filmStripModel.reset(this._tracingModel);
-    var groups = TimelineModel.TimelineModel.AsyncEventGroup;
-    var asyncEventsByGroup = this._model.mainThreadAsyncEvents();
-    this._irModel.populate(asyncEventsByGroup.get(groups.input), asyncEventsByGroup.get(groups.animation));
-    this._model.cpuProfiles().forEach(profile => PerfUI.LineLevelProfile.instance().appendCPUProfile(profile));
     if (this._statusPane)
       this._statusPane.hide();
     delete this._statusPane;
 
-    for (let entry of this._extensionTracingModels)
-      entry.model.adjustTime(this._model.minimumRecordTime() + (entry.timeOffset / 1000) - this._recordingStartTime);
+    if (!tracingModel) {
+      performanceModel.dispose();
+      this._clear();
+      return;
+    }
+
+    performanceModel.setTracingModel(tracingModel);
+    this._backingStorage = backingStorage;
+    this._setModel(performanceModel);
 
     if (this._flameChart)
       this._flameChart.resizeToPreferredHeights();
-    this._overviewPane.reset();
-    this._overviewPane.setBounds(this._model.minimumRecordTime(), this._model.maximumRecordTime());
-    this._setAutoWindowTimes();
-    this._refreshViews();
-    this._setMarkers();
-    this._overviewPane.scheduleUpdate();
-    this._updateSearchHighlight(false, true);
     if (this._detailsSplitWidget)
       this._detailsSplitWidget.showBoth();
   }
@@ -841,11 +788,14 @@
       this._loader.cancel();
   }
 
-  _setMarkers() {
+  /**
+   * @param {!TimelineModel.TimelineModel} timelineModel
+   */
+  _setMarkers(timelineModel) {
     var markers = new Map();
     var recordTypes = TimelineModel.TimelineModel.RecordType;
-    var zeroTime = this._model.minimumRecordTime();
-    for (var event of this._model.eventDividers()) {
+    var zeroTime = timelineModel.minimumRecordTime();
+    for (var event of timelineModel.eventDividers()) {
       if (event.name === recordTypes.TimeStamp || event.name === recordTypes.ConsoleTime)
         continue;
       markers.set(event.startTime, Timeline.TimelineUIUtils.createEventDivider(event, zeroTime));
@@ -965,7 +915,7 @@
       return;
 
     // FIXME: search on all threads.
-    var events = this._model.mainThreadEvents();
+    var events = this._performanceModel ? this._performanceModel.timelineModel().mainThreadEvents() : [];
     var filters = this._filters.concat([new Timeline.TimelineFilters.RegExp(this._searchRegex)]);
     var matches = [];
     for (var index = events.lowerBound(this._windowStartTime, (time, event) => time - event.startTime);
@@ -1026,7 +976,7 @@
       case Timeline.TimelineSelection.Type.Range:
         return null;
       case Timeline.TimelineSelection.Type.TraceEvent:
-        return this._frameModel.filteredFrames(selection._endTime, selection._endTime)[0];
+        return this._performanceModel.frameModel().filteredFrames(selection._endTime, selection._endTime)[0];
       default:
         console.assert(false, 'Should never be reached');
         return null;
@@ -1040,7 +990,7 @@
     var currentFrame = this._frameForSelection(this._selection);
     if (!currentFrame)
       return;
-    var frames = this._frameModel.frames();
+    var frames = this._performanceModel.frames();
     var index = frames.indexOf(currentFrame);
     console.assert(index >= 0, 'Can\'t find current frame in the frame list');
     index = Number.constrain(index + offset, 0, frames.length - 1);
@@ -1072,7 +1022,7 @@
    * @param {number} time
    */
   selectEntryAtTime(time) {
-    var events = this._model.mainThreadEvents();
+    var events = this._performanceModel ? this._performanceModel.timelineModel().mainThreadEvents() : [];
     // Find best match, then backtrack to the first visible entry.
     for (var index = events.upperBound(time, (time, event) => time - event.startTime) - 1; index >= 0; --index) {
       var event = events[index];
@@ -1130,10 +1080,13 @@
     }
   }
 
-  _setAutoWindowTimes() {
-    var tasks = this._model.mainThreadTasks();
+  /**
+   * @param {!TimelineModel.TimelineModel} timelineModel
+   */
+  _setAutoWindowTimes(timelineModel) {
+    var tasks = timelineModel.mainThreadTasks();
     if (!tasks.length) {
-      this.requestWindowTimes(this._tracingModel.minimumRecordTime(), this._tracingModel.maximumRecordTime());
+      this.requestWindowTimes(timelineModel.minimumRecordTime(), timelineModel.maximumRecordTime());
       return;
     }
     /**
@@ -1165,13 +1118,13 @@
     var leftTime = tasks[leftIndex].startTime;
     var rightTime = tasks[rightIndex].endTime;
     var span = rightTime - leftTime;
-    var totalSpan = this._tracingModel.maximumRecordTime() - this._tracingModel.minimumRecordTime();
+    var totalSpan = timelineModel.maximumRecordTime() - timelineModel.minimumRecordTime();
     if (span < totalSpan * 0.1) {
-      leftTime = this._tracingModel.minimumRecordTime();
-      rightTime = this._tracingModel.maximumRecordTime();
+      leftTime = timelineModel.minimumRecordTime();
+      rightTime = timelineModel.maximumRecordTime();
     } else {
-      leftTime = Math.max(leftTime - 0.05 * span, this._tracingModel.minimumRecordTime());
-      rightTime = Math.min(rightTime + 0.05 * span, this._tracingModel.maximumRecordTime());
+      leftTime = Math.max(leftTime - 0.05 * span, timelineModel.minimumRecordTime());
+      rightTime = Math.min(rightTime + 0.05 * span, timelineModel.maximumRecordTime());
     }
     this.requestWindowTimes(leftTime, rightTime);
   }
@@ -1202,49 +1155,6 @@
 Timeline.TimelinePanel.rowHeight = 18;
 Timeline.TimelinePanel.headerHeight = 20;
 
-/**
- * @interface
- */
-Timeline.LoaderClient = function() {};
-
-Timeline.LoaderClient.prototype = {
-  loadingStarted() {},
-
-  /**
-   * @param {number=} progress
-   */
-  loadingProgress(progress) {},
-
-  /**
-   * @param {boolean} success
-   */
-  loadingComplete(success) {},
-};
-
-/**
- * @interface
- * @extends {Timeline.LoaderClient}
- */
-Timeline.TimelineLifecycleDelegate = function() {};
-
-Timeline.TimelineLifecycleDelegate.prototype = {
-  recordingStarted() {},
-
-  /**
-   * @param {number} usage
-   */
-  recordingProgress(usage) {},
-
-  /**
-   * @param {string} title
-   * @param {!SDK.TracingModel} tracingModel
-   * @param {number} timeOffset
-   */
-  addExtensionEvents(title, tracingModel, timeOffset) {},
-
-  /** @return {?symbol} */
-  sessionGeneration() {}
-};
 
 Timeline.TimelineSelection = class {
   /**
@@ -1348,18 +1258,15 @@
    */
   view() {},
 
-  dispose() {},
-
   /**
    * @return {?Element}
    */
   resizerElement() {},
 
-  reset() {},
-
-  refreshRecords() {},
-
-  extensionDataAdded() {},
+  /**
+   * @param {?Timeline.PerformanceModel} model
+   */
+  setModel(model) {},
 
   /**
    * @param {?SDK.TracingModel.Event} event
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeModeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeModeView.js
index a5c37425..529700b 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeModeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeModeView.js
@@ -18,12 +18,6 @@
 
   /**
    * @override
-   */
-  dispose() {
-  }
-
-  /**
-   * @override
    * @return {?Element}
    */
   resizerElement() {
@@ -45,20 +39,10 @@
 
   /**
    * @override
+   * @param {?Timeline.PerformanceModel} model
    */
-  refreshRecords() {
-  }
-
-  /**
-   * @override
-   */
-  extensionDataAdded() {
-  }
-
-  /**
-   * @override
-   */
-  reset() {
+  setModel(model) {
+    this._treeView.setModel(model);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
index 54b12a7..58125b1 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -8,6 +8,8 @@
 Timeline.TimelineTreeView = class extends UI.VBox {
   constructor() {
     super();
+    /** @type {?Timeline.PerformanceModel} */
+    this._model = null;
     this.element.classList.add('timeline-tree-view');
   }
 
@@ -24,12 +26,25 @@
   }
 
   /**
+   * @param {?Timeline.PerformanceModel} model
+   */
+  setModel(model) {
+    this._model = model;
+  }
+
+  /**
    * @protected
-   * @param {!TimelineModel.TimelineModel} model
+   * @return {?Timeline.PerformanceModel} model
+   */
+  model() {
+    return this._model;
+  }
+
+  /**
+   * @protected
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    */
-  init(model, filters) {
-    this._model = model;
+  init(filters) {
     this._linkifier = new Components.Linkifier();
 
     this._filters = filters.slice();
@@ -116,7 +131,7 @@
    * @return {?Element}
    */
   _linkifyLocation(event) {
-    var target = this._model.targetByEvent(event);
+    var target = this._model.timelineModel().targetByEvent(event);
     if (!target)
       return null;
     var frame = TimelineModel.TimelineProfileTree.eventStackFrame(event);
@@ -151,6 +166,8 @@
   refreshTree() {
     this._linkifier.reset();
     this._dataGrid.rootNode().removeChildren();
+    if (!this._model)
+      return;
     var tree = this._buildTree();
     var children = tree.children();
     var maxSelfTime = 0;
@@ -183,7 +200,8 @@
    */
   buildTopDownTree(doNotAggregate, groupIdCallback) {
     return new TimelineModel.TimelineProfileTree.TopDownRootNode(
-        this._model.mainThreadEvents(), this._filters, this._startTime, this._endTime, doNotAggregate, groupIdCallback);
+        this._model.timelineModel().mainThreadEvents(), this._filters, this._startTime, this._endTime, doNotAggregate,
+        groupIdCallback);
   }
 
   /**
@@ -391,7 +409,7 @@
     var maxTime;
     switch (columnId) {
       case 'startTime':
-        value = this._profileNode.event.startTime - this._treeView._model.minimumRecordTime();
+        value = this._profileNode.event.startTime - this._treeView._model.timelineModel().minimumRecordTime();
         break;
       case 'self':
         value = this._profileNode.selfTime;
@@ -465,14 +483,13 @@
  */
 Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
   /**
-   * @param {!TimelineModel.TimelineModel} model
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    */
-  constructor(model, filters) {
+  constructor(filters) {
     super();
     this._groupBySetting =
         Common.settings.createSetting('timelineTreeGroupBy', Timeline.AggregatedTimelineTreeView.GroupBy.None);
-    this.init(model, filters);
+    this.init(filters);
     var nonessentialEvents = [
       TimelineModel.TimelineModel.RecordType.EventDispatch, TimelineModel.TimelineModel.RecordType.FunctionCall,
       TimelineModel.TimelineModel.RecordType.TimerFire
@@ -510,7 +527,7 @@
   _displayInfoForGroupNode(node) {
     var categories = Timeline.TimelineUIUtils.categories();
     var color = node.id ? Timeline.TimelineUIUtils.eventColor(/** @type {!SDK.TracingModel.Event} */ (node.event)) :
-        categories['other'].color;
+                          categories['other'].color;
 
     switch (this._groupBySetting.get()) {
       case Timeline.AggregatedTimelineTreeView.GroupBy.Category:
@@ -542,7 +559,7 @@
       case Timeline.AggregatedTimelineTreeView.GroupBy.URL:
         break;
       case Timeline.AggregatedTimelineTreeView.GroupBy.Frame:
-        var frame = this._model.pageFrameById(node.id);
+        var frame = this._model.timelineModel().pageFrameById(node.id);
         var frameName = frame ? Timeline.TimelineUIUtils.displayNameForFrame(frame, 80) : Common.UIString('Page');
         return {name: frameName, color: color};
 
@@ -700,7 +717,7 @@
       return;
     if (!node.isGroupNode())
       return;
-    var frame = this._model.pageFrameById(node.id);
+    var frame = this._model.timelineModel().pageFrameById(node.id);
     if (!frame || !frame.ownerNode)
       return;
     contextMenu.appendApplicableItems(frame.ownerNode);
@@ -744,11 +761,10 @@
  */
 Timeline.CallTreeTimelineTreeView = class extends Timeline.AggregatedTimelineTreeView {
   /**
-   * @param {!TimelineModel.TimelineModel} model
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    */
-  constructor(model, filters) {
-    super(model, filters);
+  constructor(filters) {
+    super(filters);
     this._dataGrid.markColumnAsSortedBy('total', DataGrid.DataGrid.Order.Descending);
   }
 
@@ -767,11 +783,10 @@
  */
 Timeline.BottomUpTimelineTreeView = class extends Timeline.AggregatedTimelineTreeView {
   /**
-   * @param {!TimelineModel.TimelineModel} model
    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters
    */
-  constructor(model, filters) {
-    super(model, filters);
+  constructor(filters) {
+    super(filters);
     this._dataGrid.markColumnAsSortedBy('self', DataGrid.DataGrid.Order.Descending);
   }
 
@@ -781,7 +796,7 @@
    */
   _buildTree() {
     return new TimelineModel.TimelineProfileTree.BottomUpTreeRootNode(
-        this._model.mainThreadEvents(), this._filters, this._startTime, this._endTime,
+        this._model.timelineModel().mainThreadEvents(), this._filters, this._startTime, this._endTime,
         this._groupingFunction(this._groupBySetting.get()));
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index 0b260c2a..71df758 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -1535,12 +1535,11 @@
   }
 
   /**
-   * @param {!TimelineModel.TimelineFrameModel} frameModel
    * @param {!TimelineModel.TimelineFrame} frame
    * @param {?SDK.FilmStripModel.Frame} filmStripFrame
    * @return {!Element}
    */
-  static generateDetailsContentForFrame(frameModel, frame, filmStripFrame) {
+  static generateDetailsContentForFrame(frame, filmStripFrame) {
     var contentHelper = new Timeline.TimelineDetailsContentHelper(null, null);
     contentHelper.addSection(Common.UIString('Frame'));
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/module.json b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
index 22aafb5..c707b5b 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/module.json
@@ -142,6 +142,7 @@
     "scripts": [
         "CountersGraph.js",
         "ExtensionTracingSession.js",
+        "PerformanceModel.js",
         "TimelineController.js",
         "TimelineDetailsView.js",
         "TimelineLoader.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
index 3d979b6..588da282 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -450,15 +450,20 @@
 }
 
 .timeline-flamechart-resizer {
-    height: 7px;
+    height: 8px;
     background-color: #f3f3f3;
-    border-top: #a3a3a3 1px solid;
+    border: 1px #a3a3a3;
+    border-style: solid none;
     display: flex;
     flex-direction: row;
     align-items: flex-end;
     justify-content: center;
 }
 
+.timeline-network-resizer-disabled > .timeline-flamechart-resizer {
+    display: none;
+}
+
 .timeline-flamechart-resizer:after {
     content: "...";
     font-size: 14px;
@@ -515,7 +520,7 @@
     overflow: hidden;
 }
 
-.timeline-tree-view > .toolbar {
+.timeline-tree-view .toolbar {
     border-bottom: 1px solid #dadada;
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js b/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
index ee90636..3bca486 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
@@ -738,8 +738,12 @@
     this._resizeStartSizeDIP = 0;
   }
 
-  hideDefaultResizer() {
+  /**
+   * @param {boolean=} noSplitter
+   */
+  hideDefaultResizer(noSplitter) {
     this.uninstallResizer(this._resizerElement);
+    this._sidebarElement.classList.toggle('no-default-splitter', noSplitter);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css b/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css
index e95ae683..9c93d7e 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/splitWidget.css
@@ -78,6 +78,10 @@
     pointer-events: none;
 }
 
+.shadow-split-widget.vbox > .shadow-split-widget-sidebar.no-default-splitter {
+    border: 0 !important;
+}
+
 .shadow-split-widget.vbox > .shadow-split-widget-sidebar:not(.maximized) {
     border: 0;
     border-top: 1px solid rgb(64%, 64%, 64%);
diff --git a/third_party/WebKit/Source/devtools/tests/TestExpectations b/third_party/WebKit/Source/devtools/tests/TestExpectations
index 41944a92..74db37d 100644
--- a/third_party/WebKit/Source/devtools/tests/TestExpectations
+++ b/third_party/WebKit/Source/devtools/tests/TestExpectations
@@ -21,6 +21,15 @@
 inspector/sources/debugger-frameworks/frameworks-with-worker.html [ Skip ]
 inspector/sources/debugger-ui/script-snippet-model.html [ Skip ] # TODO(chenwilliam): extract the worker test
 inspector/tracing/worker-events.html [ Skip ]
+inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.html [ Skip ]
+inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.html [ Skip ]
+inspector-protocol/debugger/debugger-pause-dedicated-worker.html [ Skip ]
+inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.html [ Skip ]
+inspector-protocol/debugger/debugger-step-into-dedicated-worker.html [ Skip ]
+inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.html [ Skip ]
+inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.html [ Skip ]
+inspector-protocol/worker/exception-from-worker-contains-stack.html [ Skip ]
+inspector-protocol/worker/worker-console.html [ Skip ]
 
 # Skipping accessibility tests b/c of protocol change
 # https://crrev.com/3a46cc72d58945804dd4919a679a8ce26690bfc0
@@ -96,3 +105,12 @@
 # Added runtime stats to timeline: http://crbug.com/660428
 inspector/tracing/timeline-js/timeline-runtime-stats.html [ Skip ]
 
+# Page.getLayoutMetrics added after 1.2 protocol
+# https://crrev.com/10f7e12361ee5e1eeb6955f0bc27eb3c182dd412
+inspector-protocol/page/get-layout-metrics.html [ Skip ]
+
+# CSSTracker added after 1.2 protocol
+# https://crrev.com/f8d52df8d16f6521c895fba8f0b8bf957d7eb7f7
+inspector/css_tracker/css-tracker-view.html [ Skip ]
+inspector/css_tracker/decorations-after-inplace-formatter.html [ Skip ]
+inspector/css_tracker/highlight-in-source.html [ Skip ]
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/network/x-frame-options-deny-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/network/x-frame-options-deny-expected.txt
new file mode 100644
index 0000000..36cac1ed
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/network/x-frame-options-deny-expected.txt
@@ -0,0 +1,7 @@
+CONSOLE ERROR: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-deny.cgi' in a frame because it set 'X-Frame-Options' to 'deny'.
+Tests that responseReceived is called on NetworkDispatcher for resource requests denied due to X-Frame-Options header.
+
+
+Received response for x-frame-options-deny.cgi
+SUCCESS
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/persistence/persistence-move-breakpoints-on-reload-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/persistence/persistence-move-breakpoints-on-reload-expected.txt
new file mode 100644
index 0000000..4d4d96e8
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/persistence/persistence-move-breakpoints-on-reload-expected.txt
@@ -0,0 +1,14 @@
+Verify that breakpoints are moved appropriately in case of page reload.
+
+
+Running: addFileSystem
+
+Running: addNetworkFooJS
+
+Running: setBreakpointInFileSystemUISourceCode
+    http://127.0.0.1:8000/inspector/persistence/resources/foo.js:0
+
+Running: reloadPageAndDumpBreakpoints
+Page reloaded.
+    file:///var/www/inspector/persistence/resources/foo.js:0
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/search/sources-search-scope-in-files-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/search/sources-search-scope-in-files-expected.txt
new file mode 100644
index 0000000..1575b301
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/search/sources-search-scope-in-files-expected.txt
@@ -0,0 +1,148 @@
+Tests that ScriptSearchScope performs search across all sources correctly.
+
+See bug 41350.
+Total uiSourceCodes: 13
+
+Running: testIgnoreCase
+Search result #1: uiSourceCode.url = file:///var/www/search.css
+  search match #1: lineNumber = 0, lineContent = 'div.searchTestUniqueString {'
+  search match #2: lineNumber = 4, lineContent = 'div.searchTestUniqueString:hover {'
+  search match #3: lineNumber = 5, lineContent = '    /* another searchTestUniqueString occurence */'
+Search result #2: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+Search result #3: uiSourceCode.url = file:///var/www/search.js
+  search match #1: lineNumber = 0, lineContent = 'function searchTestUniqueString()'
+  search match #2: lineNumber = 3, lineContent = '    // searchTestUniqueString two occurences on the same line searchTestUniqueString'
+  search match #3: lineNumber = 4, lineContent = '    // searchTestUniqueString on the next line.'
+  search match #4: lineNumber = 10, lineContent = '    searchTestUniqueString();'
+  search match #5: lineNumber = 11, lineContent = '    // SEARCHTestUniqueString();'
+
+Running: testCaseSensitive
+Search result #1: uiSourceCode.url = file:///var/www/search.css
+  search match #1: lineNumber = 0, lineContent = 'div.searchTestUniqueString {'
+  search match #2: lineNumber = 4, lineContent = 'div.searchTestUniqueString:hover {'
+  search match #3: lineNumber = 5, lineContent = '    /* another searchTestUniqueString occurence */'
+Search result #2: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+Search result #3: uiSourceCode.url = file:///var/www/search.js
+  search match #1: lineNumber = 0, lineContent = 'function searchTestUniqueString()'
+  search match #2: lineNumber = 3, lineContent = '    // searchTestUniqueString two occurences on the same line searchTestUniqueString'
+  search match #3: lineNumber = 4, lineContent = '    // searchTestUniqueString on the next line.'
+  search match #4: lineNumber = 10, lineContent = '    searchTestUniqueString();'
+
+Running: testFileHTML
+Search result #1: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+
+Running: testFileJS
+Search result #1: uiSourceCode.url = file:///var/www/search.js
+  search match #1: lineNumber = 0, lineContent = 'function searchTestUniqueString()'
+  search match #2: lineNumber = 3, lineContent = '    // searchTestUniqueString two occurences on the same line searchTestUniqueString'
+  search match #3: lineNumber = 4, lineContent = '    // searchTestUniqueString on the next line.'
+  search match #4: lineNumber = 10, lineContent = '    searchTestUniqueString();'
+  search match #5: lineNumber = 11, lineContent = '    // SEARCHTestUniqueString();'
+
+Running: testFileHTMLJS
+
+Running: testSpaceQueries
+Search result #1: uiSourceCode.url = file:///var/www/search.css
+  search match #1: lineNumber = 9, lineContent = '/* searchTestUnique space String */'
+Search result #2: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 14, lineContent = '<!-- searchTestUnique space String -->'
+Search result #3: uiSourceCode.url = file:///var/www/search.js
+  search match #1: lineNumber = 14, lineContent = '// searchTestUnique space String'
+
+Running: testSpaceQueriesFileHTML
+Search result #1: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 14, lineContent = '<!-- searchTestUnique space String -->'
+
+Running: testSpaceQueriesFileHTML_SEARCH
+Search result #1: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 14, lineContent = '<!-- searchTestUnique space String -->'
+
+Running: testSpaceQueriesFileJS_SEARCH_HTML
+
+Running: testSeveralQueriesFileHTML
+Search result #1: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+  search match #5: lineNumber = 14, lineContent = '<!-- searchTestUnique space String -->'
+
+Running: testSeveralQueriesFileHTML_SEARCH
+Search result #1: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+  search match #5: lineNumber = 14, lineContent = '<!-- searchTestUnique space String -->'
+
+Running: testSeveralQueriesFileJS_SEARCH_HTML
+
+Running: testFileSEARCH_NOT_JS_NOT_CSS
+Search result #1: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+
+Running: testSeveralQueriesFileNotCSS
+Search result #1: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+  search match #5: lineNumber = 14, lineContent = '<!-- searchTestUnique space String -->'
+Search result #2: uiSourceCode.url = file:///var/www/search.js
+  search match #1: lineNumber = 0, lineContent = 'function searchTestUniqueString()'
+  search match #2: lineNumber = 3, lineContent = '    // searchTestUniqueString two occurences on the same line searchTestUniqueString'
+  search match #3: lineNumber = 4, lineContent = '    // searchTestUniqueString on the next line.'
+  search match #4: lineNumber = 10, lineContent = '    searchTestUniqueString();'
+  search match #5: lineNumber = 11, lineContent = '    // SEARCHTestUniqueString();'
+  search match #6: lineNumber = 14, lineContent = '// searchTestUnique space String'
+
+Running: testFileQueryWithProjectName
+Running a file query with existing project name first:
+Search result #1: uiSourceCode.url = file:///var/www/search.css
+  search match #1: lineNumber = 0, lineContent = 'div.searchTestUniqueString {'
+  search match #2: lineNumber = 4, lineContent = 'div.searchTestUniqueString:hover {'
+  search match #3: lineNumber = 5, lineContent = '    /* another searchTestUniqueString occurence */'
+  search match #4: lineNumber = 9, lineContent = '/* searchTestUnique space String */'
+Search result #2: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+  search match #5: lineNumber = 14, lineContent = '<!-- searchTestUnique space String -->'
+Search result #3: uiSourceCode.url = file:///var/www/search.js
+  search match #1: lineNumber = 0, lineContent = 'function searchTestUniqueString()'
+  search match #2: lineNumber = 3, lineContent = '    // searchTestUniqueString two occurences on the same line searchTestUniqueString'
+  search match #3: lineNumber = 4, lineContent = '    // searchTestUniqueString on the next line.'
+  search match #4: lineNumber = 10, lineContent = '    searchTestUniqueString();'
+  search match #5: lineNumber = 11, lineContent = '    // SEARCHTestUniqueString();'
+  search match #6: lineNumber = 14, lineContent = '// searchTestUnique space String'
+Running a file query with non-existing project name now:
+
+Running: testDirtyFiles
+Search result #1: uiSourceCode.url = file:///var/www/search.css
+  search match #1: lineNumber = 0, lineContent = 'div.searchTestUniqueString {'
+  search match #2: lineNumber = 4, lineContent = 'div.searchTestUniqueString:hover {'
+  search match #3: lineNumber = 5, lineContent = '    /* another searchTestUniqueString occurence */'
+Search result #2: uiSourceCode.url = file:///var/www/search.html
+  search match #1: lineNumber = 4, lineContent = '<script>window.eval("function searchTestUniqueString() {}");</script>'
+  search match #2: lineNumber = 6, lineContent = '<div>searchTestUniqueString</div>'
+  search match #3: lineNumber = 8, lineContent = '<!-- searchTestUniqueString -->'
+  search match #4: lineNumber = 10, lineContent = '<div id="searchTestUniqueString">div text</div>'
+Search result #3: uiSourceCode.url = file:///var/www/search.js
+  search match #1: lineNumber = 0, lineContent = 'FOO searchTestUniqueString BAR'
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/sources/debugger/async-callstack-network-initiator-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/sources/debugger/async-callstack-network-initiator-expected.txt
new file mode 100644
index 0000000..4cb1eda8
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/sources/debugger/async-callstack-network-initiator-expected.txt
@@ -0,0 +1,19 @@
+CONSOLE MESSAGE: line 11: console.clear
+Tests asynchronous call stacks printed in console for a Network.Initiator.
+
+Set timer for test function.
+async-callstack-network-initiator.html:11 Console was cleared
+async-callstack-network-initiator.html:29 POST http://127.0.0.1:8000/failure/foo 404 (Not Found)
+
+sendXHR @ async-callstack-network-initiator.html:29
+
+timeout2 @ async-callstack-network-initiator.html:22
+
+setTimeout (async)
+
+timeout1 @ async-callstack-network-initiator.html:17
+
+setTimeout (async)
+
+testFunction @ async-callstack-network-initiator.html:12
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/sources/ui-source-code-metadata-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/sources/ui-source-code-metadata-expected.txt
new file mode 100644
index 0000000..16795c6
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/http/tests/inspector/sources/ui-source-code-metadata-expected.txt
@@ -0,0 +1,18 @@
+CONSOLE MESSAGE: line 1: Script loaded.
+Verify that network UISourceCode has metadata.
+
+
+Running: testCachedResource
+Metadata for UISourceCode: http://127.0.0.1:8000/inspector/sources/resources/style.css
+    Metadata is EMPTY
+
+Running: testDynamicResource
+Metadata for UISourceCode: http://127.0.0.1:8000/inspector/sources/resources/script.js
+    content size: 31
+    modification time: <Date>
+
+Running: testInlinedSourceMapSource
+Metadata for UISourceCode: http://127.0.0.1:8000/inspector/sources/resources/style.scss
+    content size: 26
+    modification time: null
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector-protocol/layout-fonts/generic-system-ui-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector-protocol/layout-fonts/generic-system-ui-expected.txt
new file mode 100644
index 0000000..7b35296d0
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector-protocol/layout-fonts/generic-system-ui-expected.txt
@@ -0,0 +1,9 @@
+This text should use the system font.
+#system-ui:
+"Times New Roman" : 37
+
+This text should use the system font.
+#system-ui-20pt:
+"Times New Roman" : 37
+
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector-protocol/runtime/runtime-await-promise-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector-protocol/runtime/runtime-await-promise-expected.txt
new file mode 100644
index 0000000..a91057e6
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector-protocol/runtime/runtime-await-promise-expected.txt
@@ -0,0 +1,104 @@
+Tests that Runtime.awaitPromise works.
+
+Running test: testResolvedPromise
+{
+    result : {
+        description : 239
+        type : number
+        value : 239
+    }
+}
+
+Running test: testRejectedPromise
+{
+    exceptionDetails : {
+        columnNumber : 0
+        exception : {
+            objectId : 0
+            type : object
+            value : {
+                a : 1
+            }
+        }
+        exceptionId : 0
+        lineNumber : 0
+        stackTrace : {
+            callFrames : [
+            ]
+        }
+        text : Uncaught (in promise)
+    }
+    result : {
+        type : object
+        value : {
+            a : 1
+        }
+    }
+}
+
+Running test: testRejectedPromiseWithStack
+{
+    exceptionDetails : {
+        columnNumber : 0
+        exception : {
+            description : 239
+            objectId : 0
+            type : number
+            value : 239
+        }
+        exceptionId : 0
+        lineNumber : 0
+        stackTrace : {
+            callFrames : [
+            ]
+            parent : {
+                callFrames : [
+                    [0] : {
+                        columnNumber : 4
+                        functionName : rejectPromise
+                        lineNumber : 21
+                        scriptId : 0
+                        url : 
+                    }
+                    [1] : {
+                        columnNumber : 0
+                        functionName : 
+                        lineNumber : 0
+                        scriptId : 0
+                        url : 
+                    }
+                ]
+                description : Promise.reject
+            }
+        }
+        text : Uncaught (in promise)
+    }
+    result : {
+        description : 239
+        type : number
+        value : 239
+    }
+}
+
+Running test: testPendingPromise
+{
+    result : {
+        description : 239
+        type : number
+        value : 239
+    }
+}
+
+Running test: testResolvedWithoutArgsPromise
+{
+    result : {
+        type : undefined
+    }
+}
+
+Running test: testGarbageCollectedPromise
+{
+    code : -32000
+    message : Promise was collected
+}
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-edit-property-value-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-edit-property-value-expected.txt
index 73e66a1..cdca0ec 100644
--- a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-edit-property-value-expected.txt
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-edit-property-value-expected.txt
@@ -5,7 +5,7 @@
 Node was hidden after dblclick: true
 Node was hidden after dblclick: true
 logToConsole()
-console-edit-property-value.html:10 Object
+console-edit-property-value.html:10 Object {a: 1, b: "foo", c: null}
     a: 3
     b: "foo"
     c: Array[3]
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-es6-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-es6-expected.txt
index dbbb33e..9e50d2e 100644
--- a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-es6-expected.txt
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-es6-expected.txt
@@ -79,183 +79,183 @@
 globals[12]
 Map {" from str " => " to str ", undefined => undefined, null => null, 42 => 42, Object {foo: "from"} => Object {foo: "to"}…}
 Expanded all messages
-console-format-es6.html:11 Promise
+console-format-es6.html:11 Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: -0}
     __proto__: Promise
     [[PromiseStatus]]: "rejected"
     [[PromiseValue]]: -0
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Promise]
     0: Promise
     length: 1
     __proto__: Array[0]
 globals[0]
-Promise
+Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: -0}
     __proto__: Promise
     [[PromiseStatus]]: "rejected"
     [[PromiseValue]]: -0
 console-format-es6.html:11 Symbol()
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Symbol()]
     0: Symbol()
     length: 1
     __proto__: Array[0]
 globals[1]
 Symbol()
 console-format-es6.html:11 Symbol(a)
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Symbol(a)]
     0: Symbol(a)
     length: 1
     __proto__: Array[0]
 globals[2]
 Symbol(a)
-console-format-es6.html:11 Object
+console-format-es6.html:11 Object {a: Symbol(), Symbol(a): 2}
     a: Symbol()
     getter: (...)
     Symbol(a): 2
     get getter: function getter()
     __proto__: Object
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Object]
     0: Object
     length: 1
     __proto__: Array[0]
 globals[3]
-Object
+Object {a: Symbol(), Symbol(a): 2}
     a: Symbol()
     getter: (...)
     Symbol(a): 2
     get getter: function getter()
     __proto__: Object
-console-format-es6.html:11 Map
+console-format-es6.html:11 Map {Object {a: Symbol(), Symbol(a): 2} => Object {foo: 1}}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[1]
         0: {Object => Object}
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Map]
     0: Map
     length: 1
     __proto__: Array[0]
 globals[4]
-Map
+Map {Object {a: Symbol(), Symbol(a): 2} => Object {foo: 1}}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[1]
         0: {Object => Object}
         length: 1
-console-format-es6.html:11 WeakMap
+console-format-es6.html:11 WeakMap {Object {a: Symbol(), Symbol(a): 2} => Object {foo: 1}}
     __proto__: WeakMap
     [[Entries]]: Array[1]
         0: {Object => Object}
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [WeakMap]
     0: WeakMap
     length: 1
     __proto__: Array[0]
 globals[5]
-WeakMap
+WeakMap {Object {a: Symbol(), Symbol(a): 2} => Object {foo: 1}}
     __proto__: WeakMap
     [[Entries]]: Array[1]
         0: {Object => Object}
         length: 1
-console-format-es6.html:11 Set
+console-format-es6.html:11 Set {Object {a: Symbol(), Symbol(a): 2}}
     size: (...)
     __proto__: Set
     [[Entries]]: Array[1]
         0: Object
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Set]
     0: Set
     length: 1
     __proto__: Array[0]
 globals[6]
-Set
+Set {Object {a: Symbol(), Symbol(a): 2}}
     size: (...)
     __proto__: Set
     [[Entries]]: Array[1]
         0: Object
         length: 1
-console-format-es6.html:11 WeakSet
+console-format-es6.html:11 WeakSet {Object {a: Symbol(), Symbol(a): 2}}
     __proto__: WeakSet
     [[Entries]]: Array[1]
         0: Object
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [WeakSet]
     0: WeakSet
     length: 1
     __proto__: Array[0]
 globals[7]
-WeakSet
+WeakSet {Object {a: Symbol(), Symbol(a): 2}}
     __proto__: WeakSet
     [[Entries]]: Array[1]
         0: Object
         length: 1
-console-format-es6.html:11 Map
+console-format-es6.html:11 Map {Map {} => WeakMap {}}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[1]
         0: {Map => WeakMap}
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Map]
     0: Map
     length: 1
     __proto__: Array[0]
 globals[8]
-Map
+Map {Map {} => WeakMap {}}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[1]
         0: {Map => WeakMap}
         length: 1
-console-format-es6.html:11 Map
+console-format-es6.html:11 Map {Map {…} => WeakMap {…}}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[1]
         0: {Map => WeakMap}
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Map]
     0: Map
     length: 1
     __proto__: Array[0]
 globals[9]
-Map
+Map {Map {…} => WeakMap {…}}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[1]
         0: {Map => WeakMap}
         length: 1
-console-format-es6.html:11 Set
+console-format-es6.html:11 Set {WeakSet {}}
     size: (...)
     __proto__: Set
     [[Entries]]: Array[1]
         0: WeakSet
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Set]
     0: Set
     length: 1
     __proto__: Array[0]
 globals[10]
-Set
+Set {WeakSet {}}
     size: (...)
     __proto__: Set
     [[Entries]]: Array[1]
         0: WeakSet
         length: 1
-console-format-es6.html:11 Set
+console-format-es6.html:11 Set {WeakSet {…}}
     size: (...)
     __proto__: Set
     [[Entries]]: Array[1]
         0: WeakSet
         length: 1
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Set]
     0: Set
     length: 1
     __proto__: Array[0]
 globals[11]
-Set
+Set {WeakSet {…}}
     size: (...)
     __proto__: Set
     [[Entries]]: Array[1]
         0: WeakSet
         length: 1
-console-format-es6.html:11 Map
+console-format-es6.html:11 Map {" from str " => " to str ", undefined => undefined, null => null, 42 => 42, Object {foo: "from"} => Object {foo: "to"}…}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[6]
@@ -266,12 +266,12 @@
         4: {Object => Object}
         5: {Array[1] => Array[1]}
         length: 6
-console-format-es6.html:12 Array[1]
+console-format-es6.html:12 [Map]
     0: Map
     length: 1
     __proto__: Array[0]
 globals[12]
-Map
+Map {" from str " => " to str ", undefined => undefined, null => null, 42 => 42, Object {foo: "from"} => Object {foo: "to"}…}
     size: (...)
     __proto__: Map
     [[Entries]]: Array[6]
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-expected.txt
index efbc763..ef46f51 100644
--- a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-expected.txt
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-format-expected.txt
@@ -333,42 +333,44 @@
 console-format.html:30 %%% self-escape5 dummy
 console-format.html:31 %dummy self-escape6
 console-format.html:7 /^url\(\s*(?:(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\.))*"|'(?:[^\\\']|(?:\\[\da-f]{1,6}\s?|\.))*')|(?:[!#$%&*-~\w]|(?:\\[\da-f]{1,6}\s?|\.))*)\s*\)/i
-console-format.html:8 Array[1]
+console-format.html:8 [/^url\(\s*(?:(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\…?:[!#$%&*-~\w]|(?:\\[\da-f]{1,6}\s?|\.))*)\s*\)/i]
     0: /^url\(\s*(?:(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\.))*"|'(?:[^\\\']|(?:\\[\da-f]{1,6}\s?|\.))*')|(?:[!#$%&*-~\w]|(?:\\[\da-f]{1,6}\s?|\.))*)\s*\)/i
     length: 1
     __proto__: Array[0]
 globals[0]
 /^url\(\s*(?:(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\.))*"|'(?:[^\\\']|(?:\\[\da-f]{1,6}\s?|\.))*')|(?:[!#$%&*-~\w]|(?:\\[\da-f]{1,6}\s?|\.))*)\s*\)/i
 console-format.html:7 /foo\\bar\sbaz/i
-console-format.html:8 Array[1]
+console-format.html:8 [/foo\\bar\sbaz/i]
     0: /foo\\bar\sbaz/i
     length: 1
     __proto__: Array[0]
 globals[1]
 /foo\\bar\sbaz/i
 console-format.html:7 test
-console-format.html:8 Array[1]
+console-format.html:8 ["test"]
     0: "test"
     length: 1
     __proto__: Array[0]
 globals[2]
 "test"
 console-format.html:7 test named "test"
-console-format.html:8 Array[1]
+console-format.html:8 ["test named "test""]
     0: "test named "test""
     length: 1
     __proto__: Array[0]
 globals[3]
 "test named "test""
 console-format.html:7 Error
-console-format.html:8 Array[1]
+console-format.html:8 [Error
+]
     0: Error
     length: 1
     __proto__: Array[0]
 globals[4]
 Error
 console-format.html:7 Error: my error message
-console-format.html:8 Array[1]
+console-format.html:8 [Error: my error message
+]
     0: Error: my error message
     length: 1
     __proto__: Array[0]
@@ -376,7 +378,9 @@
 Error: my error message
 console-format.html:7 Error: my multiline
 error message
-console-format.html:8 Array[1]
+console-format.html:8 [Error: my multiline
+error message
+]
     0: Error: my multiline
 error message
     length: 1
@@ -386,14 +390,14 @@
 error message
 console-format.html:7 
     <p id="p">Tests that console logging dumps proper messages.</p>
-console-format.html:8 Array[1]
+console-format.html:8 [p#p]
     0: p#p
     length: 1
     __proto__: Array[0]
 globals[7]
     <p id="p">Tests that console logging dumps proper messages.</p>
 console-format.html:7 function () { return 1; }
-console-format.html:8 Array[1]
+console-format.html:8 [function]
     0: function ()
     length: 1
     __proto__: Array[0]
@@ -402,7 +406,7 @@
 console-format.html:7 function () {
         return 2;
     }
-console-format.html:8 Array[1]
+console-format.html:8 [function]
     0: function ()
     length: 1
     __proto__: Array[0]
@@ -411,28 +415,28 @@
         return 2;
     }
 console-format.html:7 0.12
-console-format.html:8 Array[1]
+console-format.html:8 [0.12]
     0: 0.12
     length: 1
     __proto__: Array[0]
 globals[10]
 0.12
 console-format.html:7 http://webkit.org/
-console-format.html:8 Array[1]
+console-format.html:8 ["http://webkit.org/"]
     0: "http://webkit.org/"
     length: 1
     __proto__: Array[0]
 globals[11]
 "http://webkit.org/"
 console-format.html:7 null
-console-format.html:8 Array[1]
+console-format.html:8 [null]
     0: null
     length: 1
     __proto__: Array[0]
 globals[12]
 null
 console-format.html:7 undefined
-console-format.html:8 Array[1]
+console-format.html:8 [undefined]
     0: undefined
     length: 1
     __proto__: Array[0]
@@ -440,7 +444,7 @@
 undefined
 console-format.html:7 
     attr=""
-console-format.html:8 Array[1]
+console-format.html:8 [attr]
     0: attr
     length: 1
     __proto__: Array[0]
@@ -448,7 +452,7 @@
     attr=""
 console-format.html:7 
     attr="value"
-console-format.html:8 Array[1]
+console-format.html:8 [attr]
     0: attr
     length: 1
     __proto__: Array[0]
@@ -456,107 +460,107 @@
     attr="value"
 console-format.html:7 
     id="x"
-console-format.html:8 Array[1]
+console-format.html:8 [id]
     0: id
     length: 1
     __proto__: Array[0]
 globals[16]
     id="x"
-console-format.html:7 Object
+console-format.html:7 Object {}
     length: (...)
     get length: function length()
     __proto__: Object
-console-format.html:8 Array[1]
+console-format.html:8 [Object]
     0: Object
     length: 1
     __proto__: Array[0]
 globals[17]
-Object
+Object {}
     length: (...)
     get length: function length()
     __proto__: Object
 console-format.html:7 NaN
-console-format.html:8 Array[1]
+console-format.html:8 [NaN]
     0: NaN
     length: 1
     __proto__: Array[0]
 globals[18]
 NaN
 console-format.html:7 Infinity
-console-format.html:8 Array[1]
+console-format.html:8 [Infinity]
     0: Infinity
     length: 1
     __proto__: Array[0]
 globals[19]
 Infinity
 console-format.html:7 -Infinity
-console-format.html:8 Array[1]
+console-format.html:8 [-Infinity]
     0: -Infinity
     length: 1
     __proto__: Array[0]
 globals[20]
 -Infinity
-console-format.html:7 Array[10]
+console-format.html:7 ["test", "test2", undefined × 2, "test4", undefined × 5, foo: Object]
     0: "test"
     1: "test2"
     4: "test4"
     foo: Object
     length: 10
     __proto__: Array[0]
-console-format.html:8 Array[1]
+console-format.html:8 [Array[10]]
     0: Array[10]
     length: 1
     __proto__: Array[0]
 globals[21]
-Array[10]
+["test", "test2", undefined × 2, "test4", undefined × 5, foo: Object]
     0: "test"
     1: "test2"
     4: "test4"
     foo: Object
     length: 10
     __proto__: Array[0]
-console-format.html:7 Object
+console-format.html:7 Object {}
     __proto__: Object
-console-format.html:8 Array[1]
+console-format.html:8 [Object]
     0: Object
     length: 1
     __proto__: Array[0]
 globals[22]
-Object
+Object {}
     __proto__: Object
-console-format.html:7 Array[1]
+console-format.html:7 [function]
     0: function ()
     length: 1
     __proto__: Array[0]
-console-format.html:8 Array[1]
+console-format.html:8 [Array[1]]
     0: Array[1]
     length: 1
     __proto__: Array[0]
 globals[23]
-Array[1]
+[function]
     0: function ()
     length: 1
     __proto__: Array[0]
-console-format.html:7 Object
+console-format.html:7 Object {bar: "bar"}
     bar: "bar"
     __proto__: Object
-console-format.html:8 Array[1]
+console-format.html:8 [Object]
     0: Object
     length: 1
     __proto__: Array[0]
 globals[24]
-Object
+Object {bar: "bar"}
     bar: "bar"
     __proto__: Object
 console-format.html:7 
     <svg id="svg-node"></svg>
-console-format.html:8 Array[1]
+console-format.html:8 [svg#svg-node]
     0: svg#svg-node
     length: 1
     __proto__: Array[0]
 globals[25]
     <svg id="svg-node"></svg>
-console-format.html:7 Object
+console-format.html:7 Object {enumerableProp: 4, __underscoreEnumerableProp__: 5, __underscoreNonEnumerableProp: 2, abc: 3}
     enumerableProp: 4
     __underscoreEnumerableProp__: 5
     abc: 3
@@ -566,12 +570,12 @@
     get bar: function ()
     set bar: function (x)
     __proto__: Object
-console-format.html:8 Array[1]
+console-format.html:8 [Object]
     0: Object
     length: 1
     __proto__: Array[0]
 globals[26]
-Object
+Object {enumerableProp: 4, __underscoreEnumerableProp__: 5, __underscoreNonEnumerableProp: 2, abc: 3}
     enumerableProp: 4
     __underscoreEnumerableProp__: 5
     abc: 3
@@ -582,29 +586,29 @@
     set bar: function (x)
     __proto__: Object
 console-format.html:7 -0
-console-format.html:8 Array[1]
+console-format.html:8 [-0]
     0: -0
     length: 1
     __proto__: Array[0]
 globals[27]
 -0
-console-format.html:7 Object
+console-format.html:7 Object {}
     No Properties
-console-format.html:8 Array[1]
+console-format.html:8 [Object]
     0: Object
     length: 1
     __proto__: Array[0]
 globals[28]
-Object
+Object {}
     No Properties
 console-format.html:7 function Object() { [native code] }
-console-format.html:8 Array[1]
+console-format.html:8 [function]
     0: function Object()
     length: 1
     __proto__: Array[0]
 globals[29]
 function Object() { [native code] }
-console-format.html:7 Object
+console-format.html:7 Object {}
     constructor: function Object()
     hasOwnProperty: function hasOwnProperty()
     isPrototypeOf: function isPrototypeOf()
@@ -618,12 +622,12 @@
     __lookupSetter__: function __lookupSetter__()
     get __proto__: function __proto__()
     set __proto__: function __proto__()
-console-format.html:8 Array[1]
+console-format.html:8 [Object]
     0: Object
     length: 1
     __proto__: Array[0]
 globals[30]
-Object
+Object {}
     constructor: function Object()
     hasOwnProperty: function hasOwnProperty()
     isPrototypeOf: function isPrototypeOf()
@@ -639,44 +643,44 @@
     set __proto__: function __proto__()
 console-format.html:7 function ( /**/ foo/**/, /*/**/bar,
     /**/baz) {}
-console-format.html:8 Array[1]
+console-format.html:8 [function]
     0: function ( /**/ foo/**/, /*/**/bar,     /**/baz)
     length: 1
     __proto__: Array[0]
 globals[31]
 function ( /**/ foo/**/, /*/**/bar,
     /**/baz) {}
-console-format.html:7 Number
+console-format.html:7 Number {[[PrimitiveValue]]: 42}
     __proto__: Number
     [[PrimitiveValue]]: 42
-console-format.html:8 Array[1]
+console-format.html:8 [Number]
     0: Number
     length: 1
     __proto__: Array[0]
 globals[32]
-Number
+Number {[[PrimitiveValue]]: 42}
     __proto__: Number
     [[PrimitiveValue]]: 42
-console-format.html:7 String
+console-format.html:7 String {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
     0: "a"
     1: "b"
     2: "c"
     length: 3
     __proto__: String
     [[PrimitiveValue]]: "abc"
-console-format.html:8 Array[1]
+console-format.html:8 [String]
     0: String
     length: 1
     __proto__: Array[0]
 globals[33]
-String
+String {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
     0: "a"
     1: "b"
     2: "c"
     length: 3
     __proto__: String
     [[PrimitiveValue]]: "abc"
-console-format.html:7 Uint16Array[3]
+console-format.html:7 Uint16Array[3] [1, 2, 3]
     0: 1
     1: 2
     2: 3
@@ -686,12 +690,12 @@
     length: (...)
     Symbol(Symbol.toStringTag): (...)
     __proto__: TypedArray
-console-format.html:8 Array[1]
+console-format.html:8 [Uint16Array[3]]
     0: Uint16Array[3]
     length: 1
     __proto__: Array[0]
 globals[34]
-Uint16Array[3]
+Uint16Array[3] [1, 2, 3]
     0: 1
     1: 2
     2: 3
@@ -702,20 +706,20 @@
     Symbol(Symbol.toStringTag): (...)
     __proto__: TypedArray
 console-format.html:7 #text
-console-format.html:8 Array[1]
+console-format.html:8 [text]
     0: text
     length: 1
     __proto__: Array[0]
 globals[35]
 #text
 console-format.html:7 DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
-console-format.html:8 Array[1]
+console-format.html:8 [DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of th…]
     0: DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
     length: 1
     __proto__: Array[0]
 globals[36]
 DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
-console-format.html:7 Uint8Array[1]
+console-format.html:7 Uint8Array[1] [3]
     0: 3
     buffer: (...)
     byteLength: (...)
@@ -723,12 +727,12 @@
     length: (...)
     Symbol(Symbol.toStringTag): (...)
     __proto__: TypedArray
-console-format.html:8 Array[1]
+console-format.html:8 [Uint8Array[1]]
     0: Uint8Array[1]
     length: 1
     __proto__: Array[0]
 globals[37]
-Uint8Array[1]
+Uint8Array[1] [3]
     0: 3
     buffer: (...)
     byteLength: (...)
@@ -736,76 +740,76 @@
     length: (...)
     Symbol(Symbol.toStringTag): (...)
     __proto__: TypedArray
-console-format.html:7 Uint8Array[400]
+console-format.html:7 Uint8Array[400] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…]
     [0 … 99]
     [100 … 199]
     [200 … 299]
     [300 … 399]
     foo: "bar"
     __proto__: TypedArray
-console-format.html:8 Array[1]
+console-format.html:8 [Uint8Array[400]]
     0: Uint8Array[400]
     length: 1
     __proto__: Array[0]
 globals[38]
-Uint8Array[400]
+Uint8Array[400] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…]
     [0 … 99]
     [100 … 199]
     [200 … 299]
     [300 … 399]
     foo: "bar"
     __proto__: TypedArray
-console-format.html:7 Uint8Array[400000000]
+console-format.html:7 Uint8Array[400000000] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…]
     [0 … 99999999]
     [100000000 … 199999999]
     [200000000 … 299999999]
     [300000000 … 399999999]
     __proto__: TypedArray
-console-format.html:8 Array[1]
+console-format.html:8 [Uint8Array[400000000]]
     0: Uint8Array[400000000]
     length: 1
     __proto__: Array[0]
 globals[39]
-Uint8Array[400000000]
+Uint8Array[400000000] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…]
     [0 … 99999999]
     [100000000 … 199999999]
     [200000000 … 299999999]
     [300000000 … 399999999]
     __proto__: TypedArray
-console-format.html:7 namespace.longSubNamespace.x.className
+console-format.html:7 namespace.longSubNamespace.x.className {}
     __proto__: Object
-console-format.html:8 Array[1]
+console-format.html:8 [n…e.l…e.x.className]
     0: namespace.longSubNamespace.x.className
     length: 1
     __proto__: Array[0]
 globals[40]
-namespace.longSubNamespace.x.className
+namespace.longSubNamespace.x.className {}
     __proto__: Object
-console-format.html:7 Array[200]
+console-format.html:7 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…]
     [0 … 99]
     [100 … 199]
     length: 200
     __proto__: Array[0]
-console-format.html:8 Array[1]
+console-format.html:8 [Array[200]]
     0: Array[200]
     length: 1
     __proto__: Array[0]
 globals[41]
-Array[200]
+[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…]
     [0 … 99]
     [100 … 199]
     length: 200
     __proto__: Array[0]
-console-format.html:7 Array[1]
+console-format.html:7 ["test"]
     0: "test"
     length: 1
     __proto__: Array[0]
-console-format.html:8 Array[1]
+console-format.html:8 [Array[1]]
     0: Array[1]
     length: 1
     __proto__: Array[0]
 globals[42]
-Array[1]
+["test"]
     0: "test"
     length: 1
     __proto__: Array[0]
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-log-object-with-getter-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-log-object-with-getter-expected.txt
index e5bc3b6..f6126da 100644
--- a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-log-object-with-getter-expected.txt
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-log-object-with-getter-expected.txt
@@ -6,7 +6,7 @@
 console-log-object-with-getter.html:25 Object {}
 console-log-object-with-getter.html:26 [undefined × 2]
 console-log-object-with-getter.html:27 Object {}
-console-log-object-with-getter.html:25 Objectfoo: Objecta: 1b: 2__proto__: Objectget foo: function ()set bar: function (x)__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > parent expanded > name > object-properties-section-separator > object-value-object value > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
-console-log-object-with-getter.html:26 Array[2]0: 1length: 2get 0: function ()set 1: function (x)__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
-console-log-object-with-getter.html:27 Objecterror: [Exception: Error: myError]function: [Exception: function ()]number: [Exception: 123]string: [Exception: "myString"]get error: function error()get function: function function()get number: function number()get string: function string()__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > name > object-properties-section-separator > error value > object-value-error > children > name > object-properties-section-separator > error value > object-value-function > object-value-function-prefix > children > name > object-properties-section-separator > error value > object-value-number > children > name > object-properties-section-separator > error value > object-value-string > object-value-string-quote > object-value-string-quote > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-log-object-with-getter.html:25 Object {}foo: Objecta: 1b: 2__proto__: Objectget foo: function ()set bar: function (x)__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-state-note info-note > children expanded > parent expanded > name > object-properties-section-separator > object-value-object value > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-log-object-with-getter.html:26 [undefined × 2]0: 1length: 2get 0: function ()set 1: function (x)__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-undefined > object-state-note info-note > children expanded > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-log-object-with-getter.html:27 Object {}error: [Exception: Error: myError]function: [Exception: function ()]number: [Exception: 123]string: [Exception: "myString"]get error: function error()get function: function function()get number: function number()get string: function string()__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-state-note info-note > children expanded > name > object-properties-section-separator > error value > object-value-error > children > name > object-properties-section-separator > error value > object-value-function > object-value-function-prefix > children > name > object-properties-section-separator > error value > object-value-number > children > name > object-properties-section-separator > error value > object-value-string > object-value-string-quote > object-value-string-quote > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-function value > object-value-function-prefix > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-object-preview-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-object-preview-expected.txt
index 9e284be..4ca81af 100644
--- a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-object-preview-expected.txt
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/console/console-object-preview-expected.txt
@@ -32,66 +32,66 @@
 Tests that console produces instant previews for arrays and objects.
 
 console-object-preview.html:9 Mutating object in a loop console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:13 Object {a: 0, b: 0, c: 0} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > children
-console-object-preview.html:13 Object {a: 0, b: 0, c: 1} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > children
-console-object-preview.html:13 Object {a: 0, b: 0, c: 2} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > children
+console-object-preview.html:13 Object {a: 0, b: 0, c: 0} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
+console-object-preview.html:13 Object {a: 0, b: 0, c: 1} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
+console-object-preview.html:13 Object {a: 0, b: 0, c: 2} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
 console-object-preview.html:16 Mutating array in a loop console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:20 [0, 0, 0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > children
-console-object-preview.html:20 [0, 0, 1] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > children
-console-object-preview.html:20 [0, 0, 2] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > children
+console-object-preview.html:20 [0, 0, 0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-state-note info-note > children
+console-object-preview.html:20 [0, 0, 1] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-state-note info-note > children
+console-object-preview.html:20 [0, 0, 2] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-state-note info-note > children
 console-object-preview.html:23 Object with many properties console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:28 Object {property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > children
+console-object-preview.html:28 Object {property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
 console-object-preview.html:30 Array with many properties console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:35 [0, 1, property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > children
+console-object-preview.html:35 [0, 1, property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
 console-object-preview.html:37 Array with gaps and overflow console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:42 [32: 0, 89: 1, 146: 2, 203: 3, 260: 4, 317: 5, 374: 6, 431: 7, 488: 8, 545: 9, 602: 10, 659: 11, 716: 12, 773: 13, 830: 14, 887: 15, 944: 16, 1001: 17, 1058: 18, 1115: 19, 1172: 20, 1229: 21, 1286: 22, 1343: 23, 1400: 24, 1457: 25, 1514: 26, 1571: 27, 1628: 28, 1685: 29, 1742: 30, 1799: 31, 1856: 32, 1913: 33, 1970: 34, 2027: 35, 2084: 36, 2141: 37, 2198: 38, 2255: 39, 2312: 40, 2369: 41, 2426: 42, 2483: 43, 2540: 44, 2597: 45, 2654: 46, 2711: 47, 2768: 48, 2825: 49, 2882: 50, 2939: 51, 2996: 52, 3053: 53, 3110: 54, 3167: 55, 3224: 56, 3281: 57, 3338: 58, 3395: 59, 3452: 60, 3509: 61, 3566: 62, 3623: 63, 3680: 64, 3737: 65, 3794: 66, 3851: 67, 3908: 68, 3965: 69, 4022: 70, 4079: 71, 4136: 72, 4193: 73, 4250: 74, 4307: 75, 4364: 76, 4421: 77, 4478: 78, 4535: 79, 4592: 80, 4649: 81, 4706: 82, 4763: 83, 4820: 84, 4877: 85, 4934: 86, 4991: 87, 5048: 88, 5105: 89, 5162: 90, 5219: 91, 5276: 92, 5333: 93, 5390: 94, 5447: 95, 5504: 96, 5561: 97, 5618: 98, 5675: 99…] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > children
+console-object-preview.html:42 [32: 0, 89: 1, 146: 2, 203: 3, 260: 4, 317: 5, 374: 6, 431: 7, 488: 8, 545: 9, 602: 10, 659: 11, 716: 12, 773: 13, 830: 14, 887: 15, 944: 16, 1001: 17, 1058: 18, 1115: 19, 1172: 20, 1229: 21, 1286: 22, 1343: 23, 1400: 24, 1457: 25, 1514: 26, 1571: 27, 1628: 28, 1685: 29, 1742: 30, 1799: 31, 1856: 32, 1913: 33, 1970: 34, 2027: 35, 2084: 36, 2141: 37, 2198: 38, 2255: 39, 2312: 40, 2369: 41, 2426: 42, 2483: 43, 2540: 44, 2597: 45, 2654: 46, 2711: 47, 2768: 48, 2825: 49, 2882: 50, 2939: 51, 2996: 52, 3053: 53, 3110: 54, 3167: 55, 3224: 56, 3281: 57, 3338: 58, 3395: 59, 3452: 60, 3509: 61, 3566: 62, 3623: 63, 3680: 64, 3737: 65, 3794: 66, 3851: 67, 3908: 68, 3965: 69, 4022: 70, 4079: 71, 4136: 72, 4193: 73, 4250: 74, 4307: 75, 4364: 76, 4421: 77, 4478: 78, 4535: 79, 4592: 80, 4649: 81, 4706: 82, 4763: 83, 4820: 84, 4877: 85, 4934: 86, 4991: 87, 5048: 88, 5105: 89, 5162: 90, 5219: 91, 5276: 92, 5333: 93, 5390: 94, 5447: 95, 5504: 96, 5561: 97, 5618: 98, 5675: 99…] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
 console-object-preview.html:44 Array with gaps without overflow console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:49 [undefined × 32, 0, undefined × 56, 1, undefined × 56, 2, undefined × 56, 3, undefined × 56, 4, undefined × 56, 5, undefined × 56, 6, undefined × 56, 7, undefined × 56, 8, undefined × 56, 9, undefined × 56, 10, undefined × 56, 11, undefined × 56, 12, undefined × 56, 13, undefined × 56, 14, undefined × 56, 15, undefined × 56, 16, undefined × 56, 17, undefined × 56, 18, undefined × 56, 19, undefined × 56, 20, undefined × 56, 21, undefined × 56, 22, undefined × 56, 23, undefined × 56, 24, undefined × 56, 25, undefined × 56, 26, undefined × 56, 27, undefined × 56, 28, undefined × 56, 29, undefined × 56, 30, undefined × 56, 31, undefined × 56, 32, undefined × 56, 33, undefined × 56, 34, undefined × 56, 35, undefined × 56, 36, undefined × 56, 37, undefined × 56, 38, undefined × 56, 39, undefined × 56, 40, undefined × 56, 41, undefined × 56, 42, undefined × 56, 43, undefined × 56, 44, undefined × 56, 45, undefined × 56, 46, undefined × 56, 47, undefined × 56, 48, undefined × 56, 49, un console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > children
+console-object-preview.html:49 [undefined × 32, 0, undefined × 56, 1, undefined × 56, 2, undefined × 56, 3, undefined × 56, 4, undefined × 56, 5, undefined × 56, 6, undefined × 56, 7, undefined × 56, 8, undefined × 56, 9, undefined × 56, 10, undefined × 56, 11, undefined × 56, 12, undefined × 56, 13, undefined × 56, 14, undefined × 56, 15, undefined × 56, 16, undefined × 56, 17, undefined × 56, 18, undefined × 56, 19, undefined × 56, 20, undefined × 56, 21, undefined × 56, 22, undefined × 56, 23, undefined × 56, 24, undefined × 56, 25, undefined × 56, 26, undefined × 56, 27, undefined × 56, 28, undefined × 56, 29, undefined × 56, 30, undefined × 56, 31, undefined × 56, 32, undefined × 56, 33, undefined × 56, 34, undefined × 56, 35, undefined × 56, 36, undefined × 56, 37, undefined × 56, 38, undefined × 56, 39, undefined × 56, 40, undefined × 56, 41, undefined × 56, 42, undefined × 56, 43, undefined × 56, 44, undefined × 56, 45, undefined × 56, 46, undefined × 56, 47, undefined × 56, 48, undefined × 56, 49, un console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-state-note info-note > children
 console-object-preview.html:51 Object with proto console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:54 Object {d: 1} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > children
+console-object-preview.html:54 Object {d: 1} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > object-state-note info-note > children
 console-object-preview.html:56 Sparse array console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:59 [undefined × 50, 50, undefined × 99] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-undefined > object-value-number > object-value-undefined > children
+console-object-preview.html:59 [undefined × 50, 50, undefined × 99] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-undefined > object-value-number > object-value-undefined > object-state-note info-note > children
 console-object-preview.html:61 Dense array with indexes and propeties console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:67 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99…] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > children
+console-object-preview.html:67 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99…] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-state-note info-note > children
 console-object-preview.html:69 Object with properties containing whitespaces console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:76 Object {" a b ": " a b ", c d: "c d", "": "", "  ": "  ", "a↵↵b↵c": "a↵↵b↵c"} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string > children
+console-object-preview.html:76 Object {" a b ": " a b ", c d: "c d", "": "", "  ": "  ", "a↵↵b↵c": "a↵↵b↵c"} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string > object-state-note info-note > children
 console-object-preview.html:78 Object with a document.all property console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:79 Object {all: HTMLAllCollection[7]} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-array > children
+console-object-preview.html:79 Object {all: HTMLAllCollection[7]} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-array > object-state-note info-note > children
 console-object-preview.html:81 Object with special numbers console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:83 Object {nan: NaN, posInf: Infinity, negInf: -Infinity, negZero: -0} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > children
+console-object-preview.html:83 Object {nan: NaN, posInf: Infinity, negInf: -Infinity, negZero: -0} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
 console-object-preview.html:85 Object with exactly 5 properties: expected to be lossless console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:86 Object {a: 1, b: 2, c: 3, d: 4, e: 5} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > children
-console-object-preview.html:88 Object {null: null, undef: undefined, regexp: /^[regexp]$/g, bool: false} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-null > name > object-value-undefined > name > object-value-regexp > name > object-value-boolean > children
+console-object-preview.html:86 Object {a: 1, b: 2, c: 3, d: 4, e: 5} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children
+console-object-preview.html:88 Object {null: null, undef: undefined, regexp: /^[regexp]$/g, bool: false} console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-null > name > object-value-undefined > name > object-value-regexp > name > object-value-boolean > object-state-note info-note > children
 Expanded all messages
 console-object-preview.html:9 Mutating object in a loop console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:13 Objecta: 0b: 0c: 2__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
-console-object-preview.html:13 Objecta: 0b: 0c: 2__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
-console-object-preview.html:13 Objecta: 0b: 0c: 2__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:13 Object {a: 0, b: 0, c: 0}a: 0b: 0c: 2__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:13 Object {a: 0, b: 0, c: 1}a: 0b: 0c: 2__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:13 Object {a: 0, b: 0, c: 2}a: 0b: 0c: 2__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 console-object-preview.html:16 Mutating array in a loop console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:20 Array[3]0: 01: 02: 2length: 3__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
-console-object-preview.html:20 Array[3]0: 01: 02: 2length: 3__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
-console-object-preview.html:20 Array[3]0: 01: 02: 2length: 3__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:20 [0, 0, 0]0: 01: 02: 2length: 3__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:20 [0, 0, 1]0: 01: 02: 2length: 3__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:20 [0, 0, 2]0: 01: 02: 2length: 3__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
 console-object-preview.html:23 Object with many properties console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:28 Objectproperty_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:28 Object {property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…}property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 console-object-preview.html:30 Array with many properties console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:35 Array[2]0: 01: 1property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9length: 2__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:35 [0, 1, property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…]0: 01: 1property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9length: 2__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-number > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
 console-object-preview.html:37 Array with gaps and overflow console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:42 Array[5733][32 … 5675]5732: 100length: 5733__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > parent object-properties-section-name > selection fill > tree-element-title > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:42 [32: 0, 89: 1, 146: 2, 203: 3, 260: 4, 317: 5, 374: 6, 431: 7, 488: 8, 545: 9, 602: 10, 659: 11, 716: 12, 773: 13, 830: 14, 887: 15, 944: 16, 1001: 17, 1058: 18, 1115: 19, 1172: 20, 1229: 21, 1286: 22, 1343: 23, 1400: 24, 1457: 25, 1514: 26, 1571: 27, 1628: 28, 1685: 29, 1742: 30, 1799: 31, 1856: 32, 1913: 33, 1970: 34, 2027: 35, 2084: 36, 2141: 37, 2198: 38, 2255: 39, 2312: 40, 2369: 41, 2426: 42, 2483: 43, 2540: 44, 2597: 45, 2654: 46, 2711: 47, 2768: 48, 2825: 49, 2882: 50, 2939: 51, 2996: 52, 3053: 53, 3110: 54, 3167: 55, 3224: 56, 3281: 57, 3338: 58, 3395: 59, 3452: 60, 3509: 61, 3566: 62, 3623: 63, 3680: 64, 3737: 65, 3794: 66, 3851: 67, 3908: 68, 3965: 69, 4022: 70, 4079: 71, 4136: 72, 4193: 73, 4250: 74, 4307: 75, 4364: 76, 4421: 77, 4478: 78, 4535: 79, 4592: 80, 4649: 81, 4706: 82, 4763: 83, 4820: 84, 4877: 85, 4934: 86, 4991: 87, 5048: 88, 5105: 89, 5162: 90, 5219: 91, 5276: 92, 5333: 93, 5390: 94, 5447: 95, 5504: 96, 5561: 97, 5618: 98, 5675: 99…][32 … 5675]5732: 100l console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > parent object-properties-section-name > selection fill > tree-element-title > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
 console-object-preview.html:44 Array with gaps without overflow console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:49 Array[5619]32: 089: 1146: 2203: 3260: 4317: 5374: 6431: 7488: 8545: 9602: 10659: 11716: 12773: 13830: 14887: 15944: 161001: 171058: 181115: 191172: 201229: 211286: 221343: 231400: 241457: 251514: 261571: 271628: 281685: 291742: 301799: 311856: 321913: 331970: 342027: 352084: 362141: 372198: 382255: 392312: 402369: 412426: 422483: 432540: 442597: 452654: 462711: 472768: 482825: 492882: 502939: 512996: 523053: 533110: 543167: 553224: 563281: 573338: 583395: 593452: 603509: 613566: 623623: 633680: 643737: 653794: 663851: 673908: 683965: 694022: 704079: 714136: 724193: 734250: 744307: 754364: 764421: 774478: 784535: 794592: 804649: 814706: 824763: 834820: 844877: 854934: 864991: 875048: 885105: 895162: 905219: 915276: 925333: 935390: 945447: 955504: 965561: 975618: 98length: 5619__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:49 [undefined × 32, 0, undefined × 56, 1, undefined × 56, 2, undefined × 56, 3, undefined × 56, 4, undefined × 56, 5, undefined × 56, 6, undefined × 56, 7, undefined × 56, 8, undefined × 56, 9, undefined × 56, 10, undefined × 56, 11, undefined × 56, 12, undefined × 56, 13, undefined × 56, 14, undefined × 56, 15, undefined × 56, 16, undefined × 56, 17, undefined × 56, 18, undefined × 56, 19, undefined × 56, 20, undefined × 56, 21, undefined × 56, 22, undefined × 56, 23, undefined × 56, 24, undefined × 56, 25, undefined × 56, 26, undefined × 56, 27, undefined × 56, 28, undefined × 56, 29, undefined × 56, 30, undefined × 56, 31, undefined × 56, 32, undefined × 56, 33, undefined × 56, 34, undefined × 56, 35, undefined × 56, 36, undefined × 56, 37, undefined × 56, 38, undefined × 56, 39, undefined × 56, 40, undefined × 56, 41, undefined × 56, 42, undefined × 56, 43, undefined × 56, 44, undefined × 56, 45, undefined × 56, 46, undefined × 56, 47, undefined × 56, 48, undefined × 56, 49, un console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-value-undefined > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
 console-object-preview.html:51 Object with proto console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:54 Objectd: 1__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:54 Object {d: 1}d: 1__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 console-object-preview.html:56 Sparse array console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:59 Array[150]50: 50length: 150__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:59 [undefined × 50, 50, undefined × 99]50: 50length: 150__proto__: Array[0] console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-undefined > object-value-number > object-value-undefined > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
 console-object-preview.html:61 Dense array with indexes and propeties console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:67 Array[150][0 … 99][100 … 149]property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9property_10: 10property_11: 11property_12: 12property_13: 13property_14: 14property_15: 15property_16: 16property_17: 17property_18: 18property_19: 19property_20: 20property_21: 21property_22: 22property_23: 23property_24: 24property_25: 25property_26: 26property_27: 27property_28: 28property_29: 29property_30: 30property_31: 31property_32: 32property_33: 33property_34: 34property_35: 35property_36: 36property_37: 37property_38: 38property_39: 39property_40: 40property_41: 41property_42: 42property_43: 43property_44: 44property_45: 45property_46: 46property_47: 47property_48: 48property_49: 49property_50: 50property_51: 51property_52: 52property_53: 53property_54: 54property_55: 55property_56: 56property_57: 57property_58: 58property_59: 59property_60: 60property_61: 61property_62: 62property_63: 63property_64: 64property_ console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > parent object-properties-section-name > selection fill > tree-element-title > children > parent object-properties-section-name > selection fill > tree-element-title > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
+console-object-preview.html:67 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99…][0 … 99][100 … 149]property_0: 0property_1: 1property_2: 2property_3: 3property_4: 4property_5: 5property_6: 6property_7: 7property_8: 8property_9: 9property_10: 10property_11: 11property_12: 12property_13: 13property_14: 14property_15: 15property_16: 16property_17: 17property_18: 18property_19: 19property_20: 20property_21: 21property_22: 22property_23: 23property_24: 24property_25: 25property_26: 26property_27: 27property_28: 28property_29: 29property_30: 30property_31: 31property_32: 32property_33: 33property_34: 34property_35: 35property_36: 36property_37: 37property_38: 38property_39: 39pro console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-array source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-state-note info-note > children expanded > parent object-properties-section-name > selection fill > tree-element-title > children > parent object-properties-section-name > selection fill > tree-element-title > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-array value > children
 console-object-preview.html:69 Object with properties containing whitespaces console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:76 Object"": """  ": "  "" a b ": " a b ""a↵↵b↵c": "a↵↵b↵c"c d: "c d"__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:76 Object {" a b ": " a b ", c d: "c d", "": "", "  ": "  ", "a↵↵b↵c": "a↵↵b↵c"}"": """  ": "  "" a b ": " a b ""a↵↵b↵c": "a↵↵b↵c"c d: "c d"__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > selection fill > name > object-properties-section-separator > object-value-string value > object-value-string-quote > object-value-string-quote > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 console-object-preview.html:78 Object with a document.all property console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:79 Objectall: HTMLAllCollection[7]__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > parent > selection fill > name > object-properties-section-separator > object-value-array value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:79 Object {all: HTMLAllCollection[7]}all: HTMLAllCollection[7]__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-array > object-state-note info-note > children expanded > parent > selection fill > name > object-properties-section-separator > object-value-array value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 console-object-preview.html:81 Object with special numbers console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:83 Objectnan: NaNnegInf: -InfinitynegZero: -0posInf: Infinity__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:83 Object {nan: NaN, posInf: Infinity, negInf: -Infinity, negZero: -0}nan: NaNnegInf: -InfinitynegZero: -0posInf: Infinity__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 console-object-preview.html:85 Object with exactly 5 properties: expected to be lossless console-message > source-code > console-message-anchor > devtools-link > console-message-text
-console-object-preview.html:86 Objecta: 1b: 2c: 3d: 4e: 5__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
-console-object-preview.html:88 Objectbool: falsenull: nullregexp: /^[regexp]$/gundef: undefined__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-boolean value > children > selection fill > name > object-properties-section-separator > object-value-null value > children > parent > selection fill > name > object-properties-section-separator > object-value-regexp value > children > selection fill > name > object-properties-section-separator > object-value-undefined value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:86 Object {a: 1, b: 2, c: 3, d: 4, e: 5}a: 1b: 2c: 3d: 4e: 5__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > selection fill > name > object-properties-section-separator > object-value-number value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
+console-object-preview.html:88 Object {null: null, undef: undefined, regexp: /^[regexp]$/g, bool: false}bool: falsenull: nullregexp: /^[regexp]$/gundef: undefined__proto__: Object console-message > source-code > console-message-anchor > devtools-link > console-message-text > console-view-object-properties-section object-value-object source-code expanded > tree-outline-disclosure tree-outline-disclosure-hide-overflow > tree-outline source-code object-properties-section > parent object-properties-section-root-element expanded > selection fill > console-object-preview > name > object-value-null > name > object-value-undefined > name > object-value-regexp > name > object-value-boolean > object-state-note info-note > children expanded > selection fill > name > object-properties-section-separator > object-value-boolean value > children > selection fill > name > object-properties-section-separator > object-value-null value > children > parent > selection fill > name > object-properties-section-separator > object-value-regexp value > children > selection fill > name > object-properties-section-separator > object-value-undefined value > children > parent > selection fill > name object-properties-section-dimmed > object-properties-section-separator > object-value-object value > children
 
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/extensions/extensions-eval-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/extensions/extensions-eval-expected.txt
new file mode 100644
index 0000000..2f89266
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/extensions/extensions-eval-expected.txt
@@ -0,0 +1,23 @@
+Tests WebInspector extension API
+
+Started extension.
+Running tests...
+RUNNING TEST: extension_testEvalConsoleAPI
+Evaluate: "function" (exception: undefined)
+RUNNING TEST: extension_testEvalDefinesGlobalSymbols
+Evaluate: {"func":"function","variable":42} (exception: undefined)
+RUNNING TEST: extension_testEvalOk
+Evaluate: {"str":"foo","num":42} (exception: undefined)
+RUNNING TEST: extension_testEvalStatement
+Evaluate: 0 (exception: undefined)
+RUNNING TEST: extension_testEvalStringifyingLoopFailed
+error: Extension server error: Inspector protocol error: Object has too long reference chain
+Evaluate: undefined (exception: {"code":"E_PROTOCOLERROR","description":"Inspector protocol error: %s","details":["Object has too long reference chain"],"isError":true})
+RUNNING TEST: extension_testEvalThrows
+Evaluate: undefined (exception: {"isException":true,"value":"testExceptionString"})
+RUNNING TEST: extension_testEvalUndefined
+Evaluate: undefined (exception: undefined)
+RUNNING TEST: extension_testWithStringifyOverridden
+Evaluate: "OK" (exception: undefined)
+All tests done.
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/extensions/extensions-sidebar-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/extensions/extensions-sidebar-expected.txt
new file mode 100644
index 0000000..4500d50
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/extensions/extensions-sidebar-expected.txt
@@ -0,0 +1,91 @@
+Tests sidebars in WebInspector extensions API
+
+Started extension.
+Running tests...
+RUNNING TEST: extension_testElementsSidebarPageReplacedWithObject
+Got onShown(), frame defined
+Got onShown(), frame not defined
+RUNNING TEST: extension_testElementsSidebarSetExpression
+elements sidebar content: titlef0: "expression"f1: undefinedf2: nullf3: Objectf4: Array[0]f5: Array[3]f6: Objectf7: 42f8: Locationf9: HTMLCollection[1]f10: function ()f11: "foo"__proto__: Object
+RUNNING TEST: extension_testElementsSidebarSetObject
+Watch sidebar created, callback arguments dump follows:
+{
+    0 : {
+        onHidden : {
+            addListener : <function>
+            removeListener : <function>
+        }
+        onShown : {
+            addListener : <function>
+            removeListener : <function>
+        }
+        setExpression : <function>
+        setHeight : <function>
+        setObject : <function>
+        setPage : <function>
+    }
+}
+elements sidebar content: f0: "object"f1: undefinedf2: nullf3: {}f4: []f5: ["aa", "bb", "cc"]f6: {f60: 42, f61: "foo", f62: []}f7: 42
+RUNNING TEST: extension_testElementsSidebarSetPage
+Call createSidebarPane for elements
+Sidebar created
+{
+    onHidden : {
+        addListener : <function>
+        removeListener : <function>
+    }
+    onShown : {
+        addListener : <function>
+        removeListener : <function>
+    }
+    setExpression : <function>
+    setHeight : <function>
+    setObject : <function>
+    setPage : <function>
+}
+RUNNING TEST: extension_testSourcesSidebarPageReplacedWithObject
+Got onShown(), frame defined
+Got onShown(), frame not defined
+RUNNING TEST: extension_testSourcesSidebarSetExpression
+sources sidebar content: titlef0: "expression"f1: undefinedf2: nullf3: Objectf4: Array[0]f5: Array[3]f6: Objectf7: 42f8: Locationf9: HTMLCollection[1]f10: function ()__proto__: Object
+RUNNING TEST: extension_testSourcesSidebarSetExpressionOnShown
+setExpression onShown frame: undefined
+RUNNING TEST: extension_testSourcesSidebarSetObject
+Watch sidebar created, callback arguments dump follows:
+{
+    0 : {
+        onHidden : {
+            addListener : <function>
+            removeListener : <function>
+        }
+        onShown : {
+            addListener : <function>
+            removeListener : <function>
+        }
+        setExpression : <function>
+        setHeight : <function>
+        setObject : <function>
+        setPage : <function>
+    }
+}
+sources sidebar content: f0: "object"f1: undefinedf2: nullf3: {}f4: []f5: ["aa", "bb", "cc"]f6: {f60: 42, f61: "foo", f62: []}f7: 42
+RUNNING TEST: extension_testSourcesSidebarSetPage
+Call createSidebarPane for sources
+Sidebar created
+{
+    onHidden : {
+        addListener : <function>
+        removeListener : <function>
+    }
+    onShown : {
+        addListener : <function>
+        removeListener : <function>
+    }
+    setExpression : <function>
+    setHeight : <function>
+    setObject : <function>
+    setPage : <function>
+}
+sidebar height 150
+All tests done.
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/input-event-warning-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/input-event-warning-expected.txt
new file mode 100644
index 0000000..6b7d40a2
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/input-event-warning-expected.txt
@@ -0,0 +1,4 @@
+Tests that console warnings are issued for a blocked event listener and that there is no crash when an offending listener is removed by the handler.
+
+There should be no warnings above this line
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/layers/layer-replay-scale-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/layers/layer-replay-scale-expected.txt
new file mode 100644
index 0000000..8d319b02
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/layers/layer-replay-scale-expected.txt
@@ -0,0 +1,6 @@
+Tests that when layer snapshots are replayed with scaling applied the image dimensions are properly scaled.
+
+
+Image dimensions at scale undefined: 180 x 180
+Image dimensions at scale 0.5: 180 x 180
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/layers/layer-tree-model-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/layers/layer-tree-model-expected.txt
new file mode 100644
index 0000000..77d7187d
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/layers/layer-tree-model-expected.txt
@@ -0,0 +1,44 @@
+
+Initial layer tree
+#document (9)
+    iframe#frame (10)
+        iframe#frame 200x200 (11)
+            iframe#frame 200x200 (12)
+                iframe#frame 200x200 (13)
+                    iframe#frame 200x200 (14)
+                        #document 200x200 (15)
+                            div#subframe1 80x80 (16)
+    div#a 200x200 (10)
+        div#b1 100x150 (11)
+        div#b2 110x140 (11)
+            div#c 90x100 (12)
+        div#b3 110x140 (11)
+Updated layer tree
+#document (9)
+    iframe#frame (10)
+        iframe#frame 200x200 (11)
+            iframe#frame 200x200 (12)
+                iframe#frame 200x200 (13)
+                    iframe#frame 200x200 (14)
+                        #document 200x200 (15)
+                            div#subframe1 80x80 (16)
+    div#a 200x200 (10)
+        div#b2 110x140 (11)
+            div#c 90x100 (12)
+                div#b1 100x150
+        div#b4 0x200
+Updated layer geometry
+#document (9)
+    iframe#frame (10)
+        iframe#frame 200x200 (11)
+            iframe#frame 200x200 (12)
+                iframe#frame 200x200 (13)
+                    iframe#frame 200x200 (14)
+                        #document 200x200 (15)
+                            div#subframe1 80x80 (16)
+    div#a 200x200 (10)
+        div#b2 110x140 (11)
+            div#c 90x80 (12)
+                div#b1 100x150
+        div#b4 0x200
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/report-protocol-errors-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/report-protocol-errors-expected.txt
new file mode 100644
index 0000000..851eeaa
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/report-protocol-errors-expected.txt
@@ -0,0 +1,159 @@
+Tests that InspectorBackendDispatcher is catching incorrect messages.
+
+{
+    error : {
+        code : -32700
+        message : "Message must be in JSON format"
+    }
+    id : null
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32600
+        message : "The type of 'id' property must be number"
+    }
+    id : null
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32600
+        message : "The type of 'id' property must be number"
+    }
+    id : null
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32600
+        message : "The type of 'method' property must be string"
+    }
+    id : 1
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'resourceContent' wasn't found"
+    }
+    id : 2
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 3
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32602
+        data : "nodeId: integer value expected"
+        message : "Invalid request"
+    }
+    id : 4
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32602
+        data : "nodeId: integer value expected"
+        message : "Invalid request"
+    }
+    id : 5
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32602
+        data : "nodeId: integer value expected"
+        message : "Invalid request"
+    }
+    id : 6
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32602
+        data : "nodeId: integer value expected"
+        message : "Invalid request"
+    }
+    id : 7
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 8
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 9
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 10
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 11
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 12
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 13
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 14
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 15
+}
+-------------------------------------------------------
+{
+    error : {
+        code : -32601
+        message : "'DOM.test' wasn't found"
+    }
+    id : 16
+}
+-------------------------------------------------------
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/schema-get-domains-matches-agents-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/schema-get-domains-matches-agents-expected.txt
new file mode 100644
index 0000000..205b17b
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/schema-get-domains-matches-agents-expected.txt
@@ -0,0 +1,8 @@
+Tests that generated agent prototypes match with domains returned by schema.getDomains.
+
+agent Browser is missing from target
+agent Worker is missing from target
+domain SystemInfo is missing from schema.getDomains
+domain Target is missing from schema.getDomains
+domain Tethering is missing from schema.getDomains
+
diff --git a/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/screen-orientation-override-expected.txt b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/screen-orientation-override-expected.txt
new file mode 100644
index 0000000..711aab48
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/tests/baseline/protocol-1.2/inspector/screen-orientation-override-expected.txt
@@ -0,0 +1,36 @@
+CONSOLE MESSAGE: line 25: angle: 0; type: portrait-primary
+CONSOLE MESSAGE: line 25: angle: 180; type: portrait-secondary
+CONSOLE MESSAGE: line 25: angle: 90; type: landscape-primary
+CONSOLE MESSAGE: line 25: angle: 270; type: landscape-secondary
+CONSOLE MESSAGE: line 25: angle: 0; type: landscape-primary
+
+Running: initial
+
+Running: setWrongAngle1
+error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Missing or invalid 'Screen orientation angle must be non-negative, less than 360' parameter"}
+
+Running: setWrongAngle2
+error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Missing or invalid 'Screen orientation angle must be non-negative, less than 360' parameter"}
+
+Running: setWrongType
+error: Request Emulation.setDeviceMetricsOverride failed. {"code":-32602,"message":"Missing or invalid 'Invalid screen orientation type value' parameter"}
+
+Running: setPortraitPrimary
+angle: 0; type: portrait-primary
+
+Running: setPortraitSecondary
+angle: 180; type: portrait-secondary
+
+Running: setLandscapePrimary
+angle: 90; type: landscape-primary
+
+Running: restoresAfterReload
+Page reloaded.
+angle: 90; type: landscape-primary
+
+Running: setLandscapeSecondary
+angle: 270; type: landscape-secondary
+
+Running: clearOverride
+Equals to initial: true
+
diff --git a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp
index a90e01e..663842f 100644
--- a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp
+++ b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp
@@ -74,14 +74,6 @@
 }
 
 void BroadcastChannel::close() {
-  if (!Platform::current()) {
-    // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed.
-    // Note that reaching this code indicates that the MessageLoop has already
-    // been torn down, so it's impossible for further incoming messages to be
-    // dispatched on |m_binding| or reply callbacks to be invoked from
-    // |m_remoteClient|.
-    return;
-  }
   m_remoteClient.reset();
   if (m_binding.is_bound())
     m_binding.Close();
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
index 72795ee..ae354cf9 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
+++ b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
@@ -4,6 +4,8 @@
 
 #include "modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.h"
 
+#include <algorithm>
+
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/ScriptState.h"
@@ -12,6 +14,7 @@
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/frame/Deprecation.h"
+#include "core/frame/Settings.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "modules/encryptedmedia/EncryptedMediaUtils.h"
 #include "modules/encryptedmedia/MediaKeySession.h"
@@ -20,6 +23,7 @@
 #include "platform/EncryptedMediaRequest.h"
 #include "platform/Histogram.h"
 #include "platform/network/ParsedContentType.h"
+#include "platform/network/mime/ContentType.h"
 #include "public/platform/WebEncryptedMediaClient.h"
 #include "public/platform/WebEncryptedMediaRequest.h"
 #include "public/platform/WebMediaKeySystemConfiguration.h"
@@ -28,7 +32,6 @@
 #include "wtf/PtrUtil.h"
 #include "wtf/Vector.h"
 #include "wtf/text/WTFString.h"
-#include <algorithm>
 
 namespace blink {
 
@@ -50,9 +53,10 @@
     result[i].contentType = contentType;
     if (isValidContentType(contentType)) {
       // FIXME: Fail if there are unrecognized parameters.
-      ParsedContentType type(capabilities[i].contentType());
-      result[i].mimeType = type.mimeType();
-      result[i].codecs = type.parameterValueForName("codecs");
+      // http://crbug.com/690131
+      ContentType type(capabilities[i].contentType());
+      result[i].mimeType = type.type();
+      result[i].codecs = type.parameter("codecs");
     }
     result[i].robustness = capabilities[i].robustness();
   }
@@ -304,6 +308,17 @@
     const HeapVector<MediaKeySystemConfiguration>& supportedConfigurations) {
   DVLOG(3) << __func__;
 
+  ExecutionContext* executionContext = scriptState->getExecutionContext();
+  Document* document = toDocument(executionContext);
+
+  // If encrypted media is disabled, return a rejected promise.
+  if (!document->settings() ||
+      !document->settings()->getEncryptedMediaEnabled()) {
+    return ScriptPromise::rejectWithDOMException(
+        scriptState, DOMException::create(NotSupportedError,
+                                          "Encrypted media is disabled."));
+  }
+
   // From https://w3c.github.io/encrypted-media/#requestMediaKeySystemAccess
   // When this method is invoked, the user agent must run the following steps:
   // 1. If keySystem is the empty string, return a promise rejected with a
@@ -328,7 +343,6 @@
   // by the [SecureContext] IDL attribute. Since that will break some existing
   // sites, we simply keep track of sites that aren't secure and output a
   // deprecation message.
-  ExecutionContext* executionContext = scriptState->getExecutionContext();
   if (executionContext->isSecureContext()) {
     UseCounter::count(executionContext, UseCounter::EncryptedMediaSecureOrigin);
   } else {
@@ -339,7 +353,7 @@
   }
 
   // 3. Let document be the calling context's Document.
-  Document* document = toDocument(executionContext);
+  //    (Done at the begining of this function.)
   if (!document->page()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
diff --git a/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp b/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
index 846e17b..88d57545 100644
--- a/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
+++ b/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
@@ -530,13 +530,6 @@
 }
 
 void Geolocation::onGeolocationConnectionError() {
-  // If a request is outstanding at process shutdown, this error handler will
-  // be called. In that case, blink has already shut down so do nothing.
-  //
-  // TODO(sammc): Remove this once renderer shutdown is no longer graceful.
-  if (!Platform::current())
-    return;
-
   PositionError* error = PositionError::create(
       PositionError::kPositionUnavailable, failedToStartServiceErrorMessage);
   error->setIsFatal(true);
@@ -544,13 +537,6 @@
 }
 
 void Geolocation::onPermissionConnectionError() {
-  // If a request is outstanding at process shutdown, this error handler will
-  // be called. In that case, blink has already shut down so do nothing.
-  //
-  // TODO(sammc): Remove this once renderer shutdown is no longer graceful.
-  if (!Platform::current())
-    return;
-
   onGeolocationPermissionUpdated(mojom::blink::PermissionStatus::DENIED);
 }
 
diff --git a/third_party/WebKit/Source/modules/notifications/Notification.cpp b/third_party/WebKit/Source/modules/notifications/Notification.cpp
index 8f9f047..41227ea 100644
--- a/third_party/WebKit/Source/modules/notifications/Notification.cpp
+++ b/third_party/WebKit/Source/modules/notifications/Notification.cpp
@@ -41,6 +41,7 @@
 #include "core/dom/ScopedWindowFocusAllowedIndicator.h"
 #include "core/dom/TaskRunnerHelper.h"
 #include "core/events/Event.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/UseCounter.h"
 #include "modules/notifications/NotificationAction.h"
 #include "modules/notifications/NotificationData.h"
@@ -98,9 +99,10 @@
       UseCounter::countCrossOriginIframe(
           *toDocument(context), UseCounter::NotificationAPISecureOriginIframe);
   } else {
-    UseCounter::count(context, UseCounter::NotificationInsecureOrigin);
+    Deprecation::countDeprecation(context,
+                                  UseCounter::NotificationInsecureOrigin);
     if (context->isDocument())
-      UseCounter::countCrossOriginIframe(
+      Deprecation::countDeprecationCrossOriginIframe(
           *toDocument(context),
           UseCounter::NotificationAPIInsecureOriginIframe);
   }
@@ -358,8 +360,13 @@
 ScriptPromise Notification::requestPermission(
     ScriptState* scriptState,
     NotificationPermissionCallback* deprecatedCallback) {
-  return NotificationManager::from(scriptState->getExecutionContext())
-      ->requestPermission(scriptState, deprecatedCallback);
+  ExecutionContext* context = scriptState->getExecutionContext();
+  if (!context->isSecureContext()) {
+    Deprecation::countDeprecation(
+        context, UseCounter::NotificationPermissionRequestedInsecureOrigin);
+  }
+  return NotificationManager::from(context)->requestPermission(
+      scriptState, deprecatedCallback);
 }
 
 size_t Notification::maxActions() {
diff --git a/third_party/WebKit/Source/modules/payments/PaymentAppManager.cpp b/third_party/WebKit/Source/modules/payments/PaymentAppManager.cpp
index 3b06ab4..b996878 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentAppManager.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentAppManager.cpp
@@ -194,10 +194,6 @@
 }
 
 void PaymentAppManager::onServiceConnectionError() {
-  if (!Platform::current()) {
-    return;
-  }
-
   m_manager.reset();
 }
 
diff --git a/third_party/WebKit/Source/modules/permissions/Permissions.cpp b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
index 329a9a2..c393f5ed 100644
--- a/third_party/WebKit/Source/modules/permissions/Permissions.cpp
+++ b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
@@ -265,13 +265,6 @@
 }
 
 void Permissions::serviceConnectionError() {
-  if (!Platform::current()) {
-    // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed.
-    // Note that reaching this code indicates that the MessageLoop has already
-    // been torn down, so it's impossible for any pending reply callbacks on
-    // |m_service| to fire beyond this point anyway.
-    return;
-  }
   m_service.reset();
 }
 
diff --git a/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp b/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp
index 8fa5d5a..b1d675e 100644
--- a/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp
+++ b/third_party/WebKit/Source/modules/plugins/DOMPluginArray.cpp
@@ -22,6 +22,7 @@
 
 #include "core/frame/LocalFrame.h"
 #include "core/page/Page.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/plugins/PluginData.h"
 #include "wtf/Vector.h"
 #include "wtf/text/AtomicString.h"
@@ -67,8 +68,12 @@
   if (!frame())
     return;
   Page::refreshPlugins();
-  if (reload)
-    frame()->reload(FrameLoadTypeReload, ClientRedirectPolicy::ClientRedirect);
+  if (reload) {
+    frame()->reload(RuntimeEnabledFeatures::fasterLocationReloadEnabled()
+                        ? FrameLoadTypeReloadMainResource
+                        : FrameLoadTypeReload,
+                    ClientRedirectPolicy::ClientRedirect);
+  }
 }
 
 PluginData* DOMPluginArray::pluginData() const {
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
index 9fb52ad6..53c7e9f 100644
--- a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
+++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
@@ -165,11 +165,6 @@
 void SensorProxy::handleSensorError(ExceptionCode code,
                                     String sanitizedMessage,
                                     String unsanitizedMessage) {
-  if (!Platform::current()) {
-    // TODO(rockot): Remove this hack once renderer shutdown sequence is fixed.
-    return;
-  }
-
   m_state = Uninitialized;
   m_frequenciesUsed.clear();
   m_reading = device::SensorReading();
diff --git a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
index 9c863dd4..8a5aecc 100644
--- a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
@@ -129,14 +129,6 @@
 
 void WebSocketHandleImpl::onConnectionError(uint32_t customReason,
                                             const std::string& description) {
-  if (!blink::Platform::current()) {
-    // In the renderrer shutdown sequence, mojo channels are destructed and this
-    // function is called. On the other hand, blink objects became invalid
-    // *silently*, which means we must not touch |*client_| any more.
-    // TODO(yhirano): Remove this code once the shutdown sequence is fixed.
-    return;
-  }
-
   // Our connection to the WebSocket was dropped. This could be due to
   // exceeding the maximum number of concurrent websockets from this process.
   String failureMessage;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 290e42c..57dc61b 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -98,9 +98,9 @@
 action("runtime_enabled_features") {
   script = "../build/scripts/make_runtime_features.py"
 
-  runtime_enabled_features_in = "RuntimeEnabledFeatures.in"
+  runtime_enabled_features_json5 = "RuntimeEnabledFeatures.json5"
   inputs = scripts_for_in_files + [
-             runtime_enabled_features_in,
+             runtime_enabled_features_json5,
              "../build/scripts/templates/RuntimeEnabledFeatures.cpp.tmpl",
              "../build/scripts/templates/RuntimeEnabledFeatures.h.tmpl",
            ]
@@ -111,7 +111,7 @@
   ]
 
   args = [
-    rebase_path(runtime_enabled_features_in, root_build_dir),
+    rebase_path(runtime_enabled_features_json5, root_build_dir),
     "--output_dir",
     rebase_path(blink_platform_output_dir, root_build_dir),
   ]
@@ -405,10 +405,14 @@
     "audio/AudioDestination.cpp",
     "audio/AudioDestination.h",
     "audio/AudioDestinationConsumer.h",
+    "audio/AudioFIFO.cpp",
+    "audio/AudioFIFO.h",
     "audio/AudioFileReader.h",
     "audio/AudioIOCallback.h",
     "audio/AudioProcessor.cpp",
     "audio/AudioProcessor.h",
+    "audio/AudioPullFIFO.cpp",
+    "audio/AudioPullFIFO.h",
     "audio/AudioResampler.cpp",
     "audio/AudioResampler.h",
     "audio/AudioResamplerKernel.cpp",
@@ -455,8 +459,6 @@
     "audio/MultiChannelResampler.h",
     "audio/Panner.cpp",
     "audio/Panner.h",
-    "audio/PushPullFIFO.cpp",
-    "audio/PushPullFIFO.h",
     "audio/Reverb.cpp",
     "audio/Reverb.h",
     "audio/ReverbAccumulationBuffer.cpp",
@@ -1620,6 +1622,8 @@
     "testing/PictureMatchers.h",
     "testing/PlatformTestPrinters.cpp",
     "testing/RuntimeEnabledFeaturesTestHelpers.h",
+    "testing/ScopedMockedURL.cpp",
+    "testing/ScopedMockedURL.h",
     "testing/TestPaintArtifact.cpp",
     "testing/TestPaintArtifact.h",
     "testing/TestingPlatformSupport.cpp",
@@ -1695,7 +1699,6 @@
     "animation/CompositorAnimationTimelineTest.cpp",
     "animation/CompositorFloatAnimationCurveTest.cpp",
     "animation/TimingFunctionTest.cpp",
-    "audio/PushPullFIFOTest.cpp",
     "blob/BlobDataTest.cpp",
     "exported/FilePathConversionTest.cpp",
     "exported/WebStringTest.cpp",
diff --git a/third_party/WebKit/Source/platform/DateComponents.cpp b/third_party/WebKit/Source/platform/DateComponents.cpp
index 5ad6e0b7..7176b0c 100644
--- a/third_party/WebKit/Source/platform/DateComponents.cpp
+++ b/third_party/WebKit/Source/platform/DateComponents.cpp
@@ -447,8 +447,10 @@
           } else if (digitsLength == 2) {
             ok = toInt(src, index, 2, millisecond);
             millisecond *= 10;
-          } else {  // digitsLength >= 3
+          } else if (digitsLength == 3) {
             ok = toInt(src, index, 3, millisecond);
+          } else {  // digitsLength >= 4
+            return false;
           }
           DCHECK(ok);
           index += digitsLength;
diff --git a/third_party/WebKit/Source/platform/OWNERS b/third_party/WebKit/Source/platform/OWNERS
index 01734c53..33b1079 100644
--- a/third_party/WebKit/Source/platform/OWNERS
+++ b/third_party/WebKit/Source/platform/OWNERS
@@ -21,6 +21,6 @@
 
 # In addition to the above, API_OWNERS are also adequate reviewers
 # for adding / changing the status of a feature.
-per-file RuntimeEnabledFeatures.in=file://third_party/WebKit/API_OWNERS
+per-file RuntimeEnabledFeatures.json5=file://third_party/WebKit/API_OWNERS
 
 # COMPONENT: Platform
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
deleted file mode 100644
index 081f0586..0000000
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ /dev/null
@@ -1,289 +0,0 @@
-// http://dev.chromium.org/blink/runtime-enabled-features
-//
-// This list is used to generate RuntimeEnabledFeatures.h/cpp which contains
-// a class that stores static enablers for all experimental features.
-//
-// Each feature can be assigned a "status":
-// status=stable -> Enable this in all Blink configurations.  We are committed to these APIs indefinitely.
-// status=experimental -> In-progress features, Web Developers might play with, but are not on by default in stable.
-// status=test -> Enabled in ContentShell for testing, otherwise off.
-// Features without a status are not enabled anywhere by default.
-//
-// "implied_by" or "depends_on" specifies relationship to other features:
-// implied_by=feature1[,feature2,...] -> The feature is automatically enabled if any implied_by features is enabled;
-// depends_on=feature1[,feature2,...] -> The feature is enabled only if all depends_on features are enabled.
-// Only one of "implied_by" and "depends_on" can be specified.
-//
-// "stable" features listed here should be rare, as anything which we've shipped stable
-// can have its runtime flag removed soon after.
-//
-// origin_trial_feature_name=FEATURE_NAME is used to integrate the feature with
-// the Origin Trials framework. The framework allows the feature to be enabled
-// at runtime on a per-page basis through a signed token for the corresponding
-// feature name. Declaring the origin_trial_feature_name will cause a static
-// method to be generated in OriginTrials.h/cpp. This static method allows the
-// feature implementation to check if it is enabled for the current context.
-//
-// settable_from_internals specifies whether a feature can be set from internals.runtimeFlags, with the default
-// being false.
-
-Accelerated2dCanvas status=stable, settable_from_internals=True
-AudioOutputDevices status=stable
-AudioVideoTracks status=experimental
-AudioWorklet status=experimental
-Auxclick status=stable
-CoalescedEvents status=stable
-BackgroundSync status=stable
-BackspaceDefaultHandler status=test
-BroadcastChannel status=stable
-Budget status=experimental
-Canvas2dFixedRenderingMode status=test
-EnableCanvas2dDynamicRenderingModeSwitching status=experimental
-CanMakePayment status=stable
-Canvas2dImageChromium status=experimental
-ClientHints status=stable
-CompositeOpaqueFixedPosition status=test, settable_from_internals=True
-CompositeOpaqueScrollers status=stable, settable_from_internals=True
-ColorCorrectRendering status=experimental
-ColorCorrectRenderingDefaultMode status=experimental
-CompositedSelectionUpdate
-CompositorWorker status=experimental
-ContextMenu status=test
-CorsRFC1918 status=test
-CredentialManager status=stable
-CSS3Text status=experimental
-CSS3TextDecorations status=stable
-CSSApplyAtRules status=experimental
-CSSAdditiveAnimations status=experimental, depends_on=StackedCSSPropertyAnimations
-CSSBackdropFilter status=experimental
-CSSHexAlphaColor status=experimental
-CSSContainment status=stable
-CSSFontDisplay status=experimental
-CSSFontSizeAdjust status=experimental
-CSSGridLayout status=stable, settable_from_internals=True
-CSSDisplayContents status=experimental
-CSSHyphens status=stable
-CSSInBodyDoesNotBlockPaint status=experimental
-CSSIndependentTransformProperties status=experimental
-CSSMaskSourceType status=experimental
-CSSOMSmoothScroll status=experimental
-CSSOffsetPositionAnchor status=experimental
-CSSOffsetRotate status=stable
-CSSOffsetRotation status=stable
-CSSPaintAPI status=experimental, depends_on=CSSTypedOM, depends_on=Worklet
-CSSPaintAPIArguments status=experimental, depends_on=CSSPaintAPI
-CSSSnapSize status=experimental
-CSSStickyPosition status=stable
-CSSTouchActionPanDirections status=stable
-CSSTouchActionPinchZoom status=stable
-CSSTypedOM status=experimental
-CSSVariableFonts status=experimental
-CSSVariables2 status=experimental
-CSSViewport status=experimental
-CSSScrollSnapPoints status=test
-CustomElementsBuiltin status=test
-CustomElementsV1 status=stable
-CustomSchemeHandler depends_on=NavigatorContentUtils, status=experimental
-Database status=stable
-DecodeToYUV status=experimental
-DesktopCaptureDisableLocalEchoControl status=experimental
-DeviceLight status=experimental
-DisplayList2dCanvas status=stable
-DocumentCookie
-DocumentDomain
-DocumentWrite
-DocumentWriteEvaluator
-DOMConvenienceAPI status=stable
-DurableStorage status=stable
-ExpensiveBackgroundTimerThrottling status=experimental
-FasterLocationReload status=experimental
-FontCacheScaling status=test
-ForceDisplayList2dCanvas
-// See crbug.com/585250.
-ForceDisable2dCanvasCopyOnWrite
-EmbedderCSPEnforcement status=experimental
-ExecCommandInJavaScript status=test
-ComputedAccessibilityInfo status=experimental
-ExperimentalCanvasFeatures status=test
-ExperimentalContentSecurityPolicyFeatures status=experimental
-ExperimentalV8Extras status=experimental
-FastMobileScrolling
-FeaturePolicy status=experimental
-FileAPIBlobClose status=experimental
-FileSystem status=stable
-ForeignFetch status=experimental, origin_trial_feature_name=ForeignFetch
-FramebustingNeedsSameOriginOrUserGesture status=stable, settable_from_internals=True
-FullscreenUnprefixed status=test, settable_from_internals=True
-FrameTimingSupport status=experimental
-GamepadExtensions status=test, origin_trial_feature_name=WebVR
-GeometryInterfaces status=experimental, implied_by=CompositorWorker
-GetUserMedia status=stable
-GlobalCacheStorage status=stable
-HeapCompaction status=stable
-IDBObserver status=experimental
-IdleTimeSpellChecking
-ImageCapture status=experimental, origin_trial_feature_name=ImageCapture
-ImageOrientation status=test
-IndexedDBExperimental status=experimental
-InertTopControls status=stable
-InputEvent status=experimental
-InputModeAttribute status=experimental
-InputMultipleFieldsUI status=stable
-InstalledApp status=experimental
-IntersectionObserver status=stable
-LangAttributeAwareFormControlUI
-LayoutNG
-LayoutNGInline
-LinkServiceWorker status=experimental, origin_trial_feature_name=ForeignFetch
-LongTaskObserver status=experimental, origin_trial_feature_name=LongTaskObserver
-FractionalScrollOffsets
-LoadingWithMojo
-MediaCapture
-MediaCaptureDepth status=experimental
-MediaCaptureFromCanvas status=stable
-MediaCaptureFromVideo status=experimental
-MediaConstraints status=stable
-MediaDocumentDownloadButton
-MediaGetSettings status=experimental
-// MediaSession is enabled by default on Android only.
-MediaSession status=test
-MediaSourceExperimental status=experimental
-MediaSourceNewAbortAndDuration status=experimental
-MediaStreamSpeech status=experimental
-MediaQueryShape status=experimental
-MediaStreamTrackContentHint status=experimental
-MemoryInfoInWorkers status=experimental
-// This is enabled by default on Windows only. The only part that's
-// "experimental" is the support on other platforms.
-MiddleClickAutoscroll status=experimental
-MobileLayoutTheme
-ModuleScripts status=test
-NavigatorContentUtils
-WebNFC status=experimental
-NetworkInformation status=stable
-NetInfoDownlinkMax status=stable
-NotificationConstructor status=stable
-NotificationBadge status=stable
-NotificationContentImage status=stable
-NotificationInlineReplies status=experimental
-Notifications status=stable
-OnDeviceChange status=stable
-OrientationEvent
-OriginTrials status=stable
-// Define a sample API for testing integration with the Origin Trials Framework.
-// The sample API is used in both unit and layout tests for the Origin Trials
-// Framework. Do not change this flag to stable, as it exists solely to generate
-// code used by the sample API implementation.
-OriginTrialsSampleAPI origin_trial_feature_name=Frobulate
-// For simulating Android's overlay fullscreen video in layout tests on Linux.
-ForceOverlayFullscreenVideo
-OverlayScrollbars
-PagePopup status=stable
-PaintUnderInvalidationChecking settable_from_internals=True
-PassiveDocumentEventListeners status=stable
-PassPaintVisualRectToCompositor
-PaymentApp status=experimental
-PaymentDetailsError status=stable
-PaymentDetailsModifierData status=experimental
-// PaymentRequest is enabled by default on Android
-PaymentRequest status=experimental
-PaymentRequestBasicCard status=stable
-PaymentRequestPayerName status=stable
-PerformanceObserver status=stable
-PermissionDelegation status=test
-Permissions status=stable
-PermissionsRequestRevoke status=experimental
-PointerEvent status=stable
-PreciseMemoryInfo
-PreferredImageRasterBounds settable_from_internals=True
-// This feature is deprecated and we are evangelizing affected sites.
-// See https://crbug.com/346236 for current status.
-PrefixedVideoFullscreen status=stable
-Presentation status=stable
-PresentationReceiver status=test
-PushMessaging status=stable
-QuotaPromise status=experimental
-ReducedReferrerGranularity
-RemotePlayback status=stable
-RenderingPipelineThrottling status=stable
-RenderingPipelineThrottlingLoadingIframes status=stable
-RenderUnicodeControlCharacters status=stable
-ResizeObserver status=experimental
-// Handles frame scrolling via the root PaintLayer instead of the FrameView.
-// crbug.com/417782 tracks enabling this by default.
-RootLayerScrolling
-ScriptedSpeech status=stable
-// Scrolls to compensate for layout movements (bit.ly/scroll-anchoring).
-ScrollAnchoring status=experimental, settable_from_internals=True
-// Implements documentElement.scrollTop/Left and bodyElement.scrollTop/Left
-// as per the spec, matching other Web engines.
-ScrollTopLeftInterop status=experimental
-Sensor status=experimental
-ServiceWorkerNavigationPreload origin_trial_feature_name=ServiceWorkerNavigationPreload
-SetRootScroller status=experimental, origin_trial_feature_name=RootScroller
-ShadowPiercingDescendantCombinator status=experimental
-ShapeDetection status=experimental
-SharedArrayBuffer
-SharedWorker status=stable
-SlimmingPaintInvalidation implied_by=SlimmingPaintV2, status=stable
-SlimmingPaintV2
-SlimmingPaintStrictCullRectClipping
-// Used as argument in attribute of stable-release functions/interfaces where
-// a runtime-enabled feature name is required for correct IDL syntax.
-// This is a global flag; do not change its status.
-StableBlinkFeatures status=stable
-StackedCSSPropertyAnimations status=experimental
-StyleSharing status=stable
-// Do not turn this flag into stable, because many interfaces that should not
-// be shipped would be enabled. Instead, remove the flag from the shipping
-// interface.
-SpeculativeLaunchServiceWorker
-StorageEstimate status=experimental
-Suborigins status=experimental
-TimerThrottlingForBackgroundTabs status=stable
-TimerThrottlingForHiddenFrames status=stable
-TopNavWithUserActivationInSandbox status=experimental
-// Many websites disable mouse support when touch APIs are available.  We'd
-// like to enable this always but can't until more websites fix this bug.
-// Chromium sets this conditionally (eg. based on the presence of a
-// touchscreen) in ApplyWebPreferences. "Touch events" themselves are always
-// enabled since they're a feature always supported by Chrome.
-TouchEventFeatureDetection status=stable
-TrueColorRendering status=experimental
-TrustedEventsDefaultAction status=stable
-WebAnimationsAPI status=experimental
-WebAnimationsSVG status=experimental
-WebAssemblySerialization status=test
-// WebBluetooth is enabled by default on Android, ChromeOS and Mac.
-WebBluetooth status=experimental
-WebGLDraftExtensions status=experimental
-WebGLImageChromium
-WebUSB status=experimental, origin_trial_feature_name=WebUSB2
-WebVR status=test, origin_trial_feature_name=WebVR
-WebVTTRegions status=experimental
-V8BasedStructuredClone status=stable
-V8IdleTasks
-VideoFullscreenOrientationLock
-VisibilityChangeOnUnload status=stable
-XSLT status=stable
-smil status=stable
-ScrollCustomization
-AutoplayMutedVideos settable_from_internals=True
-VisualViewportAPI status=experimental
-WakeLock status=experimental
-WebAuth status=experimental
-WebFontsCacheAwareTimeoutAdaptation status=experimental
-WebFontsInterventionV2With2G
-WebFontsInterventionV2With3G
-WebFontsInterventionV2WithSlow2G
-WebFontsInterventionTrigger
-WebShare status=experimental, origin_trial_feature_name=WebShare, origin_trial_os=android
-Worklet status=experimental
-LazyParseCSS status=experimental
-SendBeaconThrowForBlobWithNonSimpleType status=experimental
-PerformanceNavigationTiming2 status=stable
-BackgroundVideoTrackOptimization status=stable
-PerformancePaintTiming status=test
-HideNonceContentAttribute status=experimental
-UnclosedFormControlIsInvalid status=experimental
-RestrictCompleteURLCharacterSet status=experimental
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
new file mode 100644
index 0000000..f8788f4
--- /dev/null
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -0,0 +1,1008 @@
+{
+  // http://dev.chromium.org/blink/runtime-enabled-features
+  //
+  // This list is used to generate RuntimeEnabledFeatures.h/cpp which contains
+  // a class that stores static enablers for all experimental features.
+
+  parameters: {
+    // Each feature can be assigned a "status":
+    // status=stable -> Enable this in all Blink configurations.  We are committed to these APIs indefinitely.
+    // status=experimental -> In-progress features, Web Developers might play with, but are not on by default in stable.
+    // status=test -> Enabled in ContentShell for testing, otherwise off.
+    // Features without a status are not enabled anywhere by default.
+    status: {
+      valid_values: ["stable", "experimental", "test"],
+    },
+
+    // "implied_by" or "depends_on" specifies relationship to other features:
+    // implied_by: ["feature1","feature2",...] -> The feature is automatically enabled if any implied_by features is enabled;
+    // depends_on: ["feature1","feature2",...] -> The feature is enabled only if all depends_on features are enabled.
+    // Only one of "implied_by" and "depends_on" can be specified.
+    //
+    // "stable" features listed here should be rare, as anything which we've shipped stable
+    // can have its runtime flag removed soon after.
+    implied_by: {
+      default: [],
+      valid_type: "list",
+    },
+    depends_on: {
+      default: [],
+      valid_type: "list",
+    },
+
+    // origin_trial_feature_name: "FEATURE_NAME" is used to integrate the feature with
+    // the Origin Trials framework. The framework allows the feature to be enabled
+    // at runtime on a per-page basis through a signed token for the corresponding
+    // feature name. Declaring the origin_trial_feature_name will cause a static
+    // method to be generated in OriginTrials.h/cpp. This static method allows the
+    // feature implementation to check if it is enabled for the current context.
+    origin_trial_feature_name: {
+    },
+    origin_trial_os: {
+      default: [],
+      valid_type: "list",
+    },
+
+    // settable_from_internals specifies whether a feature can be set from internals.runtimeFlags, with the default
+    // being false.
+    settable_from_internals: {
+      valid_type: "bool",
+    },
+
+    // Set to true to have customised {feature}Enabled() method implementation.
+    custom: {
+      valid_type: "bool",
+    },
+
+    // Feature policy IDL extended attribute (see crrev.com/2247923004).
+    feature_policy: {
+    },
+  },
+
+  data: [
+    {
+      name: "Accelerated2dCanvas",
+      settable_from_internals: true,
+      status: "stable",
+    },
+    {
+      name: "AudioOutputDevices",
+      status: "stable",
+    },
+    {
+      name: "AudioVideoTracks",
+      status: "experimental",
+    },
+    {
+      name: "AudioWorklet",
+      status: "experimental",
+    },
+    {
+      name: "Auxclick",
+      status: "stable",
+    },
+    {
+      name: "CoalescedEvents",
+      status: "stable",
+    },
+    {
+      name: "BackgroundSync",
+      status: "stable",
+    },
+    {
+      name: "BackspaceDefaultHandler",
+      status: "test",
+    },
+    {
+      name: "BroadcastChannel",
+      status: "stable",
+    },
+    {
+      name: "Budget",
+      status: "experimental",
+    },
+    {
+      name: "Canvas2dFixedRenderingMode",
+      status: "test",
+    },
+    {
+      name: "EnableCanvas2dDynamicRenderingModeSwitching",
+      status: "experimental",
+    },
+    {
+      name: "CanMakePayment",
+      status: "stable",
+    },
+    {
+      name: "Canvas2dImageChromium",
+      status: "experimental",
+    },
+    {
+      name: "ClientHints",
+      status: "stable",
+    },
+    {
+      name: "CompositeOpaqueFixedPosition",
+      settable_from_internals: true,
+      status: "test",
+    },
+    {
+      name: "CompositeOpaqueScrollers",
+      settable_from_internals: true,
+      status: "stable",
+    },
+    {
+      name: "ColorCorrectRendering",
+      status: "experimental",
+    },
+    {
+      name: "ColorCorrectRenderingDefaultMode",
+      status: "experimental",
+    },
+    {
+      name: "CompositedSelectionUpdate",
+    },
+    {
+      name: "CompositorWorker",
+      status: "experimental",
+    },
+    {
+      name: "ContextMenu",
+      status: "test",
+    },
+    {
+      name: "CorsRFC1918",
+      status: "test",
+    },
+    {
+      name: "CredentialManager",
+      status: "stable",
+    },
+    {
+      name: "CSS3Text",
+      status: "experimental",
+    },
+    {
+      name: "CSS3TextDecorations",
+      status: "stable",
+    },
+    {
+      name: "CSSApplyAtRules",
+      status: "experimental",
+    },
+    {
+      name: "CSSAdditiveAnimations",
+      depends_on: ["StackedCSSPropertyAnimations"],
+      status: "experimental",
+    },
+    {
+      name: "CSSBackdropFilter",
+      status: "experimental",
+    },
+    {
+      name: "CSSHexAlphaColor",
+      status: "experimental",
+    },
+    {
+      name: "CSSContainment",
+      status: "stable",
+    },
+    {
+      name: "CSSFontDisplay",
+      status: "experimental",
+    },
+    {
+      name: "CSSFontSizeAdjust",
+      status: "experimental",
+    },
+    {
+      name: "CSSGridLayout",
+      settable_from_internals: true,
+      status: "stable",
+    },
+    {
+      name: "CSSDisplayContents",
+      status: "experimental",
+    },
+    {
+      name: "CSSHyphens",
+      status: "stable",
+    },
+    {
+      name: "CSSInBodyDoesNotBlockPaint",
+      status: "experimental",
+    },
+    {
+      name: "CSSIndependentTransformProperties",
+      status: "experimental",
+    },
+    {
+      name: "CSSMaskSourceType",
+      status: "experimental",
+    },
+    {
+      name: "CSSOMSmoothScroll",
+      status: "experimental",
+    },
+    {
+      name: "CSSOffsetPositionAnchor",
+      status: "experimental",
+    },
+    {
+      name: "CSSOffsetRotate",
+      status: "stable",
+    },
+    {
+      name: "CSSOffsetRotation",
+      status: "stable",
+    },
+    {
+      name: "CSSPaintAPI",
+      depends_on: ["Worklet"],
+      status: "experimental",
+    },
+    {
+      name: "CSSPaintAPIArguments",
+      depends_on: ["CSSPaintAPI"],
+      status: "experimental",
+    },
+    {
+      name: "CSSSnapSize",
+      status: "experimental",
+    },
+    {
+      name: "CSSStickyPosition",
+      status: "stable",
+    },
+    {
+      name: "CSSTouchActionPanDirections",
+      status: "stable",
+    },
+    {
+      name: "CSSTouchActionPinchZoom",
+      status: "stable",
+    },
+    {
+      name: "CSSTypedOM",
+      status: "experimental",
+    },
+    {
+      name: "CSSVariableFonts",
+      status: "experimental",
+    },
+    {
+      name: "CSSVariables2",
+      status: "experimental",
+    },
+    {
+      name: "CSSViewport",
+      status: "experimental",
+    },
+    {
+      name: "CSSScrollSnapPoints",
+      status: "test",
+    },
+    {
+      name: "CustomElementsBuiltin",
+      status: "test",
+    },
+    {
+      name: "CustomElementsV1",
+      status: "stable",
+    },
+    {
+      name: "CustomSchemeHandler",
+      depends_on: ["NavigatorContentUtils"],
+      status: "experimental",
+    },
+    {
+      name: "Database",
+      status: "stable",
+    },
+    {
+      name: "DecodeToYUV",
+      status: "experimental",
+    },
+    {
+      name: "DesktopCaptureDisableLocalEchoControl",
+      status: "experimental",
+    },
+    {
+      name: "DeviceLight",
+      status: "experimental",
+    },
+    {
+      name: "DisplayList2dCanvas",
+      status: "stable",
+    },
+    {
+      name: "DocumentCookie",
+    },
+    {
+      name: "DocumentDomain",
+    },
+    {
+      name: "DocumentWrite",
+    },
+    {
+      name: "DocumentWriteEvaluator",
+    },
+    {
+      name: "DOMConvenienceAPI",
+      status: "stable",
+    },
+    {
+      name: "DurableStorage",
+      status: "stable",
+    },
+    {
+      name: "ExpensiveBackgroundTimerThrottling",
+      status: "experimental",
+    },
+    {
+      name: "FasterLocationReload",
+      status: "experimental",
+    },
+    {
+      name: "FontCacheScaling",
+      status: "test",
+    },
+    {
+      name: "ForceDisplayList2dCanvas",
+    },
+    // See crbug.com/585250.
+    {
+      name: "ForceDisable2dCanvasCopyOnWrite",
+    },
+    {
+      name: "EmbedderCSPEnforcement",
+      status: "experimental",
+    },
+    {
+      name: "ExecCommandInJavaScript",
+      status: "test",
+    },
+    {
+      name: "ComputedAccessibilityInfo",
+      status: "experimental",
+    },
+    {
+      name: "ExperimentalCanvasFeatures",
+      status: "test",
+    },
+    {
+      name: "ExperimentalContentSecurityPolicyFeatures",
+      status: "experimental",
+    },
+    {
+      name: "ExperimentalV8Extras",
+      status: "experimental",
+    },
+    {
+      name: "FastMobileScrolling",
+    },
+    {
+      name: "FeaturePolicy",
+      status: "experimental",
+    },
+    {
+      name: "FileAPIBlobClose",
+      status: "experimental",
+    },
+    {
+      name: "FileSystem",
+      status: "stable",
+    },
+    {
+      name: "ForeignFetch",
+      origin_trial_feature_name: "ForeignFetch",
+      status: "experimental",
+    },
+    {
+      name: "FramebustingNeedsSameOriginOrUserGesture",
+      settable_from_internals: true,
+      status: "stable",
+    },
+    {
+      name: "FullscreenUnprefixed",
+      settable_from_internals: true,
+      status: "test",
+    },
+    {
+      name: "FrameTimingSupport",
+      status: "experimental",
+    },
+    {
+      name: "GamepadExtensions",
+      origin_trial_feature_name: "WebVR",
+      status: "test",
+    },
+    {
+      name: "GeometryInterfaces",
+      implied_by: ["CompositorWorker"],
+      status: "experimental",
+    },
+    {
+      name: "GetUserMedia",
+      status: "stable",
+    },
+    {
+      name: "GlobalCacheStorage",
+      status: "stable",
+    },
+    {
+      name: "HeapCompaction",
+      status: "stable",
+    },
+    {
+      name: "IDBObserver",
+      status: "experimental",
+    },
+    {
+      name: "IdleTimeSpellChecking",
+    },
+    {
+      name: "ImageCapture",
+      origin_trial_feature_name: "ImageCapture",
+      status: "experimental",
+    },
+    {
+      name: "ImageOrientation",
+      status: "test",
+    },
+    {
+      name: "IndexedDBExperimental",
+      status: "experimental",
+    },
+    {
+      name: "InertTopControls",
+      status: "stable",
+    },
+    {
+      name: "InputEvent",
+      status: "experimental",
+    },
+    {
+      name: "InputModeAttribute",
+      status: "experimental",
+    },
+    {
+      name: "InputMultipleFieldsUI",
+      status: "stable",
+    },
+    {
+      name: "InstalledApp",
+      status: "experimental",
+    },
+    {
+      name: "IntersectionObserver",
+      status: "stable",
+    },
+    {
+      name: "LangAttributeAwareFormControlUI",
+    },
+    {
+      name: "LayoutNG",
+    },
+    {
+      name: "LayoutNGInline",
+    },
+    {
+      name: "LinkServiceWorker",
+      origin_trial_feature_name: "ForeignFetch",
+      status: "experimental",
+    },
+    {
+      name: "LongTaskObserver",
+      origin_trial_feature_name: "LongTaskObserver",
+      status: "experimental",
+    },
+    {
+      name: "FractionalScrollOffsets",
+    },
+    {
+      name: "LoadingWithMojo",
+    },
+    {
+      name: "MediaCapture",
+    },
+    {
+      name: "MediaCaptureDepth",
+      status: "experimental",
+    },
+    {
+      name: "MediaCaptureFromCanvas",
+      status: "stable",
+    },
+    {
+      name: "MediaCaptureFromVideo",
+      status: "experimental",
+    },
+    {
+      name: "MediaConstraints",
+      status: "stable",
+    },
+    {
+      name: "MediaDocumentDownloadButton",
+    },
+    {
+      name: "MediaGetSettings",
+      status: "experimental",
+    },
+    // MediaSession is enabled by default on Android only.
+    // TODO(rbyers): Add parameter to specify platform.
+    {
+      name: "MediaSession",
+      status: "test",
+    },
+    {
+      name: "MediaSourceExperimental",
+      status: "experimental",
+    },
+    {
+      name: "MediaSourceNewAbortAndDuration",
+      status: "experimental",
+    },
+    {
+      name: "MediaStreamSpeech",
+      status: "experimental",
+    },
+    {
+      name: "MediaQueryShape",
+      status: "experimental",
+    },
+    {
+      name: "MediaStreamTrackContentHint",
+      status: "experimental",
+    },
+    {
+      name: "MemoryInfoInWorkers",
+      status: "experimental",
+    },
+    // This is enabled by default on Windows only. The only part that's
+    // "experimental" is the support on other platforms.
+    {
+      name: "MiddleClickAutoscroll",
+      status: "experimental",
+    },
+    {
+      name: "MobileLayoutTheme",
+    },
+    {
+      name: "ModuleScripts",
+      status: "test",
+    },
+    {
+      name: "MojoJS",
+      status: "test",
+    },
+    {
+      name: "NavigatorContentUtils",
+    },
+    {
+      name: "WebNFC",
+      status: "experimental",
+    },
+    {
+      name: "NetworkInformation",
+      status: "stable",
+    },
+    {
+      name: "NetInfoDownlinkMax",
+      status: "stable",
+    },
+    {
+      name: "NotificationConstructor",
+      status: "stable",
+    },
+    {
+      name: "NotificationBadge",
+      status: "stable",
+    },
+    {
+      name: "NotificationContentImage",
+      status: "stable",
+    },
+    {
+      name: "NotificationInlineReplies",
+      status: "experimental",
+    },
+    {
+      name: "Notifications",
+      status: "stable",
+    },
+    {
+      name: "OnDeviceChange",
+      status: "stable",
+    },
+    {
+      name: "OrientationEvent",
+    },
+    {
+      name: "OriginTrials",
+      status: "stable",
+    },
+    // Define a sample API for testing integration with the Origin Trials Framework.
+    // The sample API is used in both unit and layout tests for the Origin Trials
+    // Framework. Do not change this flag to stable, as it exists solely to generate
+    // code used by the sample API implementation.
+    {
+      name: "OriginTrialsSampleAPI",
+      origin_trial_feature_name: "Frobulate",
+    },
+    // For simulating Android's overlay fullscreen video in layout tests on Linux.
+    {
+      name: "ForceOverlayFullscreenVideo",
+    },
+    {
+      name: "OverlayScrollbars",
+    },
+    {
+      name: "PagePopup",
+      status: "stable",
+    },
+    {
+      name: "PaintUnderInvalidationChecking",
+      settable_from_internals: true,
+    },
+    {
+      name: "PassiveDocumentEventListeners",
+      status: "stable",
+    },
+    {
+      name: "PassPaintVisualRectToCompositor",
+    },
+    {
+      name: "PaymentApp",
+      status: "experimental",
+    },
+    {
+      name: "PaymentDetailsError",
+      status: "stable",
+    },
+    {
+      name: "PaymentDetailsModifierData",
+      status: "experimental",
+    },
+    // PaymentRequest is enabled by default on Android
+    {
+      name: "PaymentRequest",
+      status: "experimental",
+    },
+    {
+      name: "PaymentRequestBasicCard",
+      status: "stable",
+    },
+    {
+      name: "PaymentRequestPayerName",
+      status: "stable",
+    },
+    {
+      name: "PerformanceObserver",
+      status: "stable",
+    },
+    {
+      name: "PermissionDelegation",
+      status: "test",
+    },
+    {
+      name: "Permissions",
+      status: "stable",
+    },
+    {
+      name: "PermissionsRequestRevoke",
+      status: "experimental",
+    },
+    {
+      name: "PointerEvent",
+      status: "stable",
+    },
+    {
+      name: "PreciseMemoryInfo",
+    },
+    {
+      name: "PreferredImageRasterBounds",
+      settable_from_internals: true,
+    },
+    // This feature is deprecated and we are evangelizing affected sites.
+    // See https://crbug.com/346236 for current status.
+    {
+      name: "PrefixedVideoFullscreen",
+      status: "stable",
+    },
+    {
+      name: "Presentation",
+      status: "stable",
+    },
+    {
+      name: "PresentationReceiver",
+      status: "test",
+    },
+    {
+      name: "PushMessaging",
+      status: "stable",
+    },
+    {
+      name: "QuotaPromise",
+      status: "experimental",
+    },
+    {
+      name: "ReducedReferrerGranularity",
+    },
+    {
+      name: "RemotePlayback",
+      status: "stable",
+    },
+    {
+      name: "RenderingPipelineThrottling",
+      status: "stable",
+    },
+    {
+      name: "RenderingPipelineThrottlingLoadingIframes",
+      status: "stable",
+    },
+    {
+      name: "RenderUnicodeControlCharacters",
+      status: "stable",
+    },
+    {
+      name: "ResizeObserver",
+      status: "experimental",
+    },
+    // Handles frame scrolling via the root PaintLayer instead of the FrameView.
+    // crbug.com/417782 tracks enabling this by default.
+    {
+      name: "RootLayerScrolling",
+    },
+    {
+      name: "ScriptedSpeech",
+      status: "stable",
+    },
+    // Scrolls to compensate for layout movements (bit.ly/scroll-anchoring).
+    {
+      name: "ScrollAnchoring",
+      settable_from_internals: true,
+      status: "experimental",
+    },
+    // Implements documentElement.scrollTop/Left and bodyElement.scrollTop/Left
+    // as per the spec, matching other Web engines.
+    {
+      name: "ScrollTopLeftInterop",
+      status: "experimental",
+    },
+    {
+      name: "Sensor",
+      status: "experimental",
+    },
+    {
+      name: "ServiceWorkerNavigationPreload",
+      origin_trial_feature_name: "ServiceWorkerNavigationPreload",
+    },
+    {
+      name: "SetRootScroller",
+      origin_trial_feature_name: "RootScroller",
+      status: "experimental",
+    },
+    {
+      name: "ShadowPiercingDescendantCombinator",
+      status: "experimental",
+    },
+    {
+      name: "ShapeDetection",
+      status: "experimental",
+    },
+    {
+      name: "SharedArrayBuffer",
+    },
+    {
+      name: "SharedWorker",
+      status: "stable",
+    },
+    {
+      name: "SlimmingPaintInvalidation",
+      implied_by: ["SlimmingPaintV2"],
+      status: "stable",
+    },
+    {
+      name: "SlimmingPaintV2",
+    },
+    {
+      name: "SlimmingPaintStrictCullRectClipping",
+    },
+    // Used as argument in attribute of stable-release functions/interfaces where
+    // a runtime-enabled feature name is required for correct IDL syntax.
+    // This is a global flag; do not change its status.
+    {
+      name: "StableBlinkFeatures",
+      status: "stable",
+    },
+    {
+      name: "StackedCSSPropertyAnimations",
+      status: "experimental",
+    },
+    {
+      name: "StyleSharing",
+      status: "stable",
+    },
+    // Do not turn this flag into stable, because many interfaces that should not
+    // be shipped would be enabled. Instead, remove the flag from the shipping
+    // interface.
+    {
+      name: "SpeculativeLaunchServiceWorker",
+    },
+    {
+      name: "StorageEstimate",
+      status: "experimental",
+    },
+    {
+      name: "Suborigins",
+      status: "experimental",
+    },
+    {
+      name: "TimerThrottlingForBackgroundTabs",
+      status: "stable",
+    },
+    {
+      name: "TimerThrottlingForHiddenFrames",
+      status: "stable",
+    },
+    {
+      name: "TopNavWithUserActivationInSandbox",
+      status: "experimental",
+    },
+    // Many websites disable mouse support when touch APIs are available.  We'd
+    // like to enable this always but can't until more websites fix this bug.
+    // Chromium sets this conditionally (eg. based on the presence of a
+    // touchscreen) in ApplyWebPreferences. "Touch events" themselves are always
+    // enabled since they're a feature always supported by Chrome.
+    {
+      name: "TouchEventFeatureDetection",
+      status: "stable",
+    },
+    {
+      name: "TrueColorRendering",
+      status: "experimental",
+    },
+    {
+      name: "TrustedEventsDefaultAction",
+      status: "stable",
+    },
+    {
+      name: "WebAnimationsAPI",
+      status: "experimental",
+    },
+    {
+      name: "WebAnimationsSVG",
+      status: "experimental",
+    },
+    {
+      name: "WebAssemblySerialization",
+      status: "test",
+    },
+    // WebBluetooth is enabled by default on Android, ChromeOS and Mac.
+    {
+      name: "WebBluetooth",
+      status: "experimental",
+    },
+    {
+      name: "WebGLDraftExtensions",
+      status: "experimental",
+    },
+    {
+      name: "WebGLImageChromium",
+    },
+    {
+      name: "WebUSB",
+      origin_trial_feature_name: "WebUSB2",
+      status: "experimental",
+    },
+    {
+      name: "WebVR",
+      origin_trial_feature_name: "WebVR",
+      status: "test",
+    },
+    {
+      name: "WebVTTRegions",
+      status: "experimental",
+    },
+    {
+      name: "V8BasedStructuredClone",
+      status: "stable",
+    },
+    {
+      name: "V8IdleTasks",
+    },
+    {
+      name: "VideoFullscreenOrientationLock",
+    },
+    {
+      name: "VisibilityChangeOnUnload",
+      status: "stable",
+    },
+    {
+      name: "XSLT",
+      status: "stable",
+    },
+    {
+      name: "smil",
+      status: "stable",
+    },
+    {
+      name: "ScrollCustomization",
+    },
+    {
+      name: "AutoplayMutedVideos",
+      settable_from_internals: true,
+    },
+    {
+      name: "VisualViewportAPI",
+      status: "experimental",
+    },
+    {
+      name: "WakeLock",
+      status: "experimental",
+    },
+    {
+      name: "WebAuth",
+      status: "experimental",
+    },
+    {
+      name: "WebFontsCacheAwareTimeoutAdaptation",
+      status: "experimental",
+    },
+    {
+      name: "WebFontsInterventionV2With2G",
+    },
+    {
+      name: "WebFontsInterventionV2With3G",
+    },
+    {
+      name: "WebFontsInterventionV2WithSlow2G",
+    },
+    {
+      name: "WebFontsInterventionTrigger",
+    },
+    {
+      name: "WebShare",
+      origin_trial_feature_name: "WebShare",
+      origin_trial_os: ["android"],
+      status: "experimental",
+    },
+    {
+      name: "Worklet",
+      status: "experimental",
+    },
+    {
+      name: "LazyParseCSS",
+      status: "experimental",
+    },
+    {
+      name: "SendBeaconThrowForBlobWithNonSimpleType",
+      status: "experimental",
+    },
+    {
+      name: "PerformanceNavigationTiming2",
+      status: "stable",
+    },
+    {
+      name: "BackgroundVideoTrackOptimization",
+      status: "stable",
+    },
+    {
+      name: "PerformancePaintTiming",
+      status: "test",
+    },
+    {
+      name: "HideNonceContentAttribute",
+      status: "experimental",
+    },
+    {
+      name: "UnclosedFormControlIsInvalid",
+      status: "experimental",
+    },
+    {
+      name: "RestrictCompleteURLCharacterSet",
+      status: "experimental",
+    },
+  ],
+}
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
index 70ca828e..dcf0ea58 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
@@ -28,14 +28,14 @@
 
 #include "platform/audio/AudioDestination.h"
 
-#include <memory>
 #include "platform/Histogram.h"
+#include "platform/audio/AudioPullFIFO.h"
 #include "platform/audio/AudioUtilities.h"
-#include "platform/audio/PushPullFIFO.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebSecurityOrigin.h"
 #include "wtf/PtrUtil.h"
+#include <memory>
 
 namespace blink {
 
@@ -67,8 +67,6 @@
       m_outputBus(AudioBus::create(numberOfOutputChannels,
                                    AudioUtilities::kRenderQuantumFrames,
                                    false)),
-      m_renderBus(AudioBus::create(numberOfOutputChannels,
-                                   AudioUtilities::kRenderQuantumFrames)),
       m_framesElapsed(0) {
   // Calculate the optimum buffer size first.
   if (calculateBufferSize()) {
@@ -82,8 +80,9 @@
     DCHECK(m_webAudioDevice);
 
     // Create a FIFO.
-    m_fifo =
-        WTF::wrapUnique(new PushPullFIFO(numberOfOutputChannels, kFIFOSize));
+    m_fifo = WTF::wrapUnique(
+        new AudioPullFIFO(*this, numberOfOutputChannels, kFIFOSize,
+                          AudioUtilities::kRenderQuantumFrames));
   } else {
     NOTREACHED();
   }
@@ -98,8 +97,13 @@
                               double delay,
                               double delayTimestamp,
                               size_t priorFramesSkipped) {
-  CHECK_EQ(destinationData.size(), m_numberOfOutputChannels);
-  CHECK_EQ(numberOfFrames, m_callbackBufferSize);
+  DCHECK_EQ(destinationData.size(), m_numberOfOutputChannels);
+  if (destinationData.size() != m_numberOfOutputChannels)
+    return;
+
+  DCHECK_EQ(numberOfFrames, m_callbackBufferSize);
+  if (numberOfFrames != m_callbackBufferSize)
+    return;
 
   m_framesElapsed -= std::min(m_framesElapsed, priorFramesSkipped);
   double outputPosition =
@@ -112,43 +116,34 @@
   // FIFO.
   for (unsigned i = 0; i < m_numberOfOutputChannels; ++i)
     m_outputBus->setChannelMemory(i, destinationData[i], numberOfFrames);
-
-  // Number of frames to render via WebAudio graph. |framesToRender > 0| means
-  // the frames in FIFO is not enough to fulfill the requested frames from the
-  // audio device.
-  size_t framesToRender = numberOfFrames > m_fifo->framesAvailable()
-                              ? numberOfFrames - m_fifo->framesAvailable()
-                              : 0;
-
-  for (size_t pushedFrames = 0; pushedFrames < framesToRender;
-       pushedFrames += AudioUtilities::kRenderQuantumFrames) {
-    // If platform buffer is more than two times longer than |framesToProcess|
-    // we do not want output position to get stuck so we promote it
-    // using the elapsed time from the moment it was initially obtained.
-    if (m_callbackBufferSize > AudioUtilities::kRenderQuantumFrames * 2) {
-      double delta =
-          (base::TimeTicks::Now() - m_outputPositionReceivedTimestamp)
-              .InSecondsF();
-      m_outputPosition.position += delta;
-      m_outputPosition.timestamp += delta;
-    }
-
-    // Some implementations give only rough estimation of |delay| so
-    // we might have negative estimation |outputPosition| value.
-    if (m_outputPosition.position < 0.0)
-      m_outputPosition.position = 0.0;
-
-    // Process WebAudio graph and push the rendered output to FIFO.
-    m_callback.render(nullptr, m_renderBus.get(),
-                      AudioUtilities::kRenderQuantumFrames, m_outputPosition);
-    m_fifo->push(m_renderBus.get());
-  }
-
-  m_fifo->pull(m_outputBus.get(), numberOfFrames);
+  m_fifo->consume(m_outputBus.get(), numberOfFrames);
 
   m_framesElapsed += numberOfFrames;
 }
 
+void AudioDestination::provideInput(AudioBus* outputBus,
+                                    size_t framesToProcess) {
+  AudioIOPosition outputPosition = m_outputPosition;
+
+  // If platform buffer is more than two times longer than |framesToProcess|
+  // we do not want output position to get stuck so we promote it
+  // using the elapsed time from the moment it was initially obtained.
+  if (m_callbackBufferSize > framesToProcess * 2) {
+    double delta = (base::TimeTicks::Now() - m_outputPositionReceivedTimestamp)
+                       .InSecondsF();
+    outputPosition.position += delta;
+    outputPosition.timestamp += delta;
+  }
+
+  // Some implementations give only rough estimation of |delay| so
+  // we might have negative estimation |outputPosition| value.
+  if (outputPosition.position < 0.0)
+    outputPosition.position = 0.0;
+
+  // To fill the FIFO, start the render call chain of the destination node.
+  m_callback.render(nullptr, outputBus, framesToProcess, outputPosition);
+}
+
 void AudioDestination::start() {
   if (m_webAudioDevice && !m_isPlaying) {
     m_webAudioDevice->start();
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.h b/third_party/WebKit/Source/platform/audio/AudioDestination.h
index f5c699a1..d0e35b8 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.h
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.h
@@ -31,6 +31,7 @@
 
 #include "platform/audio/AudioBus.h"
 #include "platform/audio/AudioIOCallback.h"
+#include "platform/audio/AudioSourceProvider.h"
 #include "public/platform/WebAudioDevice.h"
 #include "public/platform/WebVector.h"
 #include "wtf/Allocator.h"
@@ -40,14 +41,15 @@
 
 namespace blink {
 
-class PushPullFIFO;
+class AudioPullFIFO;
 class SecurityOrigin;
 
 // The AudioDestination class is an audio sink interface between the media
 // renderer and the Blink's WebAudio module. It has a FIFO to adapt the
 // different processing block sizes of WebAudio renderer and actual hardware
 // audio callback.
-class PLATFORM_EXPORT AudioDestination : public WebAudioDevice::RenderCallback {
+class PLATFORM_EXPORT AudioDestination : public WebAudioDevice::RenderCallback,
+                                         public AudioSourceProvider {
   USING_FAST_MALLOC(AudioDestination);
   WTF_MAKE_NONCOPYABLE(AudioDestination);
 
@@ -72,6 +74,9 @@
               double delayTimestamp,
               size_t priorFramesSkipped) override;
 
+  // AudioSourceProvider (FIFO)
+  void provideInput(AudioBus* outputBus, size_t framesToProcess) override;
+
   virtual void start();
   virtual void stop();
 
@@ -93,15 +98,8 @@
   // The render callback function of WebAudio engine. (i.e. DestinationNode)
   AudioIOCallback& m_callback;
 
-  // To pass the data from FIFO to the audio device callback.
   RefPtr<AudioBus> m_outputBus;
-
-  // To push the rendered result from WebAudio graph into the FIFO.
-  RefPtr<AudioBus> m_renderBus;
-
-  // Resolves the buffer size mismatch between the WebAudio engine and
-  // the callback function from the actual audio device.
-  std::unique_ptr<PushPullFIFO> m_fifo;
+  std::unique_ptr<AudioPullFIFO> m_fifo;
 
   size_t m_framesElapsed;
   AudioIOPosition m_outputPosition;
diff --git a/third_party/WebKit/Source/platform/audio/AudioFIFO.cpp b/third_party/WebKit/Source/platform/audio/AudioFIFO.cpp
new file mode 100644
index 0000000..c35ce14
--- /dev/null
+++ b/third_party/WebKit/Source/platform/audio/AudioFIFO.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform/audio/AudioFIFO.h"
+
+namespace blink {
+
+AudioFIFO::AudioFIFO(unsigned numberOfChannels, size_t fifoLength)
+    : m_fifoAudioBus(AudioBus::create(numberOfChannels, fifoLength)),
+      m_fifoLength(fifoLength),
+      m_framesInFifo(0),
+      m_readIndex(0),
+      m_writeIndex(0) {}
+
+void AudioFIFO::consume(AudioBus* destination, size_t framesToConsume) {
+  bool isGood = destination && (framesToConsume <= m_fifoLength) &&
+                (framesToConsume <= m_framesInFifo) &&
+                (destination->length() >= framesToConsume);
+  ASSERT(isGood);
+  if (!isGood)
+    return;
+
+  // Copy the requested number of samples to the destination.
+
+  size_t part1Length;
+  size_t part2Length;
+  findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length);
+
+  size_t numberOfChannels = m_fifoAudioBus->numberOfChannels();
+
+  for (size_t channelIndex = 0; channelIndex < numberOfChannels;
+       ++channelIndex) {
+    float* destinationData = destination->channel(channelIndex)->mutableData();
+    const float* sourceData = m_fifoAudioBus->channel(channelIndex)->data();
+
+    bool isCopyGood = ((m_readIndex < m_fifoLength) &&
+                       (m_readIndex + part1Length) <= m_fifoLength &&
+                       (part1Length <= destination->length()) &&
+                       (part1Length + part2Length) <= destination->length());
+    ASSERT(isCopyGood);
+    if (!isCopyGood)
+      return;
+
+    memcpy(destinationData, sourceData + m_readIndex,
+           part1Length * sizeof(*sourceData));
+    // Handle wrap around of the FIFO, if needed.
+    if (part2Length)
+      memcpy(destinationData + part1Length, sourceData,
+             part2Length * sizeof(*sourceData));
+  }
+  m_readIndex = updateIndex(m_readIndex, framesToConsume);
+  ASSERT(m_framesInFifo >= framesToConsume);
+  m_framesInFifo -= framesToConsume;
+}
+
+void AudioFIFO::push(const AudioBus* sourceBus) {
+  // Copy the sourceBus into the FIFO buffer.
+
+  bool isGood =
+      sourceBus && (m_framesInFifo + sourceBus->length() <= m_fifoLength);
+  if (!isGood)
+    return;
+
+  size_t sourceLength = sourceBus->length();
+  size_t part1Length;
+  size_t part2Length;
+  findWrapLengths(m_writeIndex, sourceLength, part1Length, part2Length);
+
+  size_t numberOfChannels = m_fifoAudioBus->numberOfChannels();
+
+  for (size_t channelIndex = 0; channelIndex < numberOfChannels;
+       ++channelIndex) {
+    float* destination = m_fifoAudioBus->channel(channelIndex)->mutableData();
+    const float* source = sourceBus->channel(channelIndex)->data();
+
+    bool isCopyGood = ((m_writeIndex < m_fifoLength) &&
+                       (m_writeIndex + part1Length) <= m_fifoLength &&
+                       part2Length < m_fifoLength &&
+                       part1Length + part2Length <= sourceLength);
+    ASSERT(isCopyGood);
+    if (!isCopyGood)
+      return;
+
+    memcpy(destination + m_writeIndex, source,
+           part1Length * sizeof(*destination));
+
+    // Handle wrap around of the FIFO, if needed.
+    if (part2Length)
+      memcpy(destination, source + part1Length,
+             part2Length * sizeof(*destination));
+  }
+
+  m_framesInFifo += sourceLength;
+  ASSERT(m_framesInFifo <= m_fifoLength);
+  m_writeIndex = updateIndex(m_writeIndex, sourceLength);
+}
+
+void AudioFIFO::findWrapLengths(size_t index,
+                                size_t size,
+                                size_t& part1Length,
+                                size_t& part2Length) {
+  SECURITY_DCHECK(index < m_fifoLength && size <= m_fifoLength);
+  if (index < m_fifoLength && size <= m_fifoLength) {
+    if (index + size > m_fifoLength) {
+      // Need to wrap. Figure out the length of each piece.
+      part1Length = m_fifoLength - index;
+      part2Length = size - part1Length;
+    } else {
+      // No wrap needed.
+      part1Length = size;
+      part2Length = 0;
+    }
+  } else {
+    // Invalid values for index or size. Set the part lengths to zero so nothing
+    // is copied.
+    part1Length = 0;
+    part2Length = 0;
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/AudioFIFO.h b/third_party/WebKit/Source/platform/audio/AudioFIFO.h
new file mode 100644
index 0000000..ef66f92
--- /dev/null
+++ b/third_party/WebKit/Source/platform/audio/AudioFIFO.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AudioFIFO_h
+#define AudioFIFO_h
+
+#include "platform/audio/AudioBus.h"
+#include "wtf/Allocator.h"
+
+namespace blink {
+
+class AudioFIFO {
+  USING_FAST_MALLOC(AudioFIFO);
+  WTF_MAKE_NONCOPYABLE(AudioFIFO);
+
+ public:
+  // Create a FIFO large enough to hold |fifoLength| frames of data of
+  // |numberOfChannels| channels.
+  AudioFIFO(unsigned numberOfChannels, size_t fifoLength);
+
+  // Push the data from the bus into the FIFO.
+  void push(const AudioBus*);
+
+  // Consume |framesToConsume| frames of data from the FIFO and put them in
+  // |destination|. The corresponding frames are removed from the FIFO.
+  void consume(AudioBus* destination, size_t framesToConsume);
+
+  // Number of frames of data that are currently in the FIFO.
+  size_t framesInFifo() const { return m_framesInFifo; }
+
+ private:
+  // Update the FIFO index by the step, with appropriate wrapping around the
+  // endpoint.
+  int updateIndex(int index, int step) { return (index + step) % m_fifoLength; }
+
+  void findWrapLengths(size_t index,
+                       size_t providerSize,
+                       size_t& part1Length,
+                       size_t& part2Length);
+
+  // The FIFO itself. In reality, the FIFO is a circular buffer.
+  RefPtr<AudioBus> m_fifoAudioBus;
+
+  // The total available space in the FIFO.
+  size_t m_fifoLength;
+
+  // The number of actual elements in the FIFO
+  size_t m_framesInFifo;
+
+  // Where to start reading from the FIFO.
+  size_t m_readIndex;
+
+  // Where to start writing to the FIFO.
+  size_t m_writeIndex;
+};
+
+}  // namespace blink
+
+#endif  // AudioFIFO.h
diff --git a/third_party/WebKit/Source/platform/audio/AudioPullFIFO.cpp b/third_party/WebKit/Source/platform/audio/AudioPullFIFO.cpp
new file mode 100644
index 0000000..ca14cfa
--- /dev/null
+++ b/third_party/WebKit/Source/platform/audio/AudioPullFIFO.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform/audio/AudioPullFIFO.h"
+
+namespace blink {
+
+AudioPullFIFO::AudioPullFIFO(AudioSourceProvider& audioProvider,
+                             unsigned numberOfChannels,
+                             size_t fifoLength,
+                             size_t providerSize)
+    : m_provider(audioProvider),
+      m_fifo(numberOfChannels, fifoLength),
+      m_providerSize(providerSize),
+      m_tempBus(AudioBus::create(numberOfChannels, providerSize)) {}
+
+void AudioPullFIFO::consume(AudioBus* destination, size_t framesToConsume) {
+  if (!destination)
+    return;
+
+  if (framesToConsume > m_fifo.framesInFifo()) {
+    // We don't have enough data in the FIFO to fulfill the request. Ask for
+    // more data.
+    fillBuffer(framesToConsume - m_fifo.framesInFifo());
+  }
+
+  m_fifo.consume(destination, framesToConsume);
+}
+
+void AudioPullFIFO::fillBuffer(size_t numberOfFrames) {
+  // Keep asking the provider to give us data until we have received at least
+  // |numberOfFrames| of data. Stuff the data into the FIFO.
+  size_t framesProvided = 0;
+
+  while (framesProvided < numberOfFrames) {
+    m_provider.provideInput(m_tempBus.get(), m_providerSize);
+
+    m_fifo.push(m_tempBus.get());
+
+    framesProvided += m_providerSize;
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/AudioPullFIFO.h b/third_party/WebKit/Source/platform/audio/AudioPullFIFO.h
new file mode 100644
index 0000000..7f375b2e
--- /dev/null
+++ b/third_party/WebKit/Source/platform/audio/AudioPullFIFO.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AudioPullFIFO_h
+#define AudioPullFIFO_h
+
+#include "platform/audio/AudioBus.h"
+#include "platform/audio/AudioFIFO.h"
+#include "platform/audio/AudioSourceProvider.h"
+#include "wtf/Allocator.h"
+
+namespace blink {
+
+// A FIFO (First In First Out) buffer to handle mismatches in buffer sizes
+// between a provider and receiver. The receiver will "pull" data from this
+// FIFO. If data is already available in the FIFO, it is provided to the
+// receiver. If insufficient data is available to satisfy the request, the FIFO
+// will ask the provider for more data when necessary to fulfill a request.
+// Contrast this with a "push" FIFO, where the sender pushes data to the FIFO
+// which will itself push the data to the receiver when the FIFO is full.
+class PLATFORM_EXPORT AudioPullFIFO {
+  USING_FAST_MALLOC(AudioPullFIFO);
+  WTF_MAKE_NONCOPYABLE(AudioPullFIFO);
+
+ public:
+  // Create a FIFO that gets data from |provider|. The FIFO will be large
+  // enough to hold |fifoLength| frames of data of |numberOfChannels| channels.
+  // The AudioSourceProvider will be asked to produce |providerSize| frames
+  // when the FIFO needs more data.
+  AudioPullFIFO(AudioSourceProvider& audioProvider,
+                unsigned numberOfChannels,
+                size_t fifoLength,
+                size_t providerSize);
+
+  // Read |framesToConsume| frames from the FIFO into the destination. If the
+  // FIFO does not have enough data, we ask the |provider| to get more data to
+  // fulfill the request.
+  void consume(AudioBus* destination, size_t framesToConsume);
+
+ private:
+  // Fill the FIFO buffer with at least |numberOfFrames| more data.
+  void fillBuffer(size_t numberOfFrames);
+
+  // The provider of the data in our FIFO.
+  AudioSourceProvider& m_provider;
+
+  // The actual FIFO
+  AudioFIFO m_fifo;
+
+  // Number of frames of data that the provider will produce per call.
+  unsigned m_providerSize;
+
+  // Temporary workspace to hold the data from the provider.
+  RefPtr<AudioBus> m_tempBus;
+};
+
+}  // namespace blink
+
+#endif  // AudioPullFIFO.h
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp
deleted file mode 100644
index f464e9d..0000000
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform/audio/PushPullFIFO.h"
-
-#include <memory>
-#include "platform/audio/AudioUtilities.h"
-#include "wtf/PtrUtil.h"
-
-namespace blink {
-
-namespace {
-
-// Suppress the warning log if over/underflow happens more than 100 times.
-const unsigned kMaxMessagesToLog = 100;
-}
-
-const size_t PushPullFIFO::kMaxFIFOLength = 65536;
-
-PushPullFIFO::PushPullFIFO(unsigned numberOfChannels, size_t fifoLength)
-    : m_fifoLength(fifoLength),
-      m_framesAvailable(0),
-      m_indexRead(0),
-      m_indexWrite(0),
-      m_overflowCount(0),
-      m_underflowCount(0) {
-  CHECK_LE(m_fifoLength, kMaxFIFOLength);
-  m_fifoBus = AudioBus::create(numberOfChannels, m_fifoLength);
-}
-
-PushPullFIFO::~PushPullFIFO() {}
-
-// Push the data from |inputBus| to FIFO. The size of push is determined by
-// the length of |inputBus|.
-void PushPullFIFO::push(const AudioBus* inputBus) {
-  CHECK(inputBus);
-  CHECK_EQ(inputBus->length(), AudioUtilities::kRenderQuantumFrames);
-  SECURITY_CHECK(inputBus->length() <= m_fifoLength);
-  SECURITY_CHECK(m_indexWrite < m_fifoLength);
-
-  const size_t inputBusLength = inputBus->length();
-  const size_t remainder = m_fifoLength - m_indexWrite;
-
-  for (unsigned i = 0; i < m_fifoBus->numberOfChannels(); ++i) {
-    float* fifoBusChannel = m_fifoBus->channel(i)->mutableData();
-    const float* inputBusChannel = inputBus->channel(i)->data();
-    if (remainder >= inputBusLength) {
-      // The remainder is big enough for the input data.
-      memcpy(fifoBusChannel + m_indexWrite, inputBusChannel,
-             inputBusLength * sizeof(*fifoBusChannel));
-    } else {
-      // The input data overflows the remainder size. Wrap around the index.
-      memcpy(fifoBusChannel + m_indexWrite, inputBusChannel,
-             remainder * sizeof(*fifoBusChannel));
-      memcpy(fifoBusChannel, inputBusChannel + remainder,
-             (inputBusLength - remainder) * sizeof(*fifoBusChannel));
-    }
-  }
-
-  // Update the write index; wrap it around if necessary.
-  m_indexWrite = (m_indexWrite + inputBusLength) % m_fifoLength;
-
-  // In case of overflow, move the |indexRead| to the updated |indexWrite| to
-  // avoid reading overwritten frames by the next pull.
-  if (inputBusLength > m_fifoLength - m_framesAvailable) {
-    m_indexRead = m_indexWrite;
-    if (++m_overflowCount < kMaxMessagesToLog) {
-      LOG(WARNING) << "PushPullFIFO: overflow while pushing ("
-                   << "overflowCount=" << m_overflowCount
-                   << ", availableFrames=" << m_framesAvailable
-                   << ", inputFrames=" << inputBusLength
-                   << ", fifoLength=" << m_fifoLength << ")";
-    }
-  }
-
-  // Update the number of frames available in FIFO.
-  m_framesAvailable =
-      std::min(m_framesAvailable + inputBusLength, m_fifoLength);
-  DCHECK_EQ((m_indexRead + m_framesAvailable) % m_fifoLength, m_indexWrite);
-}
-
-// Pull the data out of FIFO to |outputBus|. If remaining frame in the FIFO
-// is less than the frames to pull, provides remaining frame plus the silence.
-void PushPullFIFO::pull(AudioBus* outputBus, size_t framesRequested) {
-  CHECK(outputBus);
-  SECURITY_CHECK(framesRequested <= outputBus->length());
-  SECURITY_CHECK(framesRequested <= m_fifoLength);
-  SECURITY_CHECK(m_indexRead < m_fifoLength);
-
-  const size_t remainder = m_fifoLength - m_indexRead;
-  const size_t framesToFill = std::min(m_framesAvailable, framesRequested);
-
-  for (unsigned i = 0; i < m_fifoBus->numberOfChannels(); ++i) {
-    const float* fifoBusChannel = m_fifoBus->channel(i)->data();
-    float* outputBusChannel = outputBus->channel(i)->mutableData();
-
-    // Fill up the output bus with the available frames first.
-    if (remainder >= framesToFill) {
-      // The remainder is big enough for the frames to pull.
-      memcpy(outputBusChannel, fifoBusChannel + m_indexRead,
-             framesToFill * sizeof(*fifoBusChannel));
-    } else {
-      // The frames to pull is bigger than the remainder size.
-      // Wrap around the index.
-      memcpy(outputBusChannel, fifoBusChannel + m_indexRead,
-             remainder * sizeof(*fifoBusChannel));
-      memcpy(outputBusChannel + remainder, fifoBusChannel,
-             (framesToFill - remainder) * sizeof(*fifoBusChannel));
-    }
-
-    // The frames available was not enough to fulfill the requested frames. Fill
-    // the rest of the channel with silence.
-    if (framesRequested > framesToFill) {
-      memset(outputBusChannel + framesToFill, 0,
-             (framesRequested - framesToFill) * sizeof(*outputBusChannel));
-    }
-  }
-
-  // Update the read index; wrap it around if necessary.
-  m_indexRead = (m_indexRead + framesToFill) % m_fifoLength;
-
-  // In case of underflow, move the |indexWrite| to the updated |indexRead|.
-  if (framesRequested > framesToFill) {
-    m_indexWrite = m_indexRead;
-    if (m_underflowCount++ < kMaxMessagesToLog) {
-      LOG(WARNING) << "PushPullFIFO: underflow while pulling ("
-                   << "underflowCount=" << m_underflowCount
-                   << ", availableFrames=" << m_framesAvailable
-                   << ", requestedFrames=" << framesRequested
-                   << ", fifoLength=" << m_fifoLength << ")";
-    }
-  }
-
-  // Update the number of frames in FIFO.
-  m_framesAvailable -= framesToFill;
-  DCHECK_EQ((m_indexRead + m_framesAvailable) % m_fifoLength, m_indexWrite);
-}
-
-const PushPullFIFOStateForTest PushPullFIFO::getStateForTest() const {
-  return {length(),     numberOfChannels(), framesAvailable(), m_indexRead,
-          m_indexWrite, m_overflowCount,    m_underflowCount};
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFO.h b/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
deleted file mode 100644
index 2341372..0000000
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PushPullFIFO_h
-#define PushPullFIFO_h
-
-#include "platform/audio/AudioBus.h"
-#include "public/platform/WebCommon.h"
-#include "wtf/Allocator.h"
-
-namespace blink {
-
-// A configuration data container for PushPullFIFO unit test.
-struct PushPullFIFOStateForTest {
-  const size_t fifoLength;
-  const unsigned numberOfChannels;
-  const size_t framesAvailable;
-  const size_t indexRead;
-  const size_t indexWrite;
-  const unsigned overflowCount;
-  const unsigned underflowCount;
-};
-
-// PushPullFIFO class is an intermediate audio sample storage between
-// Blink-WebAudio and the renderer. The renderer's hardware callback buffer size
-// varies on the platform, but the WebAudio always renders 128 frames (render
-// quantum, RQ) thus FIFO is needed to handle the general case.
-class BLINK_PLATFORM_EXPORT PushPullFIFO {
-  USING_FAST_MALLOC(PushPullFIFO);
-  WTF_MAKE_NONCOPYABLE(PushPullFIFO);
-
- public:
-  // Maximum FIFO length. (512 render quanta)
-  static const size_t kMaxFIFOLength;
-
-  // |fifoLength| cannot exceed |kMaxFIFOLength|. Otherwise it crashes.
-  explicit PushPullFIFO(unsigned numberOfChannels, size_t fifoLength);
-  ~PushPullFIFO();
-
-  // Pushes the rendered frames by WebAudio engine.
-  //  - The |inputBus| length is 128 frames (1 render quantum), fixed.
-  //  - In case of overflow (FIFO full while push), the existing frames in FIFO
-  //    will be overwritten and |indexRead| will be forcibly moved to
-  //    |indexWrite| to avoid reading overwritten frames.
-  void push(const AudioBus* inputBus);
-
-  // Pulling |framesRequested| by the audio device thread.
-  //  - If |framesRequested| is bigger than the length of |outputBus|, it
-  //    violates SECURITY_CHECK().
-  //  - If |framesRequested| is bigger than FIFO length, it violates
-  //    SECURITY_CHECK().
-  //  - In case of underflow (FIFO empty while pull), the remaining space in the
-  //    requested output bus will be filled with silence. Thus it will fulfill
-  //    the request from the consumer without causing error, but with a glitch.
-  void pull(AudioBus* outputBus, size_t framesRequested);
-
-  size_t framesAvailable() const { return m_framesAvailable; }
-  size_t length() const { return m_fifoLength; }
-  unsigned numberOfChannels() const { return m_fifoBus->numberOfChannels(); }
-  AudioBus* bus() const { return m_fifoBus.get(); }
-
-  // For unit test. Get the current configuration that consists of FIFO length,
-  // number of channels, read/write index position and under/overflow count.
-  const PushPullFIFOStateForTest getStateForTest() const;
-
- private:
-  // The size of the FIFO.
-  const size_t m_fifoLength = 0;
-
-  RefPtr<AudioBus> m_fifoBus;
-
-  // The number of frames in the FIFO actually available for pulling.
-  size_t m_framesAvailable;
-
-  size_t m_indexRead;
-  size_t m_indexWrite;
-
-  unsigned m_overflowCount;
-  unsigned m_underflowCount;
-};
-
-}  // namespace blink
-
-#endif  // PushPullFIFO_h
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
deleted file mode 100644
index 0a9edda2..0000000
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform/audio/PushPullFIFO.h"
-
-#include <memory>
-#include <vector>
-#include "platform/audio/AudioUtilities.h"
-#include "platform/testing/TestingPlatformSupport.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "wtf/PtrUtil.h"
-
-namespace blink {
-
-namespace {
-
-// Check the basic contract of FIFO.
-TEST(PushPullFIFOBasicTest, BasicTests) {
-  // This suppresses the multi-thread warning for GTest. Potently it increases
-  // the test execution time, but this specific test is very short and simple.
-  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-
-  // FIFO length exceeding the maximum length allowed will cause crash.
-  EXPECT_DEATH(new PushPullFIFO(2, PushPullFIFO::kMaxFIFOLength + 1),
-               "m_fifoLength <= kMaxFIFOLength");
-
-  std::unique_ptr<PushPullFIFO> testFifo =
-      WTF::wrapUnique(new PushPullFIFO(2, 1024));
-
-  // The input bus length must be |AudioUtilities::kRenderQuantumFrames|.
-  RefPtr<AudioBus> inputBusOf129Frames =
-      AudioBus::create(2, AudioUtilities::kRenderQuantumFrames + 1);
-  EXPECT_DEATH(testFifo->push(inputBusOf129Frames.get()),
-               "inputBus->length.* == .*kRenderQuantumFrames");
-  RefPtr<AudioBus> inputBusOf127Frames =
-      AudioBus::create(2, AudioUtilities::kRenderQuantumFrames - 1);
-  EXPECT_DEATH(testFifo->push(inputBusOf127Frames.get()),
-               "inputBus->length.* == .*kRenderQuantumFrames");
-
-  // Pull request frames cannot exceed the length of output bus.
-  RefPtr<AudioBus> outputBusOf512Frames = AudioBus::create(2, 512);
-  EXPECT_DEATH(testFifo->pull(outputBusOf512Frames.get(), 513),
-               "framesRequested <= outputBus->length.*");
-
-  // Pull request frames cannot exceed the length of FIFO.
-  RefPtr<AudioBus> outputBusOf1025Frames = AudioBus::create(2, 1025);
-  EXPECT_DEATH(testFifo->pull(outputBusOf1025Frames.get(), 1025),
-               "framesRequested <= m_fifoLength");
-}
-
-// Fills each AudioChannel in an AudioBus with a series of linearly increasing
-// values starting from |startingValue| and incrementing by 1. Then return value
-// will be |startingValue| + |bus_length|.
-size_t fillBusWithLinearRamp(AudioBus* targetBus, size_t startingValue) {
-  for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) {
-    float* busChannel = targetBus->channel(c)->mutableData();
-    for (size_t i = 0; i < targetBus->channel(c)->length(); ++i) {
-      busChannel[i] = static_cast<float>(startingValue + i);
-    }
-  }
-  return startingValue + targetBus->length();
-}
-
-// Inspect the content of AudioBus with a given set of index and value across
-// channels.
-bool verifyBusValueAtIndex(AudioBus* targetBus,
-                           int index,
-                           float expectedValue) {
-  for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) {
-    float* busChannel = targetBus->channel(c)->mutableData();
-    if (busChannel[index] != expectedValue) {
-      LOG(ERROR) << ">> [FAIL] expected " << expectedValue << " at index "
-                 << index << " but got " << busChannel[index] << ".";
-      return false;
-    }
-  }
-  return true;
-}
-
-struct FIFOAction {
-  // The type of action; "PUSH" or "PULL".
-  const char* action;
-  // Number of frames for the operation.
-  const size_t numberOfFrames;
-};
-
-struct AudioBusSample {
-  // The frame index of a sample in the bus.
-  const size_t index;
-  // The value at the |index| above.
-  const float value;
-};
-
-struct FIFOTestSetup {
-  // Length of FIFO to be created for test case.
-  const size_t fifoLength;
-  // Channel count of FIFO to be created for test case.
-  const unsigned numberOfChannels;
-  // A list of |FIFOAction| entries to be performed in test case.
-  const std::vector<FIFOAction> fifoActions;
-};
-
-struct FIFOTestExpectedState {
-  // Expected read index in FIFO.
-  const size_t indexRead;
-  // Expected write index in FIFO.
-  const size_t indexWrite;
-  // Expected overflow count in FIFO.
-  const unsigned overflowCount;
-  // Expected underflow count in FIFO.
-  const unsigned underflowCount;
-  // A list of expected |AudioBusSample| entries for the FIFO bus.
-  const std::vector<AudioBusSample> fifoSamples;
-  // A list of expected |AudioBusSample| entries for the output bus.
-  const std::vector<AudioBusSample> outputSamples;
-};
-
-// The data structure for the parameterized test cases.
-struct FIFOTestParam {
-  FIFOTestSetup setup;
-  FIFOTestExpectedState expectedState;
-};
-
-std::ostream& operator<<(std::ostream& out, const FIFOTestParam& param) {
-  out << "fifoLength=" << param.setup.fifoLength
-      << " numberOfChannels=" << param.setup.numberOfChannels;
-  return out;
-}
-
-class PushPullFIFOFeatureTest : public ::testing::TestWithParam<FIFOTestParam> {
-};
-
-TEST_P(PushPullFIFOFeatureTest, FeatureTests) {
-  const FIFOTestSetup setup = GetParam().setup;
-  const FIFOTestExpectedState expectedState = GetParam().expectedState;
-
-  // Create a FIFO with a specified configuration.
-  std::unique_ptr<PushPullFIFO> fifo = WTF::wrapUnique(
-      new PushPullFIFO(setup.numberOfChannels, setup.fifoLength));
-
-  RefPtr<AudioBus> outputBus;
-
-  // Iterate all the scheduled push/pull actions.
-  size_t frameCounter = 0;
-  for (const auto& action : setup.fifoActions) {
-    if (strcmp(action.action, "PUSH") == 0) {
-      RefPtr<AudioBus> inputBus =
-          AudioBus::create(setup.numberOfChannels, action.numberOfFrames);
-      frameCounter = fillBusWithLinearRamp(inputBus.get(), frameCounter);
-      fifo->push(inputBus.get());
-      LOG(INFO) << "PUSH " << action.numberOfFrames
-                << " frames (frameCounter=" << frameCounter << ")";
-    } else {
-      outputBus =
-          AudioBus::create(setup.numberOfChannels, action.numberOfFrames);
-      fifo->pull(outputBus.get(), action.numberOfFrames);
-      LOG(INFO) << "PULL " << action.numberOfFrames << " frames";
-    }
-  }
-
-  // Get FIFO config data.
-  const PushPullFIFOStateForTest actualState = fifo->getStateForTest();
-
-  // Verify the read/write indexes.
-  EXPECT_EQ(expectedState.indexRead, actualState.indexRead);
-  EXPECT_EQ(expectedState.indexWrite, actualState.indexWrite);
-  EXPECT_EQ(expectedState.overflowCount, actualState.overflowCount);
-  EXPECT_EQ(expectedState.underflowCount, actualState.underflowCount);
-
-  // Verify in-FIFO samples.
-  for (const auto& sample : expectedState.fifoSamples) {
-    EXPECT_TRUE(verifyBusValueAtIndex(fifo->bus(), sample.index, sample.value));
-  }
-
-  // Verify samples from the most recent output bus.
-  for (const auto& sample : expectedState.outputSamples) {
-    EXPECT_TRUE(
-        verifyBusValueAtIndex(outputBus.get(), sample.index, sample.value));
-  }
-}
-
-FIFOTestParam featureTestParams[] = {
-    // Test cases 0 ~ 3: Regular operation on various channel configuration.
-    //  - Mono, Stereo, Quad, 5.1.
-    //  - FIFO length and pull size are RQ-aligned.
-    {{512, 1, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
-     {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
-
-    {{512, 2, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
-     {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
-
-    {{512, 4, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
-     {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
-
-    {{512, 6, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
-     {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
-
-    // Test case 4: Pull size less than or equal to 128.
-    {{128, 2, {{"PUSH", 128}, {"PULL", 128}, {"PUSH", 128}, {"PULL", 64}}},
-     {64, 0, 0, 0, {{64, 192}, {0, 128}}, {{0, 128}, {63, 191}}}},
-
-    // Test case 5: Unusual FIFO and Pull length.
-    //  - FIFO and pull length that are not aligned to render quantum.
-    //  - Check if the indexes are wrapping around correctly.
-    //  - Check if the output bus starts and ends with correct values.
-    {{997,
-      1,
-      {
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 449},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 449},
-      }},
-     // - expectedIndexRead = 898, expectedIndexWrite = 27
-     // - overflowCount = 0, underflowCount = 0
-     // - FIFO samples (index, expectedValue) = (898, 898), (27, 27)
-     // - Output bus samples (index, expectedValue) = (0, 499), (448, 897)
-     {898, 27, 0, 0, {{898, 898}, {27, 27}}, {{0, 449}, {448, 897}}}},
-
-    // Test case 6: Overflow
-    //  - Check overflow counter.
-    //  - After the overflow occurs, the read index must be moved to the write
-    //    index. Thus pulled frames must not contain overwritten data.
-    {{512,
-      3,
-      {
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 256},
-      }},
-     // - expectedIndexRead = 384, expectedIndexWrite = 128
-     // - overflowCount = 1, underflowCount = 0
-     // - FIFO samples (index, expectedValue) = (384, 384), (128, 128)
-     // - Output bus samples (index, expectedValue) = (0, 128), (255, 383)
-     {384, 128, 1, 0, {{384, 384}, {128, 128}}, {{0, 128}, {255, 383}}}},
-
-    // Test case 7: Overflow in unusual FIFO and pull length.
-    //  - Check overflow counter.
-    //  - After the overflow occurs, the read index must be moved to the write
-    //    index. Thus pulled frames must not contain overwritten data.
-    {{577,
-      5,
-      {
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 227},
-      }},
-     // - expectedIndexRead = 290, expectedIndexWrite = 63
-     // - overflowCount = 1, underflowCount = 0
-     // - FIFO samples (index, expectedValue) = (63, 63), (290, 290)
-     // - Output bus samples (index, expectedValue) = (0, 63), (226, 289)
-     {290, 63, 1, 0, {{63, 63}, {290, 290}}, {{0, 63}, {226, 289}}}},
-
-    // Test case 8: Underflow
-    //  - Check underflow counter.
-    //  - After the underflow occurs, the write index must be moved to the read
-    //    index. Frames pulled after FIFO underflows must be zeroed.
-    {{512,
-      7,
-      {
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 384},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 384},
-      }},
-     // - expectedIndexRead = 128, expectedIndexWrite = 128
-     // - overflowCount = 0, underflowCount = 1
-     // - FIFO samples (index, expectedValue) = (128, 128)
-     // - Output bus samples (index, expectedValue) = (0, 384), (255, 639)
-     //                                               (256, 0), (383, 0)
-     {128,
-      128,
-      0,
-      1,
-      {{128, 128}},
-      {{0, 384}, {255, 639}, {256, 0}, {383, 0}}}},
-
-    // Test case 9: Underflow in unusual FIFO and pull length.
-    //  - Check underflow counter.
-    //  - After the underflow occurs, the write index must be moved to the read
-    //    index. Frames pulled after FIFO underflows must be zeroed.
-    {{523,
-      11,
-      {
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 383},
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 383},
-      }},
-     // - expectedIndexRead = 117, expectedIndexWrite = 117
-     // - overflowCount = 0, underflowCount = 1
-     // - FIFO samples (index, expectedValue) = (117, 117)
-     // - Output bus samples (index, expectedValue) = (0, 383), (256, 639)
-     //                                               (257, 0), (382, 0)
-     {117,
-      117,
-      0,
-      1,
-      {{117, 117}},
-      {{0, 383}, {256, 639}, {257, 0}, {382, 0}}}},
-
-    // Test case 10: Multiple pull from an empty FIFO.
-    //  - Check underflow counter.
-    //  - After the underflow occurs, the write index must be moved to the read
-    //    index. Frames pulled after FIFO underflows must be zeroed.
-    {{1024,
-      11,
-      {
-          {"PUSH", 128},
-          {"PUSH", 128},
-          {"PULL", 440},
-          {"PULL", 440},
-          {"PULL", 440},
-          {"PULL", 440},
-          {"PULL", 440},
-      }},
-     // - expectedIndexRead = 117, expectedIndexWrite = 117
-     // - overflowCount = 0, underflowCount = 1
-     // - FIFO samples (index, expectedValue) = (117, 117)
-     // - Output bus samples (index, expectedValue) = (0, 383), (256, 639)
-     //                                               (257, 0), (382, 0)
-     {256, 256, 0, 5, {{256, 0}}, {{0, 0}, {439, 0}}}},
-
-    // Test case 11: Multiple pull from an empty FIFO. (zero push)
-    {{1024,
-      11,
-      {
-          {"PULL", 144},
-          {"PULL", 144},
-          {"PULL", 144},
-          {"PULL", 144},
-      }},
-     // - expectedIndexRead = 0, expectedIndexWrite = 0
-     // - overflowCount = 0, underflowCount = 4
-     // - FIFO samples (index, expectedValue) = (0, 0), (1023, 0)
-     // - Output bus samples (index, expectedValue) = (0, 0), (143, 0)
-     {0, 0, 0, 4, {{0, 0}, {1023, 0}}, {{0, 0}, {143, 0}}}}};
-
-INSTANTIATE_TEST_CASE_P(PushPullFIFOFeatureTest,
-                        PushPullFIFOFeatureTest,
-                        ::testing::ValuesIn(featureTestParams));
-
-}  // namespace
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
index 0364dad..67a8692 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -410,6 +410,10 @@
   m_resourceRequest->setNavigationStartTime(navigationStartSeconds);
 }
 
+void WebURLRequest::setIsSameDocumentNavigation(bool isSameDocument) {
+  m_resourceRequest->setIsSameDocumentNavigation(isSameDocument);
+}
+
 WebURLRequest::InputToLoadPerfMetricReportPolicy
 WebURLRequest::inputPerfMetricReportPolicy() const {
   return static_cast<WebURLRequest::InputToLoadPerfMetricReportPolicy>(
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.cpp b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.cpp
index 4f17d0e..4bd2a1f 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShapeIterator.cpp
@@ -18,8 +18,9 @@
   unsigned wordLength = 0;
   std::unique_ptr<UChar[]> wordText = wordRun.normalizedUTF16(&wordLength);
 
-  HarfBuzzShaper shaper(wordText.get(), wordLength, wordRun.direction());
-  RefPtr<const ShapeResult> shapeResult = shaper.shapeResult(font);
+  HarfBuzzShaper shaper(wordText.get(), wordLength);
+  RefPtr<const ShapeResult> shapeResult =
+      shaper.shape(font, wordRun.direction());
   if (!shapeResult)
     return nullptr;
 
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
index 82d77dd..5a2c639 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp
@@ -40,7 +40,6 @@
 #include "platform/fonts/opentype/OpenTypeCapsSupport.h"
 #include "platform/fonts/shaping/CaseMappingHarfBuzzBufferFiller.h"
 #include "platform/fonts/shaping/HarfBuzzFace.h"
-#include "platform/fonts/shaping/RunSegmenter.h"
 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h"
 #include "platform/text/TextBreakIterator.h"
 #include "wtf/Compiler.h"
@@ -56,6 +55,17 @@
 namespace blink {
 using FeaturesVector = Vector<hb_feature_t, 6>;
 
+enum HolesQueueItemAction { HolesQueueNextFont, HolesQueueRange };
+
+struct HolesQueueItem {
+  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+  HolesQueueItemAction m_action;
+  unsigned m_startIndex;
+  unsigned m_numCharacters;
+  HolesQueueItem(HolesQueueItemAction action, unsigned start, unsigned num)
+      : m_action(action), m_startIndex(start), m_numCharacters(num){};
+};
+
 template <typename T>
 class HarfBuzzScopedPtr {
   STACK_ALLOCATED();
@@ -81,12 +91,8 @@
   DestroyFunction m_destroy;
 };
 
-HarfBuzzShaper::HarfBuzzShaper(const UChar* text,
-                               unsigned length,
-                               TextDirection direction)
-    : m_normalizedBuffer(text),
-      m_normalizedBufferLength(length),
-      m_textDirection(direction) {}
+HarfBuzzShaper::HarfBuzzShaper(const UChar* text, unsigned length)
+    : m_text(text), m_textLength(length) {}
 
 namespace {
 
@@ -112,7 +118,7 @@
                                     : harfBuzzDirection;
 }
 
-inline bool shapeRange(hb_buffer_t* harfBuzzBuffer,
+inline bool shapeRange(hb_buffer_t* buffer,
                        hb_feature_t* fontFeatures,
                        unsigned fontFeaturesSize,
                        const SimpleFontData* currentFont,
@@ -127,24 +133,25 @@
     return false;
   }
 
-  hb_buffer_set_language(harfBuzzBuffer, language);
-  hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript));
-  hb_buffer_set_direction(harfBuzzBuffer, direction);
+  hb_buffer_set_language(buffer, language);
+  hb_buffer_set_script(buffer, ICUScriptToHBScript(currentRunScript));
+  hb_buffer_set_direction(buffer, direction);
 
   hb_font_t* hbFont = face->getScaledFont(std::move(currentFontRangeSet));
-  hb_shape(hbFont, harfBuzzBuffer, fontFeatures, fontFeaturesSize);
+  hb_shape(hbFont, buffer, fontFeatures, fontFeaturesSize);
 
   return true;
 }
 
 }  // namespace
 
-bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* harfBuzzBuffer,
+bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* buffer,
                                          ShapeResult* shapeResult,
                                          bool& fontCycleQueued,
                                          Deque<HolesQueueItem>* holesQueue,
                                          const HolesQueueItem& currentQueueItem,
                                          const Font* font,
+                                         TextDirection textDirection,
                                          const SimpleFontData* currentFont,
                                          UScriptCode currentRunScript,
                                          bool isLastResort) const {
@@ -154,9 +161,9 @@
   unsigned previousCluster = 0;
   unsigned currentCluster = 0;
 
-  // Find first notdef glyph in harfBuzzBuffer.
-  unsigned numGlyphs = hb_buffer_get_length(harfBuzzBuffer);
-  hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos(harfBuzzBuffer, 0);
+  // Find first notdef glyph in buffer.
+  unsigned numGlyphs = hb_buffer_get_length(buffer);
+  hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos(buffer, 0);
 
   unsigned lastChangePosition = 0;
 
@@ -212,7 +219,7 @@
     unsigned numCharacters = 0;
     unsigned numGlyphsToInsert = 0;
     unsigned startIndex = 0;
-    if (HB_DIRECTION_IS_FORWARD(hb_buffer_get_direction(harfBuzzBuffer))) {
+    if (HB_DIRECTION_IS_FORWARD(hb_buffer_get_direction(buffer))) {
       startIndex = glyphInfo[lastChangePosition].cluster;
       if (glyphIndex == numGlyphs) {
         numCharacters = currentQueueItem.m_startIndex +
@@ -260,14 +267,13 @@
     // choice than adding boxes to the ShapeResult.
     if ((currentClusterResult == NotDef && numCharacters) || isLastResort) {
       hb_direction_t direction = TextDirectionToHBDirection(
-          m_textDirection, font->getFontDescription().orientation(),
-          currentFont);
+          textDirection, font->getFontDescription().orientation(), currentFont);
       // Here we need to specify glyph positions.
       ShapeResult::RunInfo* run = new ShapeResult::RunInfo(
           currentFont, direction, ICUScriptToHBScript(currentRunScript),
           startIndex, numGlyphsToInsert, numCharacters);
       shapeResult->insertRun(WTF::wrapUnique(run), lastChangePosition,
-                             numGlyphsToInsert, harfBuzzBuffer);
+                             numGlyphsToInsert, buffer);
     }
     lastChangePosition = glyphIndex;
   }
@@ -290,23 +296,22 @@
 }
 
 bool HarfBuzzShaper::collectFallbackHintChars(
-    const Deque<HolesQueueItem>& holesQueue,
+    const Deque<HolesQueueItem>* holesQueue,
     Vector<UChar32>& hint) const {
-  if (!holesQueue.size())
+  DCHECK(holesQueue);
+  if (!holesQueue->size())
     return false;
 
   hint.clear();
 
   size_t numCharsAdded = 0;
-  for (auto it = holesQueue.begin(); it != holesQueue.end(); ++it) {
+  for (auto it = holesQueue->begin(); it != holesQueue->end(); ++it) {
     if (it->m_action == HolesQueueNextFont)
       break;
 
     UChar32 hintChar;
-    RELEASE_ASSERT(it->m_startIndex + it->m_numCharacters <=
-                   m_normalizedBufferLength);
-    UTF16TextIterator iterator(m_normalizedBuffer + it->m_startIndex,
-                               it->m_numCharacters);
+    RELEASE_ASSERT(it->m_startIndex + it->m_numCharacters <= m_textLength);
+    UTF16TextIterator iterator(m_text + it->m_startIndex, it->m_numCharacters);
     while (iterator.consume(hintChar)) {
       hint.push_back(hintChar);
       numCharsAdded++;
@@ -317,13 +322,11 @@
 }
 
 namespace {
-using HolesQueueItem = HarfBuzzShaper::HolesQueueItem;
-using HolesQueueItemAction = HarfBuzzShaper::HolesQueueItemAction;
 
 void splitUntilNextCaseChange(
     const UChar* normalizedBuffer,
-    Deque<HolesQueueItem>* queue,
-    HolesQueueItem& currentQueueItem,
+    Deque<blink::HolesQueueItem>* queue,
+    blink::HolesQueueItem& currentQueueItem,
     SmallCapsIterator::SmallCapsBehavior& smallCapsBehavior) {
   unsigned numCharactersUntilCaseChange = 0;
   SmallCapsIterator smallCapsIterator(
@@ -332,8 +335,8 @@
   smallCapsIterator.consume(&numCharactersUntilCaseChange, &smallCapsBehavior);
   if (numCharactersUntilCaseChange > 0 &&
       numCharactersUntilCaseChange < currentQueueItem.m_numCharacters) {
-    queue->prepend(HolesQueueItem(
-        HolesQueueItemAction::HolesQueueRange,
+    queue->prepend(blink::HolesQueueItem(
+        blink::HolesQueueItemAction::HolesQueueRange,
         currentQueueItem.m_startIndex + numCharactersUntilCaseChange,
         currentQueueItem.m_numCharacters - numCharactersUntilCaseChange));
     currentQueueItem.m_numCharacters = numCharactersUntilCaseChange;
@@ -546,132 +549,159 @@
 
 }  // namespace
 
-PassRefPtr<ShapeResult> HarfBuzzShaper::shapeResult(const Font* font) const {
-  RefPtr<ShapeResult> result =
-      ShapeResult::create(font, m_normalizedBufferLength, m_textDirection);
-  HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(),
-                                                hb_buffer_destroy);
-  FeaturesVector fontFeatures;
-  setFontFeatures(font, &fontFeatures);
+void HarfBuzzShaper::shapeSegment(ShapeResult* result,
+                                  Deque<HolesQueueItem>* holesQueue,
+                                  hb_buffer_t* buffer,
+                                  const Font* font,
+                                  TextDirection textDirection,
+                                  FeaturesVector* fontFeatures,
+                                  RunSegmenter::RunSegmenterRange segment,
+                                  unsigned start,
+                                  unsigned end) const {
+  DCHECK(result);
+  DCHECK(holesQueue);
+  DCHECK(buffer);
+
   const FontDescription& fontDescription = font->getFontDescription();
   const hb_language_t language =
       fontDescription.localeOrDefault().harfbuzzLanguage();
-
   bool needsCapsHandling =
       fontDescription.variantCaps() != FontDescription::CapsNormal;
   OpenTypeCapsSupport capsSupport;
+
+  FontOrientation orientation = font->getFontDescription().orientation();
+  RefPtr<FontFallbackIterator> fallbackIterator =
+      font->createFontFallbackIterator(segment.fontFallbackPriority);
+
+  holesQueue->append(HolesQueueItem(HolesQueueNextFont, 0, 0));
+  holesQueue->append(HolesQueueItem(HolesQueueRange, segment.start,
+                                    segment.end - segment.start));
+
+  bool fontCycleQueued = false;
+  Vector<UChar32> fallbackCharsHint;
+  RefPtr<FontDataForRangeSet> currentFontDataForRangeSet;
+  while (holesQueue->size()) {
+    HolesQueueItem currentQueueItem = holesQueue->takeFirst();
+
+    if (currentQueueItem.m_action == HolesQueueNextFont) {
+      // For now, we're building a character list with which we probe
+      // for needed fonts depending on the declared unicode-range of a
+      // segmented CSS font. Alternatively, we can build a fake font
+      // for the shaper and check whether any glyphs were found, or
+      // define a new API on the shaper which will give us coverage
+      // information?
+      if (!collectFallbackHintChars(holesQueue, fallbackCharsHint)) {
+        // Give up shaping since we cannot retrieve a font fallback
+        // font without a hintlist.
+        holesQueue->clear();
+        break;
+      }
+
+      currentFontDataForRangeSet = fallbackIterator->next(fallbackCharsHint);
+      if (!currentFontDataForRangeSet->fontData()) {
+        DCHECK(!holesQueue->size());
+        break;
+      }
+      fontCycleQueued = false;
+      continue;
+    }
+
+    const SimpleFontData* fontData = currentFontDataForRangeSet->fontData();
+    SmallCapsIterator::SmallCapsBehavior smallCapsBehavior =
+        SmallCapsIterator::SmallCapsSameCase;
+    if (needsCapsHandling) {
+      capsSupport = OpenTypeCapsSupport(fontData->platformData().harfBuzzFace(),
+                                        fontDescription.variantCaps(),
+                                        ICUScriptToHBScript(segment.script));
+      if (capsSupport.needsRunCaseSplitting()) {
+        splitUntilNextCaseChange(m_text, holesQueue, currentQueueItem,
+                                 smallCapsBehavior);
+      }
+    }
+
+    DCHECK(currentQueueItem.m_numCharacters);
+    const SimpleFontData* smallcapsAdjustedFont =
+        needsCapsHandling && capsSupport.needsSyntheticFont(smallCapsBehavior)
+            ? fontData->smallCapsFontData(fontDescription).get()
+            : fontData;
+
+    // Compatibility with SimpleFontData approach of keeping a flag for
+    // overriding drawing direction.
+    // TODO: crbug.com/506224 This should go away in favor of storing that
+    // information elsewhere, for example in ShapeResult.
+    const SimpleFontData* directionAndSmallCapsAdjustedFont =
+        fontDataAdjustedForOrientation(smallcapsAdjustedFont, orientation,
+                                       segment.renderOrientation);
+
+    CaseMapIntend caseMapIntend = CaseMapIntend::KeepSameCase;
+    if (needsCapsHandling)
+      caseMapIntend = capsSupport.needsCaseChange(smallCapsBehavior);
+
+    // Clamp the start and end offsets of the queue item to the offsets
+    // representing the shaping window.
+    unsigned shapeStart = std::max(start, currentQueueItem.m_startIndex);
+    unsigned shapeEnd = std::min(
+        end, currentQueueItem.m_startIndex + currentQueueItem.m_numCharacters);
+
+    CaseMappingHarfBuzzBufferFiller(
+        caseMapIntend, fontDescription.localeOrDefault(), buffer, m_text,
+        m_textLength, shapeStart, shapeEnd - shapeStart);
+
+    CapsFeatureSettingsScopedOverlay capsOverlay(
+        fontFeatures, capsSupport.fontFeatureToUse(smallCapsBehavior));
+    hb_direction_t direction = TextDirectionToHBDirection(
+        textDirection, orientation, directionAndSmallCapsAdjustedFont);
+
+    if (!shapeRange(buffer, fontFeatures->isEmpty() ? 0 : fontFeatures->data(),
+                    fontFeatures->size(), directionAndSmallCapsAdjustedFont,
+                    currentFontDataForRangeSet->ranges(), segment.script,
+                    direction, language))
+      DLOG(ERROR) << "Shaping range failed.";
+
+    if (!extractShapeResults(buffer, result, fontCycleQueued, holesQueue,
+                             currentQueueItem, font, textDirection,
+                             directionAndSmallCapsAdjustedFont, segment.script,
+                             !fallbackIterator->hasNext()))
+      DLOG(ERROR) << "Shape result extraction failed.";
+
+    hb_buffer_reset(buffer);
+  }
+}
+
+PassRefPtr<ShapeResult> HarfBuzzShaper::shape(const Font* font,
+                                              TextDirection direction,
+                                              unsigned start,
+                                              unsigned end) const {
+  DCHECK(end >= start);
+  DCHECK(end <= m_textLength);
+
+  unsigned length = end - start;
+  RefPtr<ShapeResult> result = ShapeResult::create(font, length, direction);
+  HarfBuzzScopedPtr<hb_buffer_t> buffer(hb_buffer_create(), hb_buffer_destroy);
+
+  FeaturesVector fontFeatures;
+  setFontFeatures(font, &fontFeatures);
   FontOrientation orientation = font->getFontDescription().orientation();
 
-  RunSegmenter::RunSegmenterRange segmentRange = {
-      0, 0, USCRIPT_INVALID_CODE, OrientationIterator::OrientationInvalid,
-      FontFallbackPriority::Invalid};
-  RunSegmenter runSegmenter(m_normalizedBuffer, m_normalizedBufferLength,
-                            orientation);
+  // Run segmentation needs to operate on the entire string, regardless of the
+  // shaping window (defined by the start and end parameters).
+  RunSegmenter::RunSegmenterRange segmentRange = RunSegmenter::nullRange();
+  RunSegmenter runSegmenter(m_text, m_textLength, orientation);
 
-  Vector<UChar32> fallbackCharsHint;
-
-  // TODO: Check whether this treatAsZerowidthspace from the previous script
-  // segmentation plays a role here, does the new scriptRuniterator handle that
-  // correctly?
   Deque<HolesQueueItem> holesQueue;
   while (runSegmenter.consume(&segmentRange)) {
-    RefPtr<FontFallbackIterator> fallbackIterator =
-        font->createFontFallbackIterator(segmentRange.fontFallbackPriority);
-
-    holesQueue.append(HolesQueueItem(HolesQueueNextFont, 0, 0));
-    holesQueue.append(HolesQueueItem(HolesQueueRange, segmentRange.start,
-                                     segmentRange.end - segmentRange.start));
-
-    RefPtr<FontDataForRangeSet> currentFontDataForRangeSet;
-
-    bool fontCycleQueued = false;
-    while (holesQueue.size()) {
-      HolesQueueItem currentQueueItem = holesQueue.takeFirst();
-
-      if (currentQueueItem.m_action == HolesQueueNextFont) {
-        // For now, we're building a character list with which we probe
-        // for needed fonts depending on the declared unicode-range of a
-        // segmented CSS font. Alternatively, we can build a fake font
-        // for the shaper and check whether any glyphs were found, or
-        // define a new API on the shaper which will give us coverage
-        // information?
-        if (!collectFallbackHintChars(holesQueue, fallbackCharsHint)) {
-          // Give up shaping since we cannot retrieve a font fallback
-          // font without a hintlist.
-          holesQueue.clear();
-          break;
-        }
-
-        currentFontDataForRangeSet = fallbackIterator->next(fallbackCharsHint);
-        if (!currentFontDataForRangeSet->fontData()) {
-          DCHECK(!holesQueue.size());
-          break;
-        }
-        fontCycleQueued = false;
-        continue;
-      }
-
-      const SimpleFontData* fontData = currentFontDataForRangeSet->fontData();
-      SmallCapsIterator::SmallCapsBehavior smallCapsBehavior =
-          SmallCapsIterator::SmallCapsSameCase;
-      if (needsCapsHandling) {
-        capsSupport =
-            OpenTypeCapsSupport(fontData->platformData().harfBuzzFace(),
-                                fontDescription.variantCaps(),
-                                ICUScriptToHBScript(segmentRange.script));
-        if (capsSupport.needsRunCaseSplitting()) {
-          splitUntilNextCaseChange(m_normalizedBuffer, &holesQueue,
-                                   currentQueueItem, smallCapsBehavior);
-        }
-      }
-
-      ASSERT(currentQueueItem.m_numCharacters);
-
-      const SimpleFontData* smallcapsAdjustedFont =
-          needsCapsHandling && capsSupport.needsSyntheticFont(smallCapsBehavior)
-              ? fontData->smallCapsFontData(fontDescription).get()
-              : fontData;
-
-      // Compatibility with SimpleFontData approach of keeping a flag for
-      // overriding drawing direction.
-      // TODO: crbug.com/506224 This should go away in favor of storing that
-      // information elsewhere, for example in ShapeResult.
-      const SimpleFontData* directionAndSmallCapsAdjustedFont =
-          fontDataAdjustedForOrientation(smallcapsAdjustedFont, orientation,
-                                         segmentRange.renderOrientation);
-
-      CaseMapIntend caseMapIntend = CaseMapIntend::KeepSameCase;
-      if (needsCapsHandling)
-        caseMapIntend = capsSupport.needsCaseChange(smallCapsBehavior);
-
-      CaseMappingHarfBuzzBufferFiller(
-          caseMapIntend, fontDescription.localeOrDefault(),
-          harfBuzzBuffer.get(), m_normalizedBuffer, m_normalizedBufferLength,
-          currentQueueItem.m_startIndex, currentQueueItem.m_numCharacters);
-
-      CapsFeatureSettingsScopedOverlay capsOverlay(
-          &fontFeatures, capsSupport.fontFeatureToUse(smallCapsBehavior));
-
-      hb_direction_t direction = TextDirectionToHBDirection(
-          m_textDirection, orientation, directionAndSmallCapsAdjustedFont);
-
-      if (!shapeRange(harfBuzzBuffer.get(),
-                      fontFeatures.isEmpty() ? 0 : fontFeatures.data(),
-                      fontFeatures.size(), directionAndSmallCapsAdjustedFont,
-                      currentFontDataForRangeSet->ranges(), segmentRange.script,
-                      direction, language))
-        DLOG(ERROR) << "Shaping range failed.";
-
-      if (!extractShapeResults(
-              harfBuzzBuffer.get(), result.get(), fontCycleQueued, &holesQueue,
-              currentQueueItem, font, directionAndSmallCapsAdjustedFont,
-              segmentRange.script, !fallbackIterator->hasNext()))
-        DLOG(ERROR) << "Shape result extraction failed.";
-
-      hb_buffer_reset(harfBuzzBuffer.get());
+    // Only shape segments overlapping with the  range indicated by start and
+    // end. Not only those strictly within.
+    if (start < segmentRange.end && end > segmentRange.start) {
+      shapeSegment(result.get(), &holesQueue, buffer.get(), font, direction,
+                   &fontFeatures, segmentRange, start, end);
     }
   }
   return result.release();
 }
 
+PassRefPtr<ShapeResult> HarfBuzzShaper::shape(const Font* font,
+                                              TextDirection direction) const {
+  return shape(font, direction, 0, m_textLength);
+}
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.h b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.h
index 7db9bcb4..aa33142 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.h
@@ -31,54 +31,77 @@
 #ifndef HarfBuzzShaper_h
 #define HarfBuzzShaper_h
 
+#include <hb.h>
+#include <unicode/uscript.h>
+#include <memory>
+#include "platform/fonts/shaping/RunSegmenter.h"
 #include "platform/fonts/shaping/ShapeResult.h"
 #include "platform/text/TextRun.h"
 #include "wtf/Allocator.h"
 #include "wtf/Deque.h"
 #include "wtf/Vector.h"
-#include <hb.h>
-#include <memory>
-#include <unicode/uscript.h>
 
 namespace blink {
 
 class Font;
 class SimpleFontData;
 class HarfBuzzShaper;
+struct HolesQueueItem;
 
 class PLATFORM_EXPORT HarfBuzzShaper final {
  public:
-  HarfBuzzShaper(const UChar*, unsigned length, TextDirection);
-  PassRefPtr<ShapeResult> shapeResult(const Font*) const;
+  HarfBuzzShaper(const UChar*, unsigned length);
+
+  // Shape a range, defined by the start and end parameters, of the string
+  // supplied to the constructor.
+  // The start and end positions should represent boundaries where a break may
+  // occur, such as at the beginning or end of lines or at element boundaries.
+  // If given arbitrary positions the results are not guaranteed to be correct.
+  // May be called multiple times; font and direction may vary between calls.
+  PassRefPtr<ShapeResult> shape(const Font*,
+                                TextDirection,
+                                unsigned start,
+                                unsigned end) const;
+
+  // Shape the entire string with a single font and direction.
+  // Equivalent to calling the range version with a start offset of zero and an
+  // end offset equal to the length.
+  PassRefPtr<ShapeResult> shape(const Font*, TextDirection) const;
+
   ~HarfBuzzShaper() {}
 
-  enum HolesQueueItemAction { HolesQueueNextFont, HolesQueueRange };
-
-  struct HolesQueueItem {
-    DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
-    HolesQueueItemAction m_action;
-    unsigned m_startIndex;
-    unsigned m_numCharacters;
-    HolesQueueItem(HolesQueueItemAction action, unsigned start, unsigned num)
-        : m_action(action), m_startIndex(start), m_numCharacters(num){};
-  };
-
  private:
+  using FeaturesVector = Vector<hb_feature_t, 6>;
+
+  // Shapes a single seqment, as identified by the RunSegmenterRange parameter,
+  // one or more times taking font fallback into account. The start and end
+  // parameters are for the entire text run, not the segment, and are used to
+  // determine pre- and post-context for shaping.
+  void shapeSegment(ShapeResult*,
+                    Deque<HolesQueueItem>*,
+                    hb_buffer_t*,
+                    const Font*,
+                    TextDirection,
+                    FeaturesVector*,
+                    RunSegmenter::RunSegmenterRange,
+                    unsigned start,
+                    unsigned end) const;
+
   bool extractShapeResults(hb_buffer_t*,
                            ShapeResult*,
                            bool& fontCycleQueued,
                            Deque<HolesQueueItem>*,
                            const HolesQueueItem&,
                            const Font*,
+                           TextDirection,
                            const SimpleFontData*,
                            UScriptCode,
                            bool isLastResort) const;
-  bool collectFallbackHintChars(const Deque<HolesQueueItem>&,
+  bool collectFallbackHintChars(const Deque<HolesQueueItem>*,
                                 Vector<UChar32>& hint) const;
 
-  const UChar* m_normalizedBuffer;
-  unsigned m_normalizedBufferLength;
-  TextDirection m_textDirection;
+  const UChar* m_text;
+  unsigned m_textLength;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
index 9b9ec10..7b43d4a 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp
@@ -43,8 +43,8 @@
 
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLatin) {
   String latinCommon = to16Bit("ABC DEF.", 8);
-  HarfBuzzShaper shaper(latinCommon.characters16(), 8, TextDirection::kLtr);
-  RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+  HarfBuzzShaper shaper(latinCommon.characters16(), 8);
+  RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr);
 
   ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting());
   ASSERT_TRUE(
@@ -56,8 +56,8 @@
 
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLeadingCommon) {
   String leadingCommon = to16Bit("... test", 8);
-  HarfBuzzShaper shaper(leadingCommon.characters16(), 8, TextDirection::kLtr);
-  RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+  HarfBuzzShaper shaper(leadingCommon.characters16(), 8);
+  RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr);
 
   ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting());
   ASSERT_TRUE(
@@ -81,8 +81,8 @@
       {"Not-defined Variants", {0x41, 0xDB40, 0xDDEF}, 3, HB_SCRIPT_LATIN},
   };
   for (auto& test : testlist) {
-    HarfBuzzShaper shaper(test.string, test.length, TextDirection::kLtr);
-    RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+    HarfBuzzShaper shaper(test.string, test.length);
+    RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr);
 
     EXPECT_EQ(1u, testInfo(result)->numberOfRunsForTesting()) << test.name;
     ASSERT_TRUE(
@@ -109,9 +109,8 @@
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommon) {
   UChar devanagariCommonString[] = {0x915, 0x94d, 0x930, 0x28, 0x20, 0x29};
   String devanagariCommonLatin(devanagariCommonString, 6);
-  HarfBuzzShaper shaper(devanagariCommonLatin.characters16(), 6,
-                        TextDirection::kLtr);
-  RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+  HarfBuzzShaper shaper(devanagariCommonLatin.characters16(), 6);
+  RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr);
 
   ASSERT_EQ(2u, testInfo(result)->numberOfRunsForTesting());
   ASSERT_TRUE(
@@ -130,8 +129,8 @@
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) {
   UChar devanagariCommonLatinString[] = {0x915, 0x94d, 0x930, 0x20,
                                          0x61,  0x62,  0x2E};
-  HarfBuzzShaper shaper(devanagariCommonLatinString, 7, TextDirection::kLtr);
-  RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+  HarfBuzzShaper shaper(devanagariCommonLatinString, 7);
+  RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr);
 
   ASSERT_EQ(3u, testInfo(result)->numberOfRunsForTesting());
   ASSERT_TRUE(
@@ -155,8 +154,8 @@
 
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) {
   UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
-  HarfBuzzShaper shaper(mixedString, 6, TextDirection::kLtr);
-  RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+  HarfBuzzShaper shaper(mixedString, 6);
+  RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr);
 
   ASSERT_EQ(4u, testInfo(result)->numberOfRunsForTesting());
   ASSERT_TRUE(
@@ -186,20 +185,20 @@
 
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) {
   UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
-  HarfBuzzShaper shaper(mixedString, 6, TextDirection::kLtr);
-  RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+  HarfBuzzShaper shaper(mixedString, 6);
+  RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kLtr);
   ASSERT_EQ(4u, testInfo(result)->numberOfRunsForTesting());
 
   // Shape again on the same shape object and check the number of runs.
   // Should be equal if no state was retained between shape calls.
-  RefPtr<ShapeResult> result2 = shaper.shapeResult(&font);
+  RefPtr<ShapeResult> result2 = shaper.shape(&font, TextDirection::kLtr);
   ASSERT_EQ(4u, testInfo(result2)->numberOfRunsForTesting());
 }
 
 TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) {
   UChar arabicString[] = {0x628, 0x64A, 0x629};
-  HarfBuzzShaper shaper(arabicString, 3, TextDirection::kRtl);
-  RefPtr<ShapeResult> result = shaper.shapeResult(&font);
+  HarfBuzzShaper shaper(arabicString, 3);
+  RefPtr<ShapeResult> result = shaper.shape(&font, TextDirection::kRtl);
 
   ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting());
   ASSERT_TRUE(
@@ -209,4 +208,61 @@
   EXPECT_EQ(HB_SCRIPT_ARABIC, script);
 }
 
+// This is a simplified test and doesn't accuratly reflect how the shape range
+// is to be used. If you instead of the string you imagine the following HTML:
+// <div>Hello <span>World</span>!</div>
+// It better reflects the intended use where the range given to each shape call
+// corresponds to the text content of a TextNode.
+TEST_F(HarfBuzzShaperTest, ShapeLatinSegment) {
+  String string = to16Bit("Hello World!", 12);
+  TextDirection direction = TextDirection::kLtr;
+
+  HarfBuzzShaper shaper(string.characters16(), 12);
+  RefPtr<ShapeResult> combined = shaper.shape(&font, direction);
+  RefPtr<ShapeResult> first = shaper.shape(&font, direction, 0, 6);
+  RefPtr<ShapeResult> second = shaper.shape(&font, direction, 6, 11);
+  RefPtr<ShapeResult> third = shaper.shape(&font, direction, 11, 12);
+
+  HarfBuzzShaper shaper2(string.characters16(), 6);
+  RefPtr<ShapeResult> firstReference = shaper2.shape(&font, direction);
+
+  HarfBuzzShaper shaper3(string.characters16() + 6, 5);
+  RefPtr<ShapeResult> secondReference = shaper3.shape(&font, direction);
+
+  HarfBuzzShaper shaper4(string.characters16() + 11, 1);
+  RefPtr<ShapeResult> thirdReference = shaper4.shape(&font, direction);
+
+  // Width of each segment should be the same when shaped using start and end
+  // offset as it is when shaping the three segments using separate shaper
+  // instances.
+  // A full pixel is needed for tolerance to account for kerning on some
+  // platforms.
+  ASSERT_NEAR(firstReference->width(), first->width(), 1);
+  ASSERT_NEAR(secondReference->width(), second->width(), 1);
+  ASSERT_NEAR(thirdReference->width(), third->width(), 1);
+
+  // Width of shape results for the entire string should match the combined
+  // shape results from the three segments.
+  float totalWidth = first->width() + second->width() + third->width();
+  ASSERT_NEAR(combined->width(), totalWidth, 1);
+}
+
+// Represents the case where a part of a cluster has a different color.
+// <div>0x647<span style="color: red;">0x64A</span></div>
+// This test requires context-aware shaping which hasn't been implemented yet.
+// See crbug.com/689155
+TEST_F(HarfBuzzShaperTest, DISABLED_ShapeArabicWithContext) {
+  UChar arabicString[] = {0x647, 0x64A};
+  HarfBuzzShaper shaper(arabicString, 2);
+
+  RefPtr<ShapeResult> combined = shaper.shape(&font, TextDirection::kRtl);
+
+  RefPtr<ShapeResult> first = shaper.shape(&font, TextDirection::kRtl, 0, 1);
+  RefPtr<ShapeResult> second = shaper.shape(&font, TextDirection::kRtl, 1, 2);
+
+  // Combined width should be the same when shaping the two characters
+  // separately as when shaping them combined.
+  ASSERT_NEAR(combined->width(), first->width() + second->width(), 0.1);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp
index 080411347..7019bc6a 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.cpp
@@ -18,9 +18,7 @@
                            unsigned bufferSize,
                            FontOrientation runOrientation)
     : m_bufferSize(bufferSize),
-      m_candidateRange({0, 0, USCRIPT_INVALID_CODE,
-                        OrientationIterator::OrientationKeep,
-                        FontFallbackPriority::Text}),
+      m_candidateRange(nullRange()),
       m_scriptRunIterator(
           WTF::makeUnique<ScriptRunIterator>(buffer, bufferSize)),
       m_orientationIterator(
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h
index 19b1b6b..00ae00d 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h
@@ -41,6 +41,11 @@
 
   bool consume(RunSegmenterRange*);
 
+  static RunSegmenterRange nullRange() {
+    return {0, 0, USCRIPT_INVALID_CODE, OrientationIterator::OrientationKeep,
+            FontFallbackPriority::Text};
+  }
+
  private:
   void consumeOrientationIteratorPastLastSplit();
   void consumeScriptIteratorPastLastSplit();
diff --git a/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.cpp b/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.cpp
index f46ef8d..b92da36 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.cpp
@@ -4,7 +4,9 @@
 
 #include "platform/graphics/CompositorFilterOperations.h"
 
+#include "platform/geometry/IntRect.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
+#include "ui/gfx/geometry/rect.h"
 
 namespace blink {
 
@@ -92,6 +94,17 @@
   return m_filterOperations.IsEmpty();
 }
 
+FloatRect CompositorFilterOperations::mapRect(
+    const FloatRect& inputRect) const {
+  gfx::Rect result =
+      m_filterOperations.MapRect(enclosingIntRect(inputRect), SkMatrix::I());
+  return FloatRect(result.x(), result.y(), result.width(), result.height());
+}
+
+bool CompositorFilterOperations::hasFilterThatMovesPixels() const {
+  return m_filterOperations.HasFilterThatMovesPixels();
+}
+
 bool CompositorFilterOperations::operator==(
     const CompositorFilterOperations& o) const {
   return m_filterOperations == o.m_filterOperations;
diff --git a/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.h b/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.h
index f364a24..eee54f00 100644
--- a/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.h
+++ b/third_party/WebKit/Source/platform/graphics/CompositorFilterOperations.h
@@ -7,6 +7,7 @@
 
 #include "cc/output/filter_operations.h"
 #include "platform/PlatformExport.h"
+#include "platform/geometry/FloatRect.h"
 #include "platform/geometry/IntPoint.h"
 #include "platform/graphics/Color.h"
 #include "third_party/skia/include/core/SkScalar.h"
@@ -41,6 +42,12 @@
   void clear();
   bool isEmpty() const;
 
+  // Returns a rect covering the destination pixels that can be affected by
+  // source pixels in |inputRect|.
+  FloatRect mapRect(const FloatRect& inputRect) const;
+
+  bool hasFilterThatMovesPixels() const;
+
   // For reference filters, this equality operator compares pointers of the
   // image_filter fields instead of their values.
   bool operator==(const CompositorFilterOperations&) const;
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
index 1a71628f..172b402 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
@@ -44,6 +44,8 @@
 #include "third_party/skia/include/core/SkData.h"
 #include "third_party/skia/include/core/SkRRect.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/core/SkUnPreMultiply.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
 #include "third_party/skia/include/effects/SkLumaColorFilter.h"
 #include "third_party/skia/include/effects/SkPictureImageFilter.h"
 #include "third_party/skia/include/pathops/SkPathOps.h"
@@ -331,6 +333,25 @@
   m_canvas->restore();
 }
 
+namespace {
+
+int adjustedFocusRingOffset(int offset) {
+#if OS(MACOSX)
+  return offset + 2;
+#else
+  return 0;
+#endif
+}
+
+}  // anonymous ns
+
+int GraphicsContext::focusRingOutsetExtent(int offset, int width) {
+  // Unlike normal outlines (whole width is outside of the offset), focus
+  // rings are drawn with the center of the path aligned with the offset, so
+  // only half of the width is outside of the offset.
+  return adjustedFocusRingOffset(offset) + (width + 1) / 2;
+}
+
 void GraphicsContext::drawFocusRingPath(const SkPath& path,
                                         const Color& color,
                                         float width) {
@@ -366,12 +387,12 @@
     return;
 
   SkRegion focusRingRegion;
-  offset = focusRingOffset(offset);
+  offset = adjustedFocusRingOffset(offset);
   for (unsigned i = 0; i < rectCount; i++) {
     SkIRect r = rects[i];
     if (r.isEmpty())
       continue;
-    r.inset(-offset, -offset);
+    r.outset(offset, offset);
     focusRingRegion.op(r, SkRegion::kUnion_Op);
   }
 
@@ -509,6 +530,93 @@
   m_canvas->drawLine(p1.x(), p1.y(), p2.x(), p2.y(), paint);
 }
 
+namespace {
+
+#if !OS(MACOSX)
+
+sk_sp<SkPicture> recordMarker(GraphicsContext::DocumentMarkerLineStyle style) {
+  SkColor color = (style == GraphicsContext::DocumentMarkerGrammarLineStyle)
+      ? SkColorSetRGB(0xC0, 0xC0, 0xC0)
+      : SK_ColorRED;
+
+  // Record the path equivalent to this legacy pattern:
+  //   X o   o X o   o X
+  //     o X o   o X o
+
+  static const float kW = 4;
+  static const float kH = 2;
+
+  // Adjust the phase such that f' == 0 is "pixel"-centered
+  // (for optimal rasterization at native rez).
+  SkPath path;
+  path.moveTo(kW * -3 / 8, kH * 3 / 4);
+  path.cubicTo(kW * -1 / 8, kH * 3 / 4,
+               kW * -1 / 8, kH * 1 / 4,
+               kW *  1 / 8, kH * 1 / 4);
+  path.cubicTo(kW * 3 / 8, kH * 1 / 4,
+               kW * 3 / 8, kH * 3 / 4,
+               kW * 5 / 8, kH * 3 / 4);
+  path.cubicTo(kW * 7 / 8, kH * 3 / 4,
+               kW * 7 / 8, kH * 1 / 4,
+               kW * 9 / 8, kH * 1 / 4);
+
+  SkPaint paint;
+  paint.setAntiAlias(true);
+  paint.setColor(color);
+  paint.setStyle(SkPaint::kStroke_Style);
+  paint.setStrokeWidth(kH * 1 / 2);
+
+  SkPictureRecorder recorder;
+  recorder.beginRecording(kW, kH);
+  recorder.getRecordingCanvas()->drawPath(path, paint);
+
+  return recorder.finishRecordingAsPicture();
+}
+
+#else  // OS(MACOSX)
+
+sk_sp<SkPicture> recordMarker(GraphicsContext::DocumentMarkerLineStyle style) {
+  SkColor color = (style == GraphicsContext::DocumentMarkerGrammarLineStyle)
+      ? SkColorSetRGB(0x6B, 0x6B, 0x6B)
+      : SkColorSetRGB(0xFB, 0x2D, 0x1D);
+
+  // Match the artwork used by the Mac.
+  static const float kW = 4;
+  static const float kH = 3;
+  static const float kR = 1.5f;
+
+  // top->bottom translucent gradient.
+  const SkColor colors[2] = {
+      SkColorSetARGB(0x48,
+                     SkColorGetR(color),
+                     SkColorGetG(color),
+                     SkColorGetB(color)),
+      color
+  };
+  const SkPoint pts[2] = {
+      SkPoint::Make(0, 0),
+      SkPoint::Make(0, 2 * kR)
+  };
+
+  SkPaint paint;
+  paint.setAntiAlias(true);
+  paint.setColor(color);
+  paint.setShader(SkGradientShader::MakeLinear(pts,
+                                               colors,
+                                               nullptr,
+                                               ARRAY_SIZE(colors),
+                                               SkShader::kClamp_TileMode));
+  SkPictureRecorder recorder;
+  recorder.beginRecording(kW, kH);
+  recorder.getRecordingCanvas()->drawCircle(kR, kR, kR, paint);
+
+  return recorder.finishRecordingAsPicture();
+}
+
+#endif  // OS(MACOSX)
+
+}  // anonymous ns
+
 void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt,
                                                 float width,
                                                 DocumentMarkerLineStyle style,
@@ -516,133 +624,44 @@
   if (contextDisabled())
     return;
 
-  // Use 2x resources for a device scale factor of 1.5 or above.
-  // This modifes the bitmaps used for the marker, not the overall
-  // scaling of the marker.
-  int deviceScaleFactor = m_deviceScaleFactor * zoom > 1.5f ? 2 : 1;
+  DEFINE_STATIC_LOCAL(SkPicture*, spellingMarker,
+                      (recordMarker(DocumentMarkerSpellingLineStyle).release()));
+  DEFINE_STATIC_LOCAL(SkPicture*, grammarMarker,
+                      (recordMarker(DocumentMarkerGrammarLineStyle).release()));
+  const auto& marker = style == DocumentMarkerSpellingLineStyle
+      ? spellingMarker
+      : grammarMarker;
 
-  // Create the pattern we'll use to draw the underline.
-  int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0;
-  static SkBitmap* misspellBitmap1x[2] = {0, 0};
-  static SkBitmap* misspellBitmap2x[2] = {0, 0};
-  SkBitmap** misspellBitmap =
-      deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x;
-  if (!misspellBitmap[index]) {
-#if OS(MACOSX)
-    // Match the artwork used by the Mac.
-    const int rowPixels = 4 * deviceScaleFactor;
-    const int colPixels = 3 * deviceScaleFactor;
-    SkBitmap bitmap;
-    if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels))
-      return;
-
-    bitmap.eraseARGB(0, 0, 0, 0);
-    const uint32_t transparentColor = 0x00000000;
-
-    if (deviceScaleFactor == 1) {
-      const uint32_t colors[2][6] = {{0x2a2a0600, 0x57571000, 0xa8a81b00,
-                                      0xbfbf1f00, 0x70701200, 0xe0e02400},
-                                     {0x2a0f0f0f, 0x571e1e1e, 0xa83d3d3d,
-                                      0xbf454545, 0x70282828, 0xe0515151}};
-
-      // Pattern: a b a   a b a
-      //          c d c   c d c
-      //          e f e   e f e
-      for (int x = 0; x < colPixels; ++x) {
-        uint32_t* row = bitmap.getAddr32(0, x);
-        row[0] = colors[index][x * 2];
-        row[1] = colors[index][x * 2 + 1];
-        row[2] = colors[index][x * 2];
-        row[3] = transparentColor;
-      }
-    } else if (deviceScaleFactor == 2) {
-      const uint32_t colors[2][18] = {
-          {0x0a090101, 0x33320806, 0x55540f0a, 0x37360906, 0x6e6c120c,
-           0x6e6c120c, 0x7674140d, 0x8d8b1810, 0x8d8b1810, 0x96941a11,
-           0xb3b01f15, 0xb3b01f15, 0x6d6b130c, 0xd9d62619, 0xd9d62619,
-           0x19180402, 0x7c7a150e, 0xcecb2418},
-          {0x0a020202, 0x33141414, 0x55232323, 0x37161616, 0x6e2e2e2e,
-           0x6e2e2e2e, 0x76313131, 0x8d3a3a3a, 0x8d3a3a3a, 0x963e3e3e,
-           0xb34b4b4b, 0xb34b4b4b, 0x6d2d2d2d, 0xd95b5b5b, 0xd95b5b5b,
-           0x19090909, 0x7c343434, 0xce575757}};
-
-      // Pattern: a b c c b a
-      //          d e f f e d
-      //          g h j j h g
-      //          k l m m l k
-      //          n o p p o n
-      //          q r s s r q
-      for (int x = 0; x < colPixels; ++x) {
-        uint32_t* row = bitmap.getAddr32(0, x);
-        row[0] = colors[index][x * 3];
-        row[1] = colors[index][x * 3 + 1];
-        row[2] = colors[index][x * 3 + 2];
-        row[3] = colors[index][x * 3 + 2];
-        row[4] = colors[index][x * 3 + 1];
-        row[5] = colors[index][x * 3];
-        row[6] = transparentColor;
-        row[7] = transparentColor;
-      }
-    } else
-      ASSERT_NOT_REACHED();
-
-    misspellBitmap[index] = new SkBitmap(bitmap);
-#else
-    // We use a 2-pixel-high misspelling indicator because that seems to be
-    // what Blink is designed for, and how much room there is in a typical
-    // page for it.
-    const int rowPixels =
-        32 * deviceScaleFactor;  // Must be multiple of 4 for pattern below.
-    const int colPixels = 2 * deviceScaleFactor;
-    SkBitmap bitmap;
-    if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels))
-      return;
-
-    bitmap.eraseARGB(0, 0, 0, 0);
-    if (deviceScaleFactor == 1)
-      draw1xMarker(&bitmap, index);
-    else if (deviceScaleFactor == 2)
-      draw2xMarker(&bitmap, index);
-    else
-      ASSERT_NOT_REACHED();
-
-    misspellBitmap[index] = new SkBitmap(bitmap);
-#endif
-  }
-
-#if OS(MACOSX)
   // Position already includes zoom and device scale factor.
   SkScalar originX = WebCoreFloatToSkScalar(pt.x());
   SkScalar originY = WebCoreFloatToSkScalar(pt.y());
 
+#if OS(MACOSX)
   // Make sure to draw only complete dots, and finish inside the marked text.
-  float rowPixels = misspellBitmap[index]->width() * zoom / deviceScaleFactor;
-  float dotCount = floorf(width / rowPixels);
-  width = dotCount * rowPixels;
+  width -= fmodf(width, marker->cullRect().width() * zoom);
 #else
-  SkScalar originX = WebCoreFloatToSkScalar(pt.x());
-
   // Offset it vertically by 1 so that there's some space under the text.
-  SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1;
+  originY += 1;
 #endif
 
-  SkMatrix localMatrix;
-  localMatrix.setScale(zoom / deviceScaleFactor, zoom / deviceScaleFactor);
-  localMatrix.postTranslate(originX, originY);
+  const auto rect = SkRect::MakeWH(width, marker->cullRect().height() * zoom);
+  const auto localMatrix = SkMatrix::MakeScale(zoom, zoom);
 
   PaintFlags paint;
-  paint.setShader(WrapSkShader(SkShader::MakeBitmapShader(
-      *misspellBitmap[index], SkShader::kRepeat_TileMode,
-      SkShader::kRepeat_TileMode, &localMatrix)));
+  paint.setAntiAlias(true);
+  paint.setShader(WrapSkShader(
+      SkShader::MakePictureShader(sk_ref_sp(marker),
+                                  SkShader::kRepeat_TileMode,
+                                  SkShader::kClamp_TileMode,
+                                  &localMatrix,
+                                  nullptr)));
 
-  SkRect rect;
-  rect.set(
-      originX, originY, originX + WebCoreFloatToSkScalar(width),
-      originY +
-          SkIntToScalar(misspellBitmap[index]->height() / deviceScaleFactor) *
-              zoom);
-
-  drawRect(rect, paint);
+  // Apply the origin translation as a global transform.  This ensures that the
+  // shader local matrix depends solely on zoom => Skia can reuse the same
+  // cached tile for all markers at a given zoom level.
+  SkAutoCanvasRestore acr(m_canvas, true);
+  m_canvas->translate(originX, originY);
+  m_canvas->drawRect(rect, paint);
 }
 
 void GraphicsContext::drawLineForText(const FloatPoint& pt, float width) {
@@ -1330,95 +1349,4 @@
   return nullptr;
 }
 
-#if !OS(MACOSX)
-void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index) {
-  const SkPMColor lineColor = lineColors(index);
-  const SkPMColor antiColor1 = antiColors1(index);
-  const SkPMColor antiColor2 = antiColors2(index);
-
-  uint32_t* row1 = bitmap->getAddr32(0, 0);
-  uint32_t* row2 = bitmap->getAddr32(0, 1);
-  uint32_t* row3 = bitmap->getAddr32(0, 2);
-  uint32_t* row4 = bitmap->getAddr32(0, 3);
-
-  // Pattern: X0o   o0X0o   o0
-  //          XX0o o0XXX0o o0X
-  //           o0XXX0o o0XXX0o
-  //            o0X0o   o0X0o
-  const SkPMColor row1Color[] = {lineColor, antiColor1, antiColor2, 0,
-                                 0,         0,          antiColor2, antiColor1};
-  const SkPMColor row2Color[] = {lineColor, lineColor,  antiColor1, antiColor2,
-                                 0,         antiColor2, antiColor1, lineColor};
-  const SkPMColor row3Color[] = {0,         antiColor2, antiColor1, lineColor,
-                                 lineColor, lineColor,  antiColor1, antiColor2};
-  const SkPMColor row4Color[] = {0,         0,          antiColor2, antiColor1,
-                                 lineColor, antiColor1, antiColor2, 0};
-
-  for (int x = 0; x < bitmap->width() + 8; x += 8) {
-    int count = std::min(bitmap->width() - x, 8);
-    if (count > 0) {
-      memcpy(row1 + x, row1Color, count * sizeof(SkPMColor));
-      memcpy(row2 + x, row2Color, count * sizeof(SkPMColor));
-      memcpy(row3 + x, row3Color, count * sizeof(SkPMColor));
-      memcpy(row4 + x, row4Color, count * sizeof(SkPMColor));
-    }
-  }
-}
-
-void GraphicsContext::draw1xMarker(SkBitmap* bitmap, int index) {
-  const uint32_t lineColor = lineColors(index);
-  const uint32_t antiColor = antiColors2(index);
-
-  // Pattern: X o   o X o   o X
-  //            o X o   o X o
-  uint32_t* row1 = bitmap->getAddr32(0, 0);
-  uint32_t* row2 = bitmap->getAddr32(0, 1);
-  for (int x = 0; x < bitmap->width(); x++) {
-    switch (x % 4) {
-      case 0:
-        row1[x] = lineColor;
-        break;
-      case 1:
-        row1[x] = antiColor;
-        row2[x] = antiColor;
-        break;
-      case 2:
-        row2[x] = lineColor;
-        break;
-      case 3:
-        row1[x] = antiColor;
-        row2[x] = antiColor;
-        break;
-    }
-  }
-}
-
-SkPMColor GraphicsContext::lineColors(int index) {
-  static const SkPMColor colors[] = {
-      SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00),  // Opaque red.
-      SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0)   // Opaque gray.
-  };
-
-  return colors[index];
-}
-
-SkPMColor GraphicsContext::antiColors1(int index) {
-  static const SkPMColor colors[] = {
-      SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00),  // Semitransparent red.
-      SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0)   // Semitransparent gray.
-  };
-
-  return colors[index];
-}
-
-SkPMColor GraphicsContext::antiColors2(int index) {
-  static const SkPMColor colors[] = {
-      SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00),  // More transparent red
-      SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0)   // More transparent gray
-  };
-
-  return colors[index];
-}
-#endif
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsContext.h b/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
index 448c49fb..4819495f 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
@@ -47,7 +47,6 @@
 #include "wtf/Noncopyable.h"
 #include <memory>
 
-class SkBitmap;
 class SkPath;
 class SkRRect;
 struct SkRect;
@@ -359,12 +358,7 @@
                                           float strokeWidth,
                                           StrokeStyle);
 
-  static int focusRingOutsetExtent(int offset, int width) {
-    // Unlike normal outlines (whole width is outside of the offset), focus
-    // rings are drawn with the center of the path aligned with the offset, so
-    // only half of the width is outside of the offset.
-    return focusRingOffset(offset) + (width + 1) / 2;
-  }
+  static int focusRingOutsetExtent(int offset, int width);
 
 #if DCHECK_IS_ON()
   void setInDrawingRecorder(bool);
@@ -383,17 +377,6 @@
   template <typename DrawTextFunc>
   void drawTextPasses(const DrawTextFunc&);
 
-#if OS(MACOSX)
-  static inline int focusRingOffset(int offset) { return offset + 2; }
-#else
-  static inline int focusRingOffset(int offset) { return 0; }
-  static SkPMColor lineColors(int);
-  static SkPMColor antiColors1(int);
-  static SkPMColor antiColors2(int);
-  static void draw1xMarker(SkBitmap*, int);
-  static void draw2xMarker(SkBitmap*, int);
-#endif
-
   void saveLayer(const SkRect* bounds, const PaintFlags*);
   void restoreLayer();
 
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index f496615..b259565 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -1152,21 +1152,12 @@
   m_scrollableArea = scrollableArea;
 
   // VisualViewport scrolling may involve pinch zoom and gets routed through
-  // WebViewImpl explicitly rather than via GraphicsLayer::didScroll since it
+  // WebViewImpl explicitly rather than via ScrollableArea::didScroll since it
   // needs to be set in tandem with the page scale delta.
   if (isVisualViewport)
-    m_layer->layer()->setScrollClient(0);
+    m_layer->layer()->setScrollClient(nullptr);
   else
-    m_layer->layer()->setScrollClient(this);
-}
-
-void GraphicsLayer::didScroll() {
-  if (m_scrollableArea) {
-    ScrollOffset newOffset =
-        toFloatSize(m_layer->layer()->scrollPositionDouble() -
-                    m_scrollableArea->scrollOrigin());
-    m_scrollableArea->setScrollOffset(newOffset, CompositorScroll);
-  }
+    m_layer->layer()->setScrollClient(scrollableArea);
 }
 
 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
index f0116389..11b7fe69 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -48,7 +48,6 @@
 #include "platform/transforms/TransformationMatrix.h"
 #include "public/platform/WebContentLayer.h"
 #include "public/platform/WebImageLayer.h"
-#include "public/platform/WebLayerScrollClient.h"
 #include "public/platform/WebLayerStickyPositionConstraint.h"
 #include "third_party/skia/include/core/SkFilterQuality.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
@@ -70,9 +69,7 @@
 
 // GraphicsLayer is an abstraction for a rendering surface with backing store,
 // which may have associated transformation and animations.
-
-class PLATFORM_EXPORT GraphicsLayer : public WebLayerScrollClient,
-                                      public cc::LayerClient,
+class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
                                       public DisplayItemClient {
   WTF_MAKE_NONCOPYABLE(GraphicsLayer);
   USING_FAST_MALLOC(GraphicsLayer);
@@ -254,9 +251,6 @@
   void paint(const IntRect* interestRect,
              GraphicsContext::DisabledMode = GraphicsContext::NothingDisabled);
 
-  // WebLayerScrollClient implementation.
-  void didScroll() override;
-
   // cc::LayerClient implementation.
   std::unique_ptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(
       cc::Layer*) override;
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
index 08c8864..7dd4b73 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
@@ -204,16 +204,4 @@
   ScrollOffset m_scrollOffset;
 };
 
-TEST_F(GraphicsLayerTest, applyScrollToScrollableArea) {
-  FakeScrollableArea* scrollableArea = FakeScrollableArea::create();
-  m_graphicsLayer->setScrollableArea(scrollableArea, false);
-
-  WebDoublePoint scrollPosition(7, 9);
-  m_platformLayer->setScrollPositionDouble(scrollPosition);
-  m_graphicsLayer->didScroll();
-
-  EXPECT_FLOAT_EQ(scrollPosition.x, scrollableArea->getScrollOffset().width());
-  EXPECT_FLOAT_EQ(scrollPosition.y, scrollableArea->getScrollOffset().height());
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp
index 9ca9da31..4a9bff9 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp
@@ -18,6 +18,14 @@
   return root;
 }
 
+FloatRect EffectPaintPropertyNode::mapRect(const FloatRect& inputRect) const {
+  FloatRect rect = inputRect;
+  rect.moveBy(-m_paintOffset);
+  FloatRect result = m_filter.mapRect(rect);
+  result.moveBy(m_paintOffset);
+  return result;
+}
+
 cc::Layer* EffectPaintPropertyNode::ensureDummyLayer() const {
   if (m_dummyLayer)
     return m_dummyLayer.get();
@@ -28,12 +36,14 @@
 String EffectPaintPropertyNode::toString() const {
   return String::format(
       "parent=%p localTransformSpace=%p outputClip=%p opacity=%f filter=%s "
-      "blendMode=%s directCompositingReasons=%s compositorElementId=(%d, %d)",
+      "blendMode=%s directCompositingReasons=%s compositorElementId=(%d, %d) "
+      "paintOffset=%s",
       m_parent.get(), m_localTransformSpace.get(), m_outputClip.get(),
       m_opacity, m_filter.toString().ascii().data(),
       SkBlendMode_Name(m_blendMode),
       compositingReasonsAsString(m_directCompositingReasons).ascii().data(),
-      m_compositorElementId.primaryId, m_compositorElementId.secondaryId);
+      m_compositorElementId.primaryId, m_compositorElementId.secondaryId,
+      m_paintOffset.toString().ascii().data());
 }
 
 #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
index f62059d..b96d5299 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
@@ -39,11 +39,12 @@
       float opacity,
       SkBlendMode blendMode,
       CompositingReasons directCompositingReasons = CompositingReasonNone,
-      const CompositorElementId& compositorElementId = CompositorElementId()) {
+      const CompositorElementId& compositorElementId = CompositorElementId(),
+      const FloatPoint& paintOffset = FloatPoint()) {
     return adoptRef(new EffectPaintPropertyNode(
         std::move(parent), std::move(localTransformSpace),
         std::move(outputClip), std::move(filter), opacity, blendMode,
-        directCompositingReasons, compositorElementId));
+        directCompositingReasons, compositorElementId, paintOffset));
   }
 
   void update(
@@ -54,7 +55,8 @@
       float opacity,
       SkBlendMode blendMode,
       CompositingReasons directCompositingReasons = CompositingReasonNone,
-      CompositorElementId compositorElementId = CompositorElementId()) {
+      const CompositorElementId& compositorElementId = CompositorElementId(),
+      const FloatPoint& paintOffset = FloatPoint()) {
     DCHECK(!isRoot());
     DCHECK(parent != this);
     m_parent = parent;
@@ -65,6 +67,7 @@
     m_blendMode = blendMode;
     m_directCompositingReasons = directCompositingReasons;
     m_compositorElementId = compositorElementId;
+    m_paintOffset = paintOffset;
   }
 
   const TransformPaintPropertyNode* localTransformSpace() const {
@@ -80,6 +83,14 @@
   const EffectPaintPropertyNode* parent() const { return m_parent.get(); }
   bool isRoot() const { return !m_parent; }
 
+  bool hasFilterThatMovesPixels() const {
+    return m_filter.hasFilterThatMovesPixels();
+  }
+
+  // Returns a rect covering the pixels that can be affected by pixels in
+  // |inputRect|. The rects are in the space of localTransformSpace.
+  FloatRect mapRect(const FloatRect& inputRect) const;
+
   cc::Layer* ensureDummyLayer() const;
 
 #if DCHECK_IS_ON()
@@ -88,7 +99,8 @@
   PassRefPtr<EffectPaintPropertyNode> clone() const {
     return adoptRef(new EffectPaintPropertyNode(
         m_parent, m_localTransformSpace, m_outputClip, m_filter, m_opacity,
-        m_blendMode, m_directCompositingReasons, m_compositorElementId));
+        m_blendMode, m_directCompositingReasons, m_compositorElementId,
+        m_paintOffset));
   }
 
   // The equality operator is used by FindPropertiesNeedingUpdate.h for checking
@@ -101,7 +113,8 @@
            m_filter.equalsIgnoringReferenceFilters(o.m_filter) &&
            m_opacity == o.m_opacity && m_blendMode == o.m_blendMode &&
            m_directCompositingReasons == o.m_directCompositingReasons &&
-           m_compositorElementId == o.m_compositorElementId;
+           m_compositorElementId == o.m_compositorElementId &&
+           m_paintOffset == o.m_paintOffset;
   }
 
   String toTreeString() const;
@@ -130,7 +143,8 @@
       float opacity,
       SkBlendMode blendMode,
       CompositingReasons directCompositingReasons,
-      CompositorElementId compositorElementId)
+      CompositorElementId compositorElementId,
+      const FloatPoint& paintOffset)
       : m_parent(parent),
         m_localTransformSpace(localTransformSpace),
         m_outputClip(outputClip),
@@ -138,7 +152,8 @@
         m_opacity(opacity),
         m_blendMode(blendMode),
         m_directCompositingReasons(directCompositingReasons),
-        m_compositorElementId(compositorElementId) {}
+        m_compositorElementId(compositorElementId),
+        m_paintOffset(paintOffset) {}
 
   RefPtr<const EffectPaintPropertyNode> m_parent;
   // The local transform space serves two purposes:
@@ -168,6 +183,11 @@
 
   CompositingReasons m_directCompositingReasons;
   CompositorElementId m_compositorElementId;
+
+  // The offset of the effect's local space in m_localTransformSpace. Some
+  // effects e.g. reflection need this to apply geometry effects in the local
+  // space.
+  FloatPoint m_paintOffset;
 };
 
 // Redeclared here to avoid ODR issues.
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
index e61aa3b..7b39445 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
@@ -94,6 +94,11 @@
     return rect;
   }
 
+  if (localState.effect() != ancestorState.effect()) {
+    return slowLocalToAncestorVisualRectWithEffects(rect, localState,
+                                                    ancestorState, success);
+  }
+
   const auto& transformMatrix = localToAncestorMatrixInternal(
       localState.transform(), ancestorState.transform(), success);
   if (!success)
@@ -119,6 +124,47 @@
   return clipRect;
 }
 
+FloatClipRect GeometryMapper::slowLocalToAncestorVisualRectWithEffects(
+    const FloatRect& rect,
+    const PropertyTreeState& localState,
+    const PropertyTreeState& ancestorState,
+    bool& success) {
+  PropertyTreeState lastTransformAndClipState(localState.transform(),
+                                              localState.clip(), nullptr);
+  FloatClipRect result(rect);
+
+  for (const auto* effect = localState.effect();
+       effect && effect != ancestorState.effect(); effect = effect->parent()) {
+    if (!effect->hasFilterThatMovesPixels())
+      continue;
+
+    PropertyTreeState transformAndClipState(effect->localTransformSpace(),
+                                            effect->outputClip(), nullptr);
+    bool hasRadius = result.hasRadius();
+    result = sourceToDestinationVisualRectInternal(
+        result.rect(), lastTransformAndClipState, transformAndClipState,
+        success);
+    hasRadius |= result.hasRadius();
+    if (!success) {
+      result.setHasRadius(hasRadius);
+      return result;
+    }
+
+    result = effect->mapRect(result.rect());
+    result.setHasRadius(hasRadius);
+    lastTransformAndClipState = transformAndClipState;
+  }
+
+  PropertyTreeState finalTransformAndClipState(ancestorState.transform(),
+                                               ancestorState.clip(), nullptr);
+  bool hasRadius = result.hasRadius();
+  result = sourceToDestinationVisualRectInternal(
+      result.rect(), lastTransformAndClipState, finalTransformAndClipState,
+      success);
+  result.setHasRadius(hasRadius || result.hasRadius());
+  return result;
+}
+
 FloatRect GeometryMapper::localToAncestorRect(
     const FloatRect& rect,
     const TransformPaintPropertyNode* localTransformNode,
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h
index c0d63d6..85f6191 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h
@@ -177,6 +177,12 @@
       const PropertyTreeState& ancestorState,
       bool& success);
 
+  FloatClipRect slowLocalToAncestorVisualRectWithEffects(
+      const FloatRect&,
+      const PropertyTreeState& localState,
+      const PropertyTreeState& ancestorState,
+      bool& success);
+
   // Returns the precomputed data if already set, or adds and memoizes a new
   // PrecomputedDataForAncestor otherwise.
   PrecomputedDataForAncestor& getPrecomputedDataForAncestor(
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
index 671eadd1..0630a5f 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
@@ -6,6 +6,8 @@
 
 #include "platform/geometry/GeometryTestHelpers.h"
 #include "platform/geometry/LayoutRect.h"
+#include "platform/graphics/BoxReflection.h"
+#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
 #include "platform/graphics/paint/ClipPaintPropertyNode.h"
 #include "platform/graphics/paint/EffectPaintPropertyNode.h"
 #include "platform/graphics/paint/TransformPaintPropertyNode.h"
@@ -699,4 +701,78 @@
             lowestCommonAncestor(child1.get(), child2.get()));
 }
 
+TEST_F(GeometryMapperTest, FilterWithClipsAndTransforms) {
+  RefPtr<TransformPaintPropertyNode> transformAboveEffect =
+      TransformPaintPropertyNode::create(rootPropertyTreeState().transform(),
+                                         TransformationMatrix().scale(3),
+                                         FloatPoint3D());
+  RefPtr<TransformPaintPropertyNode> transformBelowEffect =
+      TransformPaintPropertyNode::create(transformAboveEffect,
+                                         TransformationMatrix().scale(2),
+                                         FloatPoint3D());
+
+  // This clip is between transformAboveEffect and the effect.
+  RefPtr<ClipPaintPropertyNode> clipAboveEffect = ClipPaintPropertyNode::create(
+      rootPropertyTreeState().clip(), transformAboveEffect,
+      FloatRoundedRect(-100, -100, 200, 200));
+  // This clip is between the effect and transformBelowEffect.
+  RefPtr<ClipPaintPropertyNode> clipBelowEffect =
+      ClipPaintPropertyNode::create(clipAboveEffect, transformAboveEffect,
+                                    FloatRoundedRect(10, 10, 200, 200));
+
+  CompositorFilterOperations filters;
+  filters.appendBlurFilter(20);
+  RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::create(
+      rootPropertyTreeState().effect(), transformAboveEffect, clipAboveEffect,
+      filters, 1.0, SkBlendMode::kSrcOver);
+
+  PropertyTreeState localState(transformBelowEffect.get(),
+                               clipBelowEffect.get(), effect.get());
+
+  FloatRect input(0, 0, 50, 50);
+  // 1. transformBelowEffect
+  FloatRect output = transformBelowEffect->matrix().mapRect(input);
+  // 2. clipBelowEffect
+  output.intersect(clipBelowEffect->clipRect().rect());
+  EXPECT_EQ(FloatRect(10, 10, 90, 90), output);
+  // 3. effect (the outset is 3 times of blur amount).
+  output = filters.mapRect(output);
+  EXPECT_EQ(FloatRect(-50, -50, 210, 210), output);
+  // 4. clipAboveEffect
+  output.intersect(clipAboveEffect->clipRect().rect());
+  EXPECT_EQ(FloatRect(-50, -50, 150, 150), output);
+  // 5. transformAboveEffect
+  output = transformAboveEffect->matrix().mapRect(output);
+  EXPECT_EQ(FloatRect(-150, -150, 450, 450), output);
+
+  bool hasRadius = false;
+  CHECK_MAPPINGS(
+      input, output, FloatRect(0, 0, 300, 300),
+      transformAboveEffect->matrix() * transformBelowEffect->matrix(),
+      FloatRect(30, 30, 270, 270), localState, rootPropertyTreeState(),
+      hasRadius);
+}
+
+TEST_F(GeometryMapperTest, ReflectionWithPaintOffset) {
+  CompositorFilterOperations filters;
+  filters.appendReferenceFilter(SkiaImageFilterBuilder::buildBoxReflectFilter(
+      BoxReflection(BoxReflection::HorizontalReflection, 0), nullptr));
+  RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::create(
+      rootPropertyTreeState().effect(), rootPropertyTreeState().transform(),
+      rootPropertyTreeState().clip(), filters, 1.0, SkBlendMode::kSrcOver,
+      CompositingReasonNone, CompositorElementId(), FloatPoint(100, 100));
+
+  PropertyTreeState localState = rootPropertyTreeState();
+  localState.setEffect(effect);
+
+  FloatRect input(100, 100, 50, 50);
+  // Reflection is at (50, 100, 50, 50).
+  FloatRect output(50, 100, 100, 50);
+
+  bool hasRadius = false;
+  CHECK_MAPPINGS(input, output, input, TransformationMatrix(),
+                 ClipPaintPropertyNode::root()->clipRect().rect(), localState,
+                 rootPropertyTreeState(), hasRadius);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/BlinkGC.h b/third_party/WebKit/Source/platform/heap/BlinkGC.h
index 0800e22..6d13697 100644
--- a/third_party/WebKit/Source/platform/heap/BlinkGC.h
+++ b/third_party/WebKit/Source/platform/heap/BlinkGC.h
@@ -81,6 +81,7 @@
     ForcedGC,
     MemoryPressureGC,
     PageNavigationGC,
+    ThreadTerminationGC,
     NumberOfGCReason,
   };
 
diff --git a/third_party/WebKit/Source/platform/heap/GCInfo.cpp b/third_party/WebKit/Source/platform/heap/GCInfo.cpp
index 64d1935..ba69e2a 100644
--- a/third_party/WebKit/Source/platform/heap/GCInfo.cpp
+++ b/third_party/WebKit/Source/platform/heap/GCInfo.cpp
@@ -68,8 +68,6 @@
 #if !defined(COMPONENT_BUILD)
   // On component builds we cannot compare the gcInfos as they are statically
   // defined in each of the components and hence will not match.
-  BasePage* page = pageFromObject(payload);
-  ASSERT(!page->orphaned());
   ASSERT(HeapObjectHeader::fromPayload(payload)->gcInfoIndex() == gcInfoIndex);
 #endif
 }
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp
index 102854f..090aebee 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -189,7 +189,6 @@
       m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)),
       m_safePointBarrier(WTF::makeUnique<SafePointBarrier>()),
       m_freePagePool(WTF::wrapUnique(new FreePagePool)),
-      m_orphanedPagePool(WTF::wrapUnique(new OrphanedPagePool)),
       m_markingStack(CallbackStack::create()),
       m_postMarkingCallbackStack(CallbackStack::create()),
       m_globalWeakCallbackStack(CallbackStack::create()),
@@ -282,7 +281,6 @@
 
   if (BasePage* page = lookupPageForAddress(address)) {
     ASSERT(page->contains(address));
-    ASSERT(!page->orphaned());
     ASSERT(!m_heapDoesNotContainCache->lookup(address));
     DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap());
     page->checkAndMarkPointer(visitor, address);
@@ -310,7 +308,6 @@
 
   if (BasePage* page = lookupPageForAddress(address)) {
     DCHECK(page->contains(address));
-    DCHECK(!page->orphaned());
     DCHECK(!m_heapDoesNotContainCache->lookup(address));
     DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap());
     page->checkAndMarkPointer(visitor, address, callback);
@@ -325,8 +322,6 @@
 void ThreadHeap::pushTraceCallback(void* object, TraceCallback callback) {
   ASSERT(ThreadState::current()->isInGC());
 
-  // Trace should never reach an orphaned page.
-  ASSERT(!getOrphanedPagePool()->contains(object));
   CallbackStack::Item* slot = m_markingStack->allocateEntry();
   *slot = CallbackStack::Item(object, callback);
 }
@@ -342,8 +337,6 @@
 void ThreadHeap::pushPostMarkingCallback(void* object, TraceCallback callback) {
   ASSERT(ThreadState::current()->isInGC());
 
-  // Trace should never reach an orphaned page.
-  ASSERT(!getOrphanedPagePool()->contains(object));
   CallbackStack::Item* slot = m_postMarkingCallbackStack->allocateEntry();
   *slot = CallbackStack::Item(object, callback);
 }
@@ -359,8 +352,6 @@
 void ThreadHeap::pushGlobalWeakCallback(void** cell, WeakCallback callback) {
   ASSERT(ThreadState::current()->isInGC());
 
-  // Trace should never reach an orphaned page.
-  ASSERT(!getOrphanedPagePool()->contains(cell));
   CallbackStack::Item* slot = m_globalWeakCallbackStack->allocateEntry();
   *slot = CallbackStack::Item(cell, callback);
 }
@@ -370,8 +361,6 @@
                                              WeakCallback callback) {
   ASSERT(ThreadState::current()->isInGC());
 
-  // Trace should never reach an orphaned page.
-  ASSERT(!getOrphanedPagePool()->contains(object));
   ThreadState* state = pageFromObject(object)->arena()->getThreadState();
   state->pushThreadLocalWeakCallback(closure, callback);
 }
@@ -389,8 +378,6 @@
                                    EphemeronCallback iterationDoneCallback) {
   ASSERT(ThreadState::current()->isInGC());
 
-  // Trace should never reach an orphaned page.
-  ASSERT(!getOrphanedPagePool()->contains(table));
   CallbackStack::Item* slot = m_ephemeronStack->allocateEntry();
   *slot = CallbackStack::Item(table, iterationCallback);
 
@@ -645,8 +632,7 @@
 BasePage* ThreadHeap::lookupPageForAddress(Address address) {
   ASSERT(ThreadState::current()->isInGC());
   if (PageMemoryRegion* region = m_regionTree->lookup(address)) {
-    BasePage* page = region->pageFromAddress(address);
-    return page && !page->orphaned() ? page : nullptr;
+    return region->pageFromAddress(address);
   }
   return nullptr;
 }
diff --git a/third_party/WebKit/Source/platform/heap/Heap.h b/third_party/WebKit/Source/platform/heap/Heap.h
index e3a0ebb..7ce5d0e 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.h
+++ b/third_party/WebKit/Source/platform/heap/Heap.h
@@ -48,7 +48,6 @@
 namespace blink {
 
 class FreePagePool;
-class OrphanedPagePool;
 
 class PLATFORM_EXPORT HeapAllocHooks {
  public:
@@ -444,7 +443,6 @@
   void flushHeapDoesNotContainCache();
 
   FreePagePool* getFreePagePool() { return m_freePagePool.get(); }
-  OrphanedPagePool* getOrphanedPagePool() { return m_orphanedPagePool.get(); }
 
   // This look-up uses the region search tree and a negative contains cache to
   // provide an efficient mapping from arbitrary addresses to the containing
@@ -482,7 +480,6 @@
   std::unique_ptr<HeapDoesNotContainCache> m_heapDoesNotContainCache;
   std::unique_ptr<SafePointBarrier> m_safePointBarrier;
   std::unique_ptr<FreePagePool> m_freePagePool;
-  std::unique_ptr<OrphanedPagePool> m_orphanedPagePool;
   std::unique_ptr<CallbackStack> m_markingStack;
   std::unique_ptr<CallbackStack> m_postMarkingCallbackStack;
   std::unique_ptr<CallbackStack> m_globalWeakCallbackStack;
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.cpp b/third_party/WebKit/Source/platform/heap/HeapPage.cpp
index acb4f92..47d5a09 100644
--- a/third_party/WebKit/Source/platform/heap/HeapPage.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.cpp
@@ -116,17 +116,15 @@
   ASSERT(!m_firstUnsweptPage);
 }
 
-void BaseArena::cleanupPages() {
+void BaseArena::removeAllPages() {
   clearFreeLists();
 
   ASSERT(!m_firstUnsweptPage);
-  // Add the BaseArena's pages to the orphanedPagePool.
-  for (BasePage* page = m_firstPage; page; page = page->next()) {
-    getThreadState()->heap().heapStats().decreaseAllocatedSpace(page->size());
-    getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage(
-        arenaIndex(), page);
+  while (m_firstPage) {
+    BasePage* page = m_firstPage;
+    page->unlink(&m_firstPage);
+    page->removeFromHeap();
   }
-  m_firstPage = nullptr;
 }
 
 void BaseArena::takeSnapshot(const String& dumpBaseName,
@@ -657,23 +655,9 @@
 void NormalPageArena::freePage(NormalPage* page) {
   getThreadState()->heap().heapStats().decreaseAllocatedSpace(page->size());
 
-  if (page->terminating()) {
-    // The thread is shutting down and this page is being removed as a part
-    // of the thread local GC.  In that case the object could be traced in
-    // the next global GC if there is a dangling pointer from a live thread
-    // heap to this dead thread heap.  To guard against this, we put the
-    // page into the orphaned page pool and zap the page memory.  This
-    // ensures that tracing the dangling pointer in the next global GC just
-    // crashes instead of causing use-after-frees.  After the next global
-    // GC, the orphaned pages are removed.
-    getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage(
-        arenaIndex(), page);
-  } else {
-    PageMemory* memory = page->storage();
-    page->~NormalPage();
-    getThreadState()->heap().getFreePagePool()->addFreePage(arenaIndex(),
-                                                            memory);
-  }
+  PageMemory* memory = page->storage();
+  page->~NormalPage();
+  getThreadState()->heap().getFreePagePool()->addFreePage(arenaIndex(), memory);
 }
 
 bool NormalPageArena::coalesce() {
@@ -1055,24 +1039,9 @@
   ASAN_UNPOISON_MEMORY_REGION(object->getAddress() + object->size(),
                               allocationGranularity);
 
-  if (object->terminating()) {
-    ASSERT(ThreadState::current()->isTerminating());
-    // The thread is shutting down and this page is being removed as a part
-    // of the thread local GC.  In that case the object could be traced in
-    // the next global GC if there is a dangling pointer from a live thread
-    // heap to this dead thread heap.  To guard against this, we put the
-    // page into the orphaned page pool and zap the page memory.  This
-    // ensures that tracing the dangling pointer in the next global GC just
-    // crashes instead of causing use-after-frees.  After the next global
-    // GC, the orphaned pages are removed.
-    getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage(
-        arenaIndex(), object);
-  } else {
-    ASSERT(!ThreadState::current()->isTerminating());
-    PageMemory* memory = object->storage();
-    object->~LargeObjectPage();
-    delete memory;
-  }
+  PageMemory* memory = object->storage();
+  object->~LargeObjectPage();
+  delete memory;
 }
 
 Address LargeObjectArena::lazySweepPages(size_t allocationSize,
@@ -1278,14 +1247,6 @@
   ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
 }
 
-void BasePage::markOrphaned() {
-  m_arena = nullptr;
-  m_terminating = false;
-  // Since we zap the page payload for orphaned pages we need to mark it as
-  // unused so a conservative pointer won't interpret the object headers.
-  storage()->markUnused();
-}
-
 NormalPage::NormalPage(PageMemory* storage, BaseArena* arena)
     : BasePage(storage, arena), m_objectStartBitMapComputed(false) {
   ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
@@ -1677,19 +1638,6 @@
 }
 #endif
 
-void NormalPage::markOrphaned() {
-// Zap the payload with a recognizable value to detect any incorrect
-// cross thread pointer usage.
-#if defined(ADDRESS_SANITIZER)
-  // This needs to zap poisoned memory as well.
-  // Force unpoison memory before memset.
-  ASAN_UNPOISON_MEMORY_REGION(payload(), payloadSize());
-#endif
-  OrphanedPagePool::asanDisabledMemset(
-      payload(), OrphanedPagePool::orphanedZapValue, payloadSize());
-  BasePage::markOrphaned();
-}
-
 void NormalPage::takeSnapshot(base::trace_event::MemoryAllocatorDump* pageDump,
                               ThreadState::GCSnapshotInfo& info,
                               HeapSnapshotInfo& heapInfo) {
@@ -1808,14 +1756,6 @@
 }
 #endif
 
-void LargeObjectPage::markOrphaned() {
-  // Zap the payload with a recognizable value to detect any incorrect
-  // cross thread pointer usage.
-  OrphanedPagePool::asanDisabledMemset(
-      payload(), OrphanedPagePool::orphanedZapValue, payloadSize());
-  BasePage::markOrphaned();
-}
-
 void LargeObjectPage::takeSnapshot(
     base::trace_event::MemoryAllocatorDump* pageDump,
     ThreadState::GCSnapshotInfo& info,
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.h b/third_party/WebKit/Source/platform/heap/HeapPage.h
index 6340c54..7d007aa4 100644
--- a/third_party/WebKit/Source/platform/heap/HeapPage.h
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.h
@@ -413,7 +413,6 @@
                                    Address,
                                    MarkedPointerCallbackForTesting) = 0;
 #endif
-  virtual void markOrphaned();
 
   class HeapSnapshotInfo {
     STACK_ALLOCATED();
@@ -435,7 +434,6 @@
   Address getAddress() { return reinterpret_cast<Address>(this); }
   PageMemory* storage() const { return m_storage; }
   BaseArena* arena() const { return m_arena; }
-  bool orphaned() { return !m_arena; }
   bool terminating() { return m_terminating; }
   void setTerminating() { m_terminating = true; }
 
@@ -498,7 +496,6 @@
                            Address,
                            MarkedPointerCallbackForTesting) override;
 #endif
-  void markOrphaned() override;
 
   void takeSnapshot(base::trace_event::MemoryAllocatorDump*,
                     ThreadState::GCSnapshotInfo&,
@@ -580,7 +577,6 @@
                            Address,
                            MarkedPointerCallbackForTesting) override;
 #endif
-  void markOrphaned() override;
 
   void takeSnapshot(base::trace_event::MemoryAllocatorDump*,
                     ThreadState::GCSnapshotInfo&,
@@ -717,7 +713,7 @@
  public:
   BaseArena(ThreadState*, int);
   virtual ~BaseArena();
-  void cleanupPages();
+  void removeAllPages();
 
   void takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshotInfo&);
 #if DCHECK_IS_ON()
@@ -867,7 +863,7 @@
 
 #if DCHECK_IS_ON()
 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const {
-  return !pageFromObject(this)->orphaned() && m_magic == magic;
+  return m_magic == magic;
 }
 #endif
 
diff --git a/third_party/WebKit/Source/platform/heap/PagePool.cpp b/third_party/WebKit/Source/platform/heap/PagePool.cpp
index 20e10ff0..e9c7bff4 100644
--- a/third_party/WebKit/Source/platform/heap/PagePool.cpp
+++ b/third_party/WebKit/Source/platform/heap/PagePool.cpp
@@ -48,95 +48,4 @@
   return nullptr;
 }
 
-OrphanedPagePool::~OrphanedPagePool() {
-  for (int index = 0; index < BlinkGC::NumberOfArenas; ++index) {
-    while (PoolEntry* entry = m_pool[index]) {
-      m_pool[index] = entry->next;
-      BasePage* page = entry->data;
-      delete entry;
-      PageMemory* memory = page->storage();
-      ASSERT(memory);
-      page->~BasePage();
-      delete memory;
-    }
-  }
-}
-
-void OrphanedPagePool::addOrphanedPage(int index, BasePage* page) {
-  page->markOrphaned();
-  PoolEntry* entry = new PoolEntry(page, m_pool[index]);
-  m_pool[index] = entry;
-}
-
-NO_SANITIZE_ADDRESS
-void OrphanedPagePool::decommitOrphanedPages() {
-  ASSERT(ThreadState::current()->isInGC());
-  ASSERT(ThreadState::current()->heap().isAtSafePoint());
-
-  for (int index = 0; index < BlinkGC::NumberOfArenas; ++index) {
-    PoolEntry* entry = m_pool[index];
-    PoolEntry** prevNext = &m_pool[index];
-    while (entry) {
-      BasePage* page = entry->data;
-      // Check if we should reuse the memory or just free it.
-      // Large object memory is not reused but freed, normal blink heap
-      // pages are reused.
-      // NOTE: We call the destructor before freeing or adding to the
-      // free page pool.
-      PageMemory* memory = page->storage();
-      if (page->isLargeObjectPage()) {
-        page->~BasePage();
-        delete memory;
-      } else {
-        page->~BasePage();
-        clearMemory(memory);
-        ThreadHeap::mainThreadHeap()->getFreePagePool()->addFreePage(index,
-                                                                     memory);
-      }
-
-      PoolEntry* deadEntry = entry;
-      entry = entry->next;
-      *prevNext = entry;
-      delete deadEntry;
-    }
-  }
-}
-
-// Make the compiler think that something is going on there.
-static inline void breakOptimization(void* arg) {
-#if !defined(_WIN32) || defined(__clang__)
-  __asm__ __volatile__("" : : "r"(arg) : "memory");
-#endif
-}
-
-NO_SANITIZE_ADDRESS
-void OrphanedPagePool::asanDisabledMemset(Address address,
-                                          char value,
-                                          size_t size) {
-  // Don't use memset when running with ASan since this needs to zap
-  // poisoned memory as well and the NO_SANITIZE_ADDRESS annotation
-  // only works for code in this method and not for calls to memset.
-  for (Address current = address; current < address + size; ++current) {
-    breakOptimization(current);
-    *current = value;
-  }
-}
-
-void OrphanedPagePool::clearMemory(PageMemory* memory) {
-  asanDisabledMemset(memory->writableStart(), 0, blinkPagePayloadSize());
-}
-
-#if DCHECK_IS_ON()
-bool OrphanedPagePool::contains(void* object) {
-  for (int index = 0; index < BlinkGC::NumberOfArenas; ++index) {
-    for (PoolEntry* entry = m_pool[index]; entry; entry = entry->next) {
-      BasePage* page = entry->data;
-      if (page->contains(reinterpret_cast<Address>(object)))
-        return true;
-    }
-  }
-  return false;
-}
-#endif
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/PagePool.h b/third_party/WebKit/Source/platform/heap/PagePool.h
index 0d6515ce..ae4976a 100644
--- a/third_party/WebKit/Source/platform/heap/PagePool.h
+++ b/third_party/WebKit/Source/platform/heap/PagePool.h
@@ -11,7 +11,6 @@
 
 namespace blink {
 
-class BasePage;
 class PageMemory;
 
 template <typename DataType>
@@ -55,30 +54,6 @@
   Mutex m_mutex[BlinkGC::NumberOfArenas];
 };
 
-class OrphanedPagePool : public PagePool<BasePage> {
- public:
-  // The orphaned zap value must be zero in the lowest bits to allow for
-  // using the mark bit when tracing.
-  static const uint8_t orphanedZapValue = 0xdc;
-
-  ~OrphanedPagePool();
-  void addOrphanedPage(int, BasePage*);
-  void decommitOrphanedPages();
-#if DCHECK_IS_ON()
-  bool contains(void*);
-#endif
-
-  // For orphaned pages, we need to memset with ASan disabled, because
-  // the orphaned pages can still contain poisoned memory or annotated
-  // container but we want to forcibly clear the orphaned pages without
-  // causing ASan errors. asanDisabledMemset must not be used for
-  // non-orphaned pages.
-  static void asanDisabledMemset(Address, char, size_t);
-
- private:
-  void clearMemory(PageMemory*);
-};
-
 }  // namespace blink
 
 #endif
diff --git a/third_party/WebKit/Source/platform/heap/PersistentNode.cpp b/third_party/WebKit/Source/platform/heap/PersistentNode.cpp
index 3cb18219..4c09dc74b 100644
--- a/third_party/WebKit/Source/platform/heap/PersistentNode.cpp
+++ b/third_party/WebKit/Source/platform/heap/PersistentNode.cpp
@@ -165,10 +165,6 @@
         continue;
       BasePage* page = pageFromObject(rawObject);
       ASSERT(page);
-      // The main thread will upon detach just mark its heap pages as orphaned,
-      // but not invalidate its CrossThreadPersistent<>s.
-      if (page->orphaned())
-        continue;
       if (page->arena()->getThreadState() == threadState) {
         persistent->clear();
         ASSERT(slots->m_slot[i].isUnused());
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
index d254637..85d1bf5 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -206,15 +206,15 @@
   new ThreadState();
 }
 
-void ThreadState::cleanupPages() {
+void ThreadState::removeAllPages() {
   ASSERT(checkThread());
   for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
-    m_arenas[i]->cleanupPages();
+    m_arenas[i]->removeAllPages();
 }
 
 void ThreadState::runTerminationGC() {
   if (isMainThread()) {
-    cleanupPages();
+    removeAllPages();
     return;
   }
   ASSERT(checkThread());
@@ -231,6 +231,8 @@
   // Set the terminate flag on all heap pages of this thread. This is used to
   // ensure we don't trace pages on other threads that are not part of the
   // thread local GC.
+  // TODO(haraken): Remove this. This is not needed once we remove a thread-
+  // local termination GC.
   prepareForThreadStateTermination();
 
   ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination(
@@ -242,7 +244,8 @@
   int currentCount = getPersistentRegion()->numberOfPersistents();
   ASSERT(currentCount >= 0);
   while (currentCount != oldCount) {
-    collectGarbageForTerminatingThread();
+    collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep,
+                   BlinkGC::ThreadTerminationGC);
     // Release the thread-local static persistents that were
     // instantiated while running the termination GC.
     releaseStaticPersistentNodes();
@@ -256,9 +259,7 @@
   ASSERT(m_orderedPreFinalizers.isEmpty());
   RELEASE_ASSERT(gcState() == NoGCScheduled);
 
-  // Add pages to the orphaned page pool to ensure any global GCs from this
-  // point on will not trace objects on this thread's arenas.
-  cleanupPages();
+  removeAllPages();
 }
 
 void ThreadState::detachCurrentThread() {
@@ -363,11 +364,6 @@
 
 bool ThreadState::popAndInvokeThreadLocalWeakCallback(Visitor* visitor) {
   ASSERT(checkThread());
-  // For weak processing we should never reach orphaned pages since orphaned
-  // pages are not traced and thus objects on those pages are never be
-  // registered as objects on orphaned pages. We cannot assert this here since
-  // we might have an off-heap collection. We assert it in
-  // ThreadHeap::pushThreadLocalWeakCallback.
   if (CallbackStack::Item* item = m_threadLocalWeakCallbackStack->pop()) {
     item->call(visitor);
     return true;
@@ -1655,11 +1651,6 @@
       heap().globalWeakProcessing(visitor.get());
     }
 
-    // Now we can delete all orphaned pages because there are no dangling
-    // pointers to the orphaned pages.  (If we have such dangling pointers,
-    // we should have crashed during marking before getting here.)
-    heap().getOrphanedPagePool()->decommitOrphanedPages();
-
     double markingTimeInMilliseconds = WTF::currentTimeMS() - startTime;
     heap().heapStats().setEstimatedMarkingTimePerByte(
         totalObjectSize ? (markingTimeInMilliseconds / 1000 / totalObjectSize)
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.h b/third_party/WebKit/Source/platform/heap/ThreadState.h
index df38bec..91b9e2b8d 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.h
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.h
@@ -609,7 +609,7 @@
   void poisonAllHeaps();
 #endif
 
-  void cleanupPages();
+  void removeAllPages();
 
   void prepareForThreadStateTermination();
 
diff --git a/third_party/WebKit/Source/platform/heap/TraceTraits.h b/third_party/WebKit/Source/platform/heap/TraceTraits.h
index fb5b1a0..544e762 100644
--- a/third_party/WebKit/Source/platform/heap/TraceTraits.h
+++ b/third_party/WebKit/Source/platform/heap/TraceTraits.h
@@ -108,15 +108,6 @@
   static void mark(VisitorDispatcher visitor, const T* self) {
     if (!self)
       return;
-
-    // If you hit this ASSERT, it means that there is a dangling pointer
-    // from a live thread heap to a dead thread heap. We must eliminate
-    // the dangling pointer.
-    // Release builds don't have the ASSERT, but it is OK because
-    // release builds will crash at the following self->adjustAndMark
-    // because all the entries of the orphaned arenas are zeroed out and
-    // thus the item does not have a valid vtable.
-    ASSERT(!pageFromObject(self)->orphaned());
     self->adjustAndMark(visitor);
   }
 };
diff --git a/third_party/WebKit/Source/platform/heap/VisitorImpl.h b/third_party/WebKit/Source/platform/heap/VisitorImpl.h
index f2e90e00..ec0b537f 100644
--- a/third_party/WebKit/Source/platform/heap/VisitorImpl.h
+++ b/third_party/WebKit/Source/platform/heap/VisitorImpl.h
@@ -18,14 +18,6 @@
   DCHECK(header);
   DCHECK(objectPointer);
 
-  // If you hit this DCHECK, it means that there is a dangling pointer
-  // from a live thread heap to a dead thread heap.  We must eliminate
-  // the dangling pointer.
-  // Release builds don't have the DCHECK, but it is OK because
-  // release builds will crash in the following header->isMarked()
-  // because all the entries of the orphaned arenas are zapped.
-  DCHECK(!pageFromObject(objectPointer)->orphaned());
-
   if (header->isMarked())
     return;
 
diff --git a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
index 2c54f16..d9b53a9e 100644
--- a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
@@ -75,6 +75,7 @@
       m_checkForBrowserSideNavigation(true),
       m_uiStartTime(0),
       m_isExternalRequest(false),
+      m_isSameDocumentNavigation(false),
       m_inputPerfMetricReportPolicy(
           InputToLoadPerfMetricReportPolicy::NoReport),
       m_redirectStatus(RedirectStatus::NoRedirect) {}
diff --git a/third_party/WebKit/Source/platform/network/ResourceRequest.h b/third_party/WebKit/Source/platform/network/ResourceRequest.h
index f1324df4..26d93f9 100644
--- a/third_party/WebKit/Source/platform/network/ResourceRequest.h
+++ b/third_party/WebKit/Source/platform/network/ResourceRequest.h
@@ -310,6 +310,11 @@
   void setNavigationStartTime(double);
   double navigationStartTime() const { return m_navigationStart; }
 
+  void setIsSameDocumentNavigation(bool isSameDocument) {
+    m_isSameDocumentNavigation = isSameDocument;
+  }
+  bool isSameDocumentNavigation() const { return m_isSameDocumentNavigation; }
+
  private:
   const CacheControlHeader& cacheControlHeader() const;
 
@@ -350,6 +355,7 @@
   bool m_checkForBrowserSideNavigation;
   double m_uiStartTime;
   bool m_isExternalRequest;
+  bool m_isSameDocumentNavigation;
   InputToLoadPerfMetricReportPolicy m_inputPerfMetricReportPolicy;
 
   mutable CacheControlHeader m_cacheControlHeaderCache;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
index 0e1681e..b0a03cd 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
@@ -662,6 +662,12 @@
                  std::max(0, size.height() - horizontalScrollbarHeight()));
 }
 
+void ScrollableArea::didScroll(const gfx::ScrollOffset& offset) {
+  ScrollOffset newOffset = ScrollOffset(offset.x() - scrollOrigin().x(),
+                                        offset.y() - scrollOrigin().y());
+  setScrollOffset(newOffset, CompositorScroll);
+}
+
 DEFINE_TRACE(ScrollableArea) {
   visitor->trace(m_scrollAnimator);
   visitor->trace(m_programmaticScrollAnimator);
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
index 3d6fced..d84ded4 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -35,6 +35,7 @@
 #include "platform/scroll/ScrollAnimatorBase.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "platform/scroll/Scrollbar.h"
+#include "public/platform/WebLayerScrollClient.h"
 #include "wtf/MathExtras.h"
 #include "wtf/Noncopyable.h"
 #include "wtf/Vector.h"
@@ -59,7 +60,8 @@
   IncludeScrollbars,
 };
 
-class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
+class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin,
+                                       public WebLayerScrollClient {
   WTF_MAKE_NONCOPYABLE(ScrollableArea);
 
  public:
@@ -372,6 +374,9 @@
   // Ideally a frame-specific throttled one can be used.
   virtual RefPtr<WebTaskRunner> getTimerTaskRunner() const = 0;
 
+  // Callback for compositor-side scrolling.
+  void didScroll(const gfx::ScrollOffset&) override;
+
  protected:
   ScrollableArea();
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
index 4909395..3a7b40b 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp
@@ -253,4 +253,18 @@
             scrollableArea->getScrollbarOverlayColorTheme());
 }
 
+TEST_F(ScrollableAreaTest, ScrollableAreaDidScroll) {
+  ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
+      platform;
+
+  MockScrollableArea* scrollableArea =
+      MockScrollableArea::create(ScrollOffset(100, 100));
+  scrollableArea->setScrollOrigin(IntPoint(20, 30));
+  scrollableArea->didScroll(gfx::ScrollOffset(40, 51));
+
+  // After calling didScroll, the new offset should account for scroll origin.
+  EXPECT_EQ(20, scrollableArea->scrollOffsetInt().width());
+  EXPECT_EQ(21, scrollableArea->scrollOffsetInt().height());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
index 7b499d50..eb9ed62 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
@@ -63,6 +63,9 @@
   bool scrollAnimatorEnabled() const override { return false; }
   int pageStep(ScrollbarOrientation) const override { return 0; }
   void scrollControlWasSetNeedsPaintInvalidation() {}
+  void setScrollOrigin(const IntPoint& origin) {
+    ScrollableArea::setScrollOrigin(origin);
+  }
 
   RefPtr<WebTaskRunner> getTimerTaskRunner() const final {
     return Platform::current()->currentThread()->scheduler()->timerTaskRunner();
diff --git a/third_party/WebKit/Source/platform/testing/ScopedMockedURL.cpp b/third_party/WebKit/Source/platform/testing/ScopedMockedURL.cpp
new file mode 100644
index 0000000..30ead6a
--- /dev/null
+++ b/third_party/WebKit/Source/platform/testing/ScopedMockedURL.cpp
@@ -0,0 +1,28 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/testing/ScopedMockedURL.h"
+
+#include "platform/testing/URLTestHelpers.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebURLLoaderMockFactory.h"
+
+namespace blink {
+namespace testing {
+
+ScopedMockedURL::ScopedMockedURL(const WebURL& url) : m_url(url) {}
+
+ScopedMockedURL::~ScopedMockedURL() {
+  Platform::current()->getURLLoaderMockFactory()->unregisterURL(m_url);
+}
+
+ScopedMockedURLLoad::ScopedMockedURLLoad(const WebURL& fullURL,
+                                         const WebString& filePath,
+                                         const WebString& mimeType)
+    : ScopedMockedURL(fullURL) {
+  URLTestHelpers::registerMockedURLLoad(fullURL, filePath, mimeType);
+}
+
+}  // namespace testing
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/ScopedMockedURL.h b/third_party/WebKit/Source/platform/testing/ScopedMockedURL.h
new file mode 100644
index 0000000..f04cbca
--- /dev/null
+++ b/third_party/WebKit/Source/platform/testing/ScopedMockedURL.h
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ScopedMockedURL_h
+#define ScopedMockedURL_h
+
+#include "public/platform/WebString.h"
+#include "public/platform/WebURL.h"
+#include "public/platform/WebURLResponse.h"
+
+namespace blink {
+
+namespace testing {
+
+// Convenience classes that register a mocked URL on construction, and
+// unregister it on destruction. This prevent mocked URL from leaking to other
+// tests.
+class ScopedMockedURL {
+ public:
+  explicit ScopedMockedURL(const WebURL&);
+  virtual ~ScopedMockedURL();
+
+ private:
+  WebURL m_url;
+};
+
+class ScopedMockedURLLoad : ScopedMockedURL {
+ public:
+  ScopedMockedURLLoad(
+      const WebURL& fullURL,
+      const WebString& filePath,
+      const WebString& mimeType = WebString::fromUTF8("text/html"));
+  ~ScopedMockedURLLoad() override = default;
+};
+
+}  // namespace testing
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp
index 686f769..bcb720e 100644
--- a/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp
@@ -36,11 +36,9 @@
 #include "platform/testing/UnitTestHelpers.h"
 #include "public/platform/FilePathConversion.h"
 #include "public/platform/Platform.h"
-#include "public/platform/WebURL.h"
 #include "public/platform/WebURLError.h"
 #include "public/platform/WebURLLoadTiming.h"
 #include "public/platform/WebURLLoaderMockFactory.h"
-#include "public/platform/WebURLResponse.h"
 
 namespace blink {
 namespace URLTestHelpers {
diff --git a/third_party/WebKit/Source/platform/testing/URLTestHelpers.h b/third_party/WebKit/Source/platform/testing/URLTestHelpers.h
index 6cb59d3..1003577 100644
--- a/third_party/WebKit/Source/platform/testing/URLTestHelpers.h
+++ b/third_party/WebKit/Source/platform/testing/URLTestHelpers.h
@@ -34,11 +34,9 @@
 #include "platform/weborigin/KURL.h"
 #include "public/platform/WebString.h"
 #include "public/platform/WebURL.h"
+#include "public/platform/WebURLResponse.h"
 
 namespace blink {
-
-class WebURLResponse;
-
 namespace URLTestHelpers {
 
 inline blink::KURL toKURL(const std::string& url) {
@@ -46,6 +44,9 @@
   return blink::KURL(blink::ParsedURLString, wtfString);
 }
 
+// Avoid directly using these methods, instead please use ScopedMockedURL (or
+// define a variant of ScopedMockedURL classes if necessary) in new code.
+//
 // Helper functions for mock URLs. These functions set up the desired URL and
 // mimeType, with a 200 OK return status.
 // webTestDataPath() or platformTestDataPath() in UnitTestHelpers can be used to
@@ -66,6 +67,8 @@
     const WebURL& fullURL,
     const WebString& filePath,
     const WebString& mimeType = WebString::fromUTF8("text/html"));
+
+// Registers with a custom response.
 void registerMockedURLLoadWithCustomResponse(const WebURL& fullURL,
                                              const WebString& filePath,
                                              WebURLResponse);
diff --git a/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp b/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
index dd43f21..a262960 100644
--- a/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
+++ b/third_party/WebKit/Source/web/SharedWorkerRepositoryClientImpl.cpp
@@ -96,6 +96,11 @@
 
   void connected() override { m_worker->setIsBeingConnected(false); }
 
+  void countFeature(uint32_t feature) override {
+    UseCounter::count(m_worker->getExecutionContext(),
+                      static_cast<UseCounter::Feature>(feature));
+  }
+
   Persistent<SharedWorker> m_worker;
 };
 
diff --git a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp
index 3f886aa..13137450 100644
--- a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp
@@ -716,8 +716,9 @@
     focusPlugin();
 
   WebCursorInfo cursorInfo;
-  if (m_webPlugin->handleInputEvent(transformedEvent, cursorInfo) !=
-      WebInputEventResult::NotHandled)
+  if (m_webPlugin &&
+      m_webPlugin->handleInputEvent(transformedEvent, cursorInfo) !=
+          WebInputEventResult::NotHandled)
     event->setDefaultHandled();
 
   // A windowless plugin can change the cursor in response to a mouse move
diff --git a/third_party/WebKit/Source/web/WebSettingsImpl.cpp b/third_party/WebKit/Source/web/WebSettingsImpl.cpp
index 0be2ae1..30e251d1 100644
--- a/third_party/WebKit/Source/web/WebSettingsImpl.cpp
+++ b/third_party/WebKit/Source/web/WebSettingsImpl.cpp
@@ -278,6 +278,10 @@
   m_devToolsEmulator->setPluginsEnabled(enabled);
 }
 
+void WebSettingsImpl::setEncryptedMediaEnabled(bool enabled) {
+  m_settings->setEncryptedMediaEnabled(enabled);
+}
+
 void WebSettingsImpl::setAvailablePointerTypes(int pointers) {
   m_devToolsEmulator->setAvailablePointerTypes(pointers);
 }
diff --git a/third_party/WebKit/Source/web/WebSettingsImpl.h b/third_party/WebKit/Source/web/WebSettingsImpl.h
index d228e29..21cb3129 100644
--- a/third_party/WebKit/Source/web/WebSettingsImpl.h
+++ b/third_party/WebKit/Source/web/WebSettingsImpl.h
@@ -136,6 +136,7 @@
   void setPictographFontFamily(const WebString&,
                                UScriptCode = USCRIPT_COMMON) override;
   void setPluginsEnabled(bool) override;
+  void setEncryptedMediaEnabled(bool) override;
   void setAvailablePointerTypes(int) override;
   void setPrimaryPointerType(PointerType) override;
   void setAvailableHoverTypes(int) override;
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
index 7c2cece..04764e4 100644
--- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
@@ -222,16 +222,18 @@
 
 // WorkerReportingProxy --------------------------------------------------------
 
-void WebSharedWorkerImpl::countFeature(UseCounter::Feature) {
-  // TODO(nhiroki): Support UseCounter for SharedWorker. Send an IPC message to
-  // the browser process and ask each connected document to record API use in
-  // its UseCounter (https://crbug.com/376039).
+void WebSharedWorkerImpl::countFeature(UseCounter::Feature feature) {
+  m_parentFrameTaskRunners->get(TaskType::UnspecedTimer)
+      ->postTask(BLINK_FROM_HERE,
+                 crossThreadBind(&WebSharedWorkerClient::countFeature,
+                                 crossThreadUnretained(m_client), feature));
 }
 
-void WebSharedWorkerImpl::countDeprecation(UseCounter::Feature) {
-  // TODO(nhiroki): Support UseCounter for SharedWorker. Send an IPC message to
-  // the browser process and ask each connected document to record API use in
-  // its UseCounter (https://crbug.com/376039).
+void WebSharedWorkerImpl::countDeprecation(UseCounter::Feature feature) {
+  // Go through the same code path with countFeature() because a deprecation
+  // message is already shown on the worker console and a remaining work is just
+  // to record an API use.
+  countFeature(feature);
 }
 
 void WebSharedWorkerImpl::reportException(const String& errorMessage,
diff --git a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
index e4a01a9..77d6e99 100644
--- a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
@@ -226,8 +226,8 @@
   WebLayer* webScrollLayer =
       compositedLayerMapping->scrollingContentsLayer()->platformLayer();
   ASSERT_TRUE(webScrollLayer);
-  ASSERT_NEAR(1.2f, webScrollLayer->scrollPositionDouble().x, 0.01f);
-  ASSERT_NEAR(1.2f, webScrollLayer->scrollPositionDouble().y, 0.01f);
+  ASSERT_NEAR(1.2f, webScrollLayer->scrollPosition().x, 0.01f);
+  ASSERT_NEAR(1.2f, webScrollLayer->scrollPosition().y, 0.01f);
 
   RuntimeEnabledFeatures::setFractionalScrollOffsetsEnabled(
       origFractionalOffsetsEnabled);
@@ -740,7 +740,7 @@
                      ->isOverlayScrollbar()
                  ? 0
                  : 15);
-  ASSERT_EQ(expectedScrollPosition, webScrollLayer->scrollPositionDouble().x);
+  ASSERT_EQ(expectedScrollPosition, webScrollLayer->scrollPosition().x);
 }
 
 TEST_P(ScrollingCoordinatorTest, setupScrollbarLayerShouldNotCrash) {
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 2056909..a9b73309 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -6761,15 +6761,14 @@
   WebLocalFrameImpl* frameImpl = webViewHelper.webView()->mainFrameImpl();
   DocumentLoader::InitialScrollState& initialScrollState =
       frameImpl->frame()->loader().documentLoader()->initialScrollState();
-  GraphicsLayer* frameViewLayer = frameImpl->frameView()->layerForScrolling();
 
   EXPECT_FALSE(client.wasFrameScrolled());
   EXPECT_FALSE(initialScrollState.wasScrolledByUser);
 
+  auto* scrollableArea = frameImpl->frameView()->layoutViewportScrollableArea();
+
   // Do a compositor scroll, verify that this is counted as a user scroll.
-  frameViewLayer->platformLayer()->setScrollPositionDouble(
-      WebDoublePoint(0, 1));
-  frameViewLayer->didScroll();
+  scrollableArea->didScroll(gfx::ScrollOffset(0, 1));
   webViewHelper.webView()->applyViewportDeltas(WebFloatSize(), WebFloatSize(),
                                                WebFloatSize(), 1.7f, 0);
   EXPECT_TRUE(client.wasFrameScrolled());
@@ -6779,9 +6778,7 @@
   initialScrollState.wasScrolledByUser = false;
 
   // The page scale 1.0f and scroll.
-  frameViewLayer->platformLayer()->setScrollPositionDouble(
-      WebDoublePoint(0, 2));
-  frameViewLayer->didScroll();
+  scrollableArea->didScroll(gfx::ScrollOffset(0, 2));
   webViewHelper.webView()->applyViewportDeltas(WebFloatSize(), WebFloatSize(),
                                                WebFloatSize(), 1.0f, 0);
   EXPECT_TRUE(client.wasFrameScrolled());
@@ -6790,7 +6787,7 @@
   initialScrollState.wasScrolledByUser = false;
 
   // No scroll event if there is no scroll delta.
-  frameViewLayer->didScroll();
+  scrollableArea->didScroll(gfx::ScrollOffset(0, 2));
   webViewHelper.webView()->applyViewportDeltas(WebFloatSize(), WebFloatSize(),
                                                WebFloatSize(), 1.0f, 0);
   EXPECT_FALSE(client.wasFrameScrolled());
@@ -6798,9 +6795,7 @@
   client.reset();
 
   // Non zero page scale and scroll.
-  frameViewLayer->platformLayer()->setScrollPositionDouble(
-      WebDoublePoint(9, 15));
-  frameViewLayer->didScroll();
+  scrollableArea->didScroll(gfx::ScrollOffset(9, 15));
   webViewHelper.webView()->applyViewportDeltas(WebFloatSize(), WebFloatSize(),
                                                WebFloatSize(), 0.6f, 0);
   EXPECT_TRUE(client.wasFrameScrolled());
diff --git a/third_party/WebKit/Source/wtf/allocator/Partitions.cpp b/third_party/WebKit/Source/wtf/allocator/Partitions.cpp
index 04602cf8..bcc4658 100644
--- a/third_party/WebKit/Source/wtf/allocator/Partitions.cpp
+++ b/third_party/WebKit/Source/wtf/allocator/Partitions.cpp
@@ -43,6 +43,7 @@
 bool Partitions::s_initialized = false;
 
 base::PartitionAllocatorGeneric Partitions::m_fastMallocAllocator;
+base::PartitionAllocatorGeneric Partitions::m_arrayBufferAllocator;
 base::PartitionAllocatorGeneric Partitions::m_bufferAllocator;
 base::SizeSpecificPartitionAllocator<1024> Partitions::m_layoutAllocator;
 Partitions::ReportPartitionAllocSizeFunction Partitions::m_reportSizeFunction =
@@ -55,6 +56,7 @@
   if (!s_initialized) {
     base::PartitionAllocGlobalInit(&Partitions::handleOutOfMemory);
     m_fastMallocAllocator.init();
+    m_arrayBufferAllocator.init();
     m_bufferAllocator.init();
     m_layoutAllocator.init();
     m_reportSizeFunction = reportSizeFunction;
@@ -67,6 +69,8 @@
   if (!s_initialized)
     return;
 
+  PartitionPurgeMemoryGeneric(arrayBufferPartition(),
+                              base::PartitionPurgeDecommitEmptyPages);
   PartitionPurgeMemoryGeneric(bufferPartition(),
                               base::PartitionPurgeDecommitEmptyPages);
   PartitionPurgeMemoryGeneric(fastMallocPartition(),
@@ -101,6 +105,8 @@
   decommitFreeableMemory();
   PartitionDumpStatsGeneric(fastMallocPartition(), "fast_malloc", isLightDump,
                             partitionStatsDumper);
+  PartitionDumpStatsGeneric(arrayBufferPartition(), "array_buffer", isLightDump,
+                            partitionStatsDumper);
   PartitionDumpStatsGeneric(bufferPartition(), "buffer", isLightDump,
                             partitionStatsDumper);
   PartitionDumpStats(layoutPartition(), "layout", isLightDump,
diff --git a/third_party/WebKit/Source/wtf/allocator/Partitions.h b/third_party/WebKit/Source/wtf/allocator/Partitions.h
index 159e011..2aea9ecb 100644
--- a/third_party/WebKit/Source/wtf/allocator/Partitions.h
+++ b/third_party/WebKit/Source/wtf/allocator/Partitions.h
@@ -49,6 +49,11 @@
   static const char* const kAllocatedObjectPoolName;
 
   static void initialize(ReportPartitionAllocSizeFunction);
+  ALWAYS_INLINE static base::PartitionRootGeneric* arrayBufferPartition() {
+    DCHECK(s_initialized);
+    return m_arrayBufferAllocator.root();
+  }
+
   ALWAYS_INLINE static base::PartitionRootGeneric* bufferPartition() {
     DCHECK(s_initialized);
     return m_bufferAllocator.root();
@@ -76,6 +81,7 @@
   static size_t totalSizeOfCommittedPages() {
     size_t totalSize = 0;
     totalSize += m_fastMallocAllocator.root()->total_size_of_committed_pages;
+    totalSize += m_arrayBufferAllocator.root()->total_size_of_committed_pages;
     totalSize += m_bufferAllocator.root()->total_size_of_committed_pages;
     totalSize += m_layoutAllocator.root()->total_size_of_committed_pages;
     return totalSize;
@@ -131,12 +137,14 @@
   //     is for performance: As LayoutObjects are guaranteed to only be used
   //     by the main thread, we can bypass acquiring a lock. Also we can
   //     improve memory locality by putting LayoutObjects together.
-  //   - Buffer partition: A partition to allocate objects that have a strong
-  //     risk where the length and/or the contents are exploited from user
-  //     scripts. Vectors, HashTables, ArrayBufferContents and Strings are
-  //     allocated in the buffer partition.
+  //   - ArrayBuffer partition: A partition to allocate array buffers.
+  //   - Buffer partition: A partition to allocate other buffers that have
+  //     a strong risk where the length and/or the contents are exploited from
+  //     user scripts. Vectors, HashTables and Strings are allocated in the
+  //      buffer partition.
   //   - Fast malloc partition: A partition to allocate all other objects.
   static base::PartitionAllocatorGeneric m_fastMallocAllocator;
+  static base::PartitionAllocatorGeneric m_arrayBufferAllocator;
   static base::PartitionAllocatorGeneric m_bufferAllocator;
   static base::SizeSpecificPartitionAllocator<1024> m_layoutAllocator;
   static ReportPartitionAllocSizeFunction m_reportSizeFunction;
diff --git a/third_party/WebKit/Source/wtf/typed_arrays/ArrayBufferContents.cpp b/third_party/WebKit/Source/wtf/typed_arrays/ArrayBufferContents.cpp
index 6b92d6f..30fbd61 100644
--- a/third_party/WebKit/Source/wtf/typed_arrays/ArrayBufferContents.cpp
+++ b/third_party/WebKit/Source/wtf/typed_arrays/ArrayBufferContents.cpp
@@ -112,7 +112,7 @@
                                                   int flags,
                                                   void*& data) {
   data = PartitionAllocGenericFlags(
-      WTF::Partitions::bufferPartition(), flags, size,
+      Partitions::arrayBufferPartition(), flags, size,
       WTF_HEAP_PROFILER_TYPE_NAME(ArrayBufferContents));
   if (policy == ZeroInitialize && data)
     memset(data, '\0', size);
@@ -131,7 +131,7 @@
 }
 
 void ArrayBufferContents::freeMemory(void* data, size_t size) {
-  Partitions::bufferFree(data);
+  PartitionFreeGeneric(Partitions::arrayBufferPartition(), data);
 }
 
 ArrayBufferContents::DataHolder::DataHolder()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py
index 132b8bd1..5c32387 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py
@@ -106,7 +106,7 @@
 
         # Don't check lines that have expectations for directories, since
         # the flakiness of all sub-tests isn't as easy to check.
-        if self._is_directory(test_expectation_line.path):
+        if self._port.test_isdir(test_expectation_line.name):
             return False
 
         # The line can be deleted if the only expectation on the line that appears in the actual
@@ -196,12 +196,6 @@
                                      'SKIP')
         return any(s in expectations for s in unstrippable_expectations)
 
-    def _is_directory(self, path):
-        """Checks whether a path relative to the layout tests directory is a directory."""
-        filesystem = self._host.filesystem
-        abs_path = filesystem.join(self._port.layout_tests_dir(), path)
-        return filesystem.isdir(abs_path)
-
     def _get_builder_results_by_path(self):
         """Returns a dictionary of results for each builder.
 
diff --git a/third_party/WebKit/public/platform/WebLayer.h b/third_party/WebKit/public/platform/WebLayer.h
index e51ae30..9da1a40 100644
--- a/third_party/WebKit/public/platform/WebLayer.h
+++ b/third_party/WebKit/public/platform/WebLayer.h
@@ -29,7 +29,7 @@
 #include "WebBlendMode.h"
 #include "WebColor.h"
 #include "WebCommon.h"
-#include "WebDoublePoint.h"
+#include "WebFloatPoint.h"
 #include "WebFloatPoint3D.h"
 #include "WebFloatSize.h"
 #include "WebPoint.h"
@@ -158,8 +158,8 @@
   virtual void setClipParent(WebLayer*) = 0;
 
   // Scrolling
-  virtual void setScrollPositionDouble(WebDoublePoint) = 0;
-  virtual WebDoublePoint scrollPositionDouble() const = 0;
+  virtual void setScrollPosition(WebFloatPoint) = 0;
+  virtual WebFloatPoint scrollPosition() const = 0;
 
   // To set a WebLayer as scrollable we must specify the corresponding clip
   // layer.
diff --git a/third_party/WebKit/public/platform/WebLayerScrollClient.h b/third_party/WebKit/public/platform/WebLayerScrollClient.h
index 42f9576f..1979834 100644
--- a/third_party/WebKit/public/platform/WebLayerScrollClient.h
+++ b/third_party/WebKit/public/platform/WebLayerScrollClient.h
@@ -32,7 +32,7 @@
 // A client that is notified of scrolling on a WebLayer.
 class BLINK_PLATFORM_EXPORT WebLayerScrollClient {
  public:
-  virtual void didScroll() = 0;
+  virtual void didScroll(const gfx::ScrollOffset&) = 0;
 
  protected:
   virtual ~WebLayerScrollClient() {}
diff --git a/third_party/WebKit/public/platform/WebURLRequest.h b/third_party/WebKit/public/platform/WebURLRequest.h
index 57c31b6..84aa69f 100644
--- a/third_party/WebKit/public/platform/WebURLRequest.h
+++ b/third_party/WebKit/public/platform/WebURLRequest.h
@@ -335,6 +335,12 @@
 
   BLINK_PLATFORM_EXPORT void setNavigationStartTime(double);
 
+  // PlzNavigate: specify that the request was intended to be loaded as a same
+  // document navigation. No network requests should be made and the request
+  // should be dropped if a different document was loaded in the frame
+  // in-between.
+  BLINK_PLATFORM_EXPORT void setIsSameDocumentNavigation(bool);
+
 #if INSIDE_BLINK
   BLINK_PLATFORM_EXPORT ResourceRequest& toMutableResourceRequest();
   BLINK_PLATFORM_EXPORT const ResourceRequest& toResourceRequest() const;
diff --git a/third_party/WebKit/public/platform/modules/permissions/WebPermissionType.h b/third_party/WebKit/public/platform/modules/permissions/WebPermissionType.h
index 7d3960f..9df396e 100644
--- a/third_party/WebKit/public/platform/modules/permissions/WebPermissionType.h
+++ b/third_party/WebKit/public/platform/modules/permissions/WebPermissionType.h
@@ -10,12 +10,7 @@
 enum WebPermissionType {
   WebPermissionTypeGeolocation,
   WebPermissionTypeNotifications,
-  WebPermissionTypePush,
-  WebPermissionTypePushNotifications,
-  WebPermissionTypeMidi,
   WebPermissionTypeMidiSysEx,
-  WebPermissionTypeDurableStorage,
-  WebPermissionTypeBackgroundSync,
 
   WebPermissionTypeLast,
 };
diff --git a/third_party/WebKit/public/web/WebSettings.h b/third_party/WebKit/public/web/WebSettings.h
index ef17af89..79b8b3c 100644
--- a/third_party/WebKit/public/web/WebSettings.h
+++ b/third_party/WebKit/public/web/WebSettings.h
@@ -214,6 +214,7 @@
   virtual void setPictographFontFamily(const WebString&,
                                        UScriptCode = USCRIPT_COMMON) = 0;
   virtual void setPluginsEnabled(bool) = 0;
+  virtual void setEncryptedMediaEnabled(bool) = 0;
   virtual void setPresentationReceiver(bool) = 0;
   virtual void setAvailablePointerTypes(int) = 0;
   virtual void setPrimaryPointerType(PointerType) = 0;
diff --git a/third_party/WebKit/public/web/WebSharedWorkerClient.h b/third_party/WebKit/public/web/WebSharedWorkerClient.h
index 14bc7c3..e75a34c5 100644
--- a/third_party/WebKit/public/web/WebSharedWorkerClient.h
+++ b/third_party/WebKit/public/web/WebSharedWorkerClient.h
@@ -53,6 +53,7 @@
 // or workerContextDestroyed() is called).
 class WebSharedWorkerClient {
  public:
+  virtual void countFeature(uint32_t) = 0;
   virtual void workerContextClosed() = 0;
   virtual void workerContextDestroyed() = 0;
   virtual void workerReadyForInspection() {}
diff --git a/third_party/WebKit/public/web/WebSharedWorkerConnectListener.h b/third_party/WebKit/public/web/WebSharedWorkerConnectListener.h
index 078eb028..d896c18f 100644
--- a/third_party/WebKit/public/web/WebSharedWorkerConnectListener.h
+++ b/third_party/WebKit/public/web/WebSharedWorkerConnectListener.h
@@ -48,6 +48,10 @@
 
   // Called when a connection is established.
   virtual void connected() = 0;
+
+  // Called when some API to be recorded in UseCounter is called on the worker
+  // global scope.
+  virtual void countFeature(uint32_t) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index 6907d7d..caa6f0f9 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: unknown
-Revision: 88442dd5788bf7836ab013939cca4a4683560cb0
+Revision: cd284713834e4d9c184dd06643b0a87f73d9b062
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS
index db8c048c..0da988b7 100644
--- a/third_party/crashpad/crashpad/DEPS
+++ b/third_party/crashpad/crashpad/DEPS
@@ -38,7 +38,7 @@
 
   'crashpad/third_party/mini_chromium/mini_chromium':
       Var('chromium_git') + '/chromium/mini_chromium@' +
-      '4f3cfc8e7c2b7d77f94f41a32c3ec84a6920f05d',
+      'f65519e442d23498937251e680a3b113927613b0',
 }
 
 hooks = [
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_test_server.py b/third_party/crashpad/crashpad/util/net/http_transport_test_server.py
index 3f085a5..3d3c55a 100755
--- a/third_party/crashpad/crashpad/util/net/http_transport_test_server.py
+++ b/third_party/crashpad/crashpad/util/net/http_transport_test_server.py
@@ -26,7 +26,7 @@
 write the entire request to stdout. It will then terminate.
 
 This server is written in Python since it provides a simple HTTP stack, and
-because parsing Chunked encoding is safer and easier in a memory-safe language.
+because parsing chunked encoding is safer and easier in a memory-safe language.
 This could easily have been written in C++ instead.
 """
 
@@ -80,7 +80,7 @@
     RequestHandler.raw_request = self.rfile.buffer
     self.rfile.buffer = ''
 
-    if self.headers.get('Transfer-Encoding', '') == 'Chunked':
+    if self.headers.get('Transfer-Encoding', '').lower() == 'chunked':
       body = self.handle_chunked_encoding()
     else:
       length = int(self.headers.get('Content-Length', -1))
@@ -130,6 +130,10 @@
       return -1
     return int(chunk_size_and_ext_line[:chunk_size_end], base=16)
 
+  def log_request(self, code='-', size='-'):
+    # The default implementation logs these to sys.stderr, which is just noise.
+    pass
+
 
 def Main():
   if sys.platform == 'win32':
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_win.cc b/third_party/crashpad/crashpad/util/net/http_transport_win.cc
index 58ecc478..294048a 100644
--- a/third_party/crashpad/crashpad/util/net/http_transport_win.cc
+++ b/third_party/crashpad/crashpad/util/net/http_transport_win.cc
@@ -15,17 +15,22 @@
 #include "util/net/http_transport.h"
 
 #include <windows.h>
+#include <stddef.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <sys/types.h>
+#include <wchar.h>
 #include <winhttp.h>
 
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/scoped_generic.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "package.h"
 #include "util/file/file_io.h"
+#include "util/numeric/safe_assignment.h"
 #include "util/net/http_body.h"
 
 namespace crashpad {
@@ -34,7 +39,7 @@
 
 // PLOG doesn't work for messages from WinHTTP, so we need to use
 // FORMAT_MESSAGE_FROM_HMODULE + the dll name manually here.
-void LogErrorWinHttpMessage(const char* extra) {
+std::string WinHttpMessage(const char* extra) {
   DWORD error_code = GetLastError();
   char msgbuf[256];
   DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
@@ -46,15 +51,13 @@
                              msgbuf,
                              arraysize(msgbuf),
                              NULL);
-  if (len) {
-    LOG(ERROR) << extra << ": " << msgbuf
-               << base::StringPrintf(" (0x%X)", error_code);
-  } else {
-    LOG(ERROR) << base::StringPrintf(
-        "Error (0x%X) while retrieving error. (0x%X)",
-        GetLastError(),
-        error_code);
+  if (!len) {
+    return base::StringPrintf("%s: error 0x%x while retrieving error 0x%x",
+                              extra,
+                              GetLastError(),
+                              error_code);
   }
+  return base::StringPrintf("%s: %s (0x%x)", extra, msgbuf, error_code);
 }
 
 struct ScopedHINTERNETTraits {
@@ -64,7 +67,7 @@
   static void Free(HINTERNET handle) {
     if (handle) {
       if (!WinHttpCloseHandle(handle)) {
-        LogErrorWinHttpMessage("WinHttpCloseHandle");
+        LOG(ERROR) << WinHttpMessage("WinHttpCloseHandle");
       }
     }
   }
@@ -97,7 +100,7 @@
                   WINHTTP_NO_PROXY_BYPASS,
                   0));
   if (!session.get()) {
-    LogErrorWinHttpMessage("WinHttpOpen");
+    LOG(ERROR) << WinHttpMessage("WinHttpOpen");
     return false;
   }
 
@@ -107,7 +110,7 @@
                           timeout_in_ms,
                           timeout_in_ms,
                           timeout_in_ms)) {
-    LogErrorWinHttpMessage("WinHttpSetTimeouts");
+    LOG(ERROR) << WinHttpMessage("WinHttpSetTimeouts");
     return false;
   }
 
@@ -121,7 +124,7 @@
   // https://msdn.microsoft.com/en-us/library/aa384092.aspx
   if (!WinHttpCrackUrl(
           url_wide.c_str(), 0, 0, &url_components)) {
-    LogErrorWinHttpMessage("WinHttpCrackUrl");
+    LOG(ERROR) << WinHttpMessage("WinHttpCrackUrl");
     return false;
   }
   DCHECK(url_components.nScheme == INTERNET_SCHEME_HTTP ||
@@ -136,7 +139,7 @@
   ScopedHINTERNET connect(WinHttpConnect(
       session.get(), host_name.c_str(), url_components.nPort, 0));
   if (!connect.get()) {
-    LogErrorWinHttpMessage("WinHttpConnect");
+    LOG(ERROR) << WinHttpMessage("WinHttpConnect");
     return false;
   }
 
@@ -150,57 +153,152 @@
       url_components.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE
                                                       : 0));
   if (!request.get()) {
-    LogErrorWinHttpMessage("WinHttpOpenRequest");
+    LOG(ERROR) << WinHttpMessage("WinHttpOpenRequest");
     return false;
   }
 
   // Add headers to the request.
+  //
+  // If Content-Length is not provided, implement chunked mode per RFC 7230
+  // §4.1.
+  //
+  // Note that chunked mode can only be used on Vista and later. Otherwise,
+  // WinHttpSendRequest() requires a real value for dwTotalLength, used for the
+  // Content-Length header. Determining that in the absence of a provided
+  // Content-Length would require reading the entire request body before calling
+  // WinHttpSendRequest().
+  bool chunked = true;
+  size_t content_length = 0;
   for (const auto& pair : headers()) {
-    std::wstring header_string =
-        base::UTF8ToUTF16(pair.first) + L": " + base::UTF8ToUTF16(pair.second);
-    if (!WinHttpAddRequestHeaders(
-            request.get(),
-            header_string.c_str(),
-            base::checked_cast<DWORD>(header_string.size()),
-            WINHTTP_ADDREQ_FLAG_ADD)) {
-      LogErrorWinHttpMessage("WinHttpAddRequestHeaders");
-      return false;
+    if (pair.first == kContentLength) {
+      chunked = !base::StringToSizeT(pair.second, &content_length);
+      DCHECK(!chunked);
+    } else {
+      std::wstring header_string = base::UTF8ToUTF16(pair.first) + L": " +
+                                   base::UTF8ToUTF16(pair.second) + L"\r\n";
+      if (!WinHttpAddRequestHeaders(
+              request.get(),
+              header_string.c_str(),
+              base::checked_cast<DWORD>(header_string.size()),
+              WINHTTP_ADDREQ_FLAG_ADD)) {
+        LOG(ERROR) << WinHttpMessage("WinHttpAddRequestHeaders");
+        return false;
+      }
     }
   }
 
-  // We need the Content-Length up front, so buffer in memory. We should modify
-  // the interface to not require this, and then use WinHttpWriteData after
-  // WinHttpSendRequest.
-  std::vector<uint8_t> post_data;
-
-  // Write the body of a POST if any.
-  const size_t kBufferSize = 4096;
-  for (;;) {
-    uint8_t buffer[kBufferSize];
-    FileOperationResult bytes_to_write =
-        body_stream()->GetBytesBuffer(buffer, sizeof(buffer));
-    if (bytes_to_write == 0) {
-      break;
-    } else if (bytes_to_write < 0) {
-      LOG(ERROR) << "GetBytesBuffer failed";
+  DWORD content_length_dword;
+  if (chunked) {
+    const wchar_t kTransferEncodingHeader[] = L"Transfer-Encoding: chunked\r\n";
+    if (!WinHttpAddRequestHeaders(
+            request.get(),
+            kTransferEncodingHeader,
+            base::checked_cast<DWORD>(wcslen(kTransferEncodingHeader)),
+            WINHTTP_ADDREQ_FLAG_ADD)) {
+      LOG(ERROR) << WinHttpMessage("WinHttpAddRequestHeaders");
       return false;
     }
-    post_data.insert(post_data.end(), buffer, buffer + bytes_to_write);
+
+    content_length_dword = WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH;
+  } else if (!AssignIfInRange(&content_length_dword, content_length)) {
+    content_length_dword = WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH;
   }
 
   if (!WinHttpSendRequest(request.get(),
                           WINHTTP_NO_ADDITIONAL_HEADERS,
                           0,
-                          &post_data[0],
-                          base::checked_cast<DWORD>(post_data.size()),
-                          base::checked_cast<DWORD>(post_data.size()),
+                          WINHTTP_NO_REQUEST_DATA,
+                          0,
+                          content_length_dword,
                           0)) {
-    LogErrorWinHttpMessage("WinHttpSendRequest");
+    LOG(ERROR) << WinHttpMessage("WinHttpSendRequest");
     return false;
   }
 
+  size_t total_written = 0;
+  FileOperationResult data_bytes;
+  do {
+    struct {
+      char size[8];
+      char crlf0[2];
+      uint8_t data[32 * 1024];
+      char crlf1[2];
+    } buf;
+    static_assert(sizeof(buf) == sizeof(buf.size) +
+                                 sizeof(buf.crlf0) +
+                                 sizeof(buf.data) +
+                                 sizeof(buf.crlf1),
+                  "buf should not have padding");
+
+    // Read a block of data.
+    data_bytes = body_stream()->GetBytesBuffer(buf.data, sizeof(buf.data));
+    if (data_bytes == -1) {
+      return false;
+    }
+    DCHECK_GE(data_bytes, 0);
+    DCHECK_LE(static_cast<size_t>(data_bytes), sizeof(buf.data));
+
+    void* write_start;
+    DWORD write_size;
+
+    if (chunked) {
+      // Chunked encoding uses the entirety of buf. buf.size is presented in
+      // hexadecimal without any leading "0x". The terminating CR and LF will be
+      // placed immediately following the used portion of buf.data, even if
+      // buf.data is not full, and not necessarily in buf.crlf1.
+
+      unsigned int data_bytes_ui = base::checked_cast<unsigned int>(data_bytes);
+
+      // snprintf() would NUL-terminate, but _snprintf() won’t.
+      int rv = _snprintf(buf.size, sizeof(buf.size), "%08x", data_bytes_ui);
+      DCHECK_GE(rv, 0);
+      DCHECK_EQ(static_cast<size_t>(rv), sizeof(buf.size));
+      DCHECK_NE(buf.size[sizeof(buf.size) - 1], '\0');
+
+      buf.crlf0[0] = '\r';
+      buf.crlf0[1] = '\n';
+      buf.data[data_bytes] = '\r';
+      buf.data[data_bytes + 1] = '\n';
+
+      // Skip leading zeroes in the chunk size.
+      unsigned int size_len;
+      for (size_len = sizeof(buf.size); size_len > 1; --size_len) {
+        if (buf.size[sizeof(buf.size) - size_len] != '0') {
+          break;
+        }
+      }
+
+      write_start = buf.crlf0 - size_len;
+      write_size = base::checked_cast<DWORD>(size_len + sizeof(buf.crlf0) +
+                                             data_bytes + sizeof(buf.crlf1));
+    } else {
+      // When not using chunked encoding, only use buf.data.
+      write_start = buf.data;
+      write_size = base::checked_cast<DWORD>(data_bytes);
+    }
+
+    // write_size will be 0 at EOF in non-chunked mode. Skip the write in that
+    // case. In contrast, at EOF in chunked mode, a zero-length chunk must be
+    // sent to signal EOF. This will happen when processing the EOF indicated by
+    // a 0 return from body_stream()->GetBytesBuffer() above.
+    if (write_size != 0) {
+      DWORD written;
+      if (!WinHttpWriteData(request.get(), write_start, write_size, &written)) {
+        LOG(ERROR) << WinHttpMessage("WinHttpWriteData");
+        return false;
+      }
+
+      DCHECK_EQ(written, write_size);
+      total_written += written;
+    }
+  } while (data_bytes > 0);
+
+  if (!chunked) {
+    DCHECK_EQ(total_written, content_length);
+  }
+
   if (!WinHttpReceiveResponse(request.get(), nullptr)) {
-    LogErrorWinHttpMessage("WinHttpReceiveResponse");
+    LOG(ERROR) << WinHttpMessage("WinHttpReceiveResponse");
     return false;
   }
 
@@ -214,7 +312,7 @@
           &status_code,
           &sizeof_status_code,
           WINHTTP_NO_HEADER_INDEX)) {
-    LogErrorWinHttpMessage("WinHttpQueryHeaders");
+    LOG(ERROR) << WinHttpMessage("WinHttpQueryHeaders");
     return false;
   }
 
@@ -232,10 +330,10 @@
     // which executes synchronously, is only concerned with reading until EOF.
     DWORD bytes_read = 0;
     do {
-      char read_buffer[kBufferSize];
+      char read_buffer[4096];
       if (!WinHttpReadData(
               request.get(), read_buffer, sizeof(read_buffer), &bytes_read)) {
-        LogErrorWinHttpMessage("WinHttpReadData");
+        LOG(ERROR) << WinHttpMessage("WinHttpReadData");
         return false;
       }
 
diff --git a/third_party/crashpad/crashpad/util/win/process_info.cc b/third_party/crashpad/crashpad/util/win/process_info.cc
index d05a23d..2e285b8 100644
--- a/third_party/crashpad/crashpad/util/win/process_info.cc
+++ b/third_party/crashpad/crashpad/util/win/process_info.cc
@@ -19,9 +19,12 @@
 #include <algorithm>
 #include <limits>
 #include <memory>
+#include <new>
 #include <type_traits>
 
 #include "base/logging.h"
+#include "base/memory/free_deleter.h"
+#include "base/process/memory.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "util/numeric/safe_assignment.h"
@@ -36,6 +39,16 @@
 
 namespace {
 
+using UniqueMallocPtr = std::unique_ptr<uint8_t[], base::FreeDeleter>;
+
+UniqueMallocPtr UncheckedAllocate(size_t size) {
+  void* raw_ptr = nullptr;
+  if (!base::UncheckedMalloc(size, &raw_ptr))
+    return UniqueMallocPtr();
+
+  return UniqueMallocPtr(new (raw_ptr) uint8_t[size]);
+}
+
 NTSTATUS NtQueryInformationProcess(HANDLE process_handle,
                                    PROCESSINFOCLASS process_information_class,
                                    PVOID process_information,
@@ -347,14 +360,20 @@
 std::vector<ProcessInfo::Handle> ProcessInfo::BuildHandleVector(
     HANDLE process) const {
   ULONG buffer_size = 2 * 1024 * 1024;
-  std::unique_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
-
   // Typically if the buffer were too small, STATUS_INFO_LENGTH_MISMATCH would
   // return the correct size in the final argument, but it does not for
   // SystemExtendedHandleInformation, so we loop and attempt larger sizes.
   NTSTATUS status;
   ULONG returned_length;
+  UniqueMallocPtr buffer;
   for (int tries = 0; tries < 5; ++tries) {
+    buffer.reset();
+    buffer = UncheckedAllocate(buffer_size);
+    if (!buffer) {
+      LOG(ERROR) << "UncheckedAllocate";
+      return std::vector<Handle>();
+    }
+
     status = crashpad::NtQuerySystemInformation(
         static_cast<SYSTEM_INFORMATION_CLASS>(SystemExtendedHandleInformation),
         buffer.get(),
@@ -364,8 +383,6 @@
       break;
 
     buffer_size *= 2;
-    buffer.reset();
-    buffer.reset(new uint8_t[buffer_size]);
   }
 
   if (!NT_SUCCESS(status)) {
diff --git a/third_party/crashpad/crashpad/util/win/process_info.h b/third_party/crashpad/crashpad/util/win/process_info.h
index 0bb8d7356..be968f9 100644
--- a/third_party/crashpad/crashpad/util/win/process_info.h
+++ b/third_party/crashpad/crashpad/util/win/process_info.h
@@ -170,6 +170,7 @@
                              bool is_64_bit,
                              ProcessInfo* process_info);
 
+  // This function is best-effort under low memory conditions.
   std::vector<Handle> BuildHandleVector(HANDLE process) const;
 
   pid_t process_id_;
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index d263a8cc..099b2bd 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -33,6 +33,8 @@
     for (const auto& arg : args) {
       if (arg == "dump-graph") {
         options_.dump_graph = true;
+      } else if (arg == "warn-stack-allocated-trace-method") {
+        options_.warn_stack_allocated_trace_method = true;
       } else if (arg == "warn-unneeded-finalizer") {
         options_.warn_unneeded_finalizer = true;
       } else if (arg == "use-chromium-style-naming") {
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp b/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
index c15b8e8..28af4bc0 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
@@ -181,6 +181,8 @@
     return;
 
   if (CXXMethodDecl* trace = info->GetTraceMethod()) {
+    if (options_.warn_stack_allocated_trace_method && info->IsStackAllocated())
+      reporter_.TraceMethodForStackAllocatedClass(info, trace);
     if (trace->isPure())
       reporter_.ClassDeclaresPureVirtualTrace(info, trace);
   } else if (info->RequiresTraceMethod()) {
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h b/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
index baaa2ff..0df51cd 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
+++ b/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
@@ -11,9 +11,17 @@
 
 struct BlinkGCPluginOptions {
   bool dump_graph = false;
+
+  // If |true|, emit warning if stack allocated class types provide
+  // a trace method.
+  bool warn_stack_allocated_trace_method = false;
+  // If |true|, emit warning for class types which derive from from
+  // GarbageCollectedFinalized<> when just GarbageCollected<> will do.
   bool warn_unneeded_finalizer = false;
+
   // TODO(https://crbug.com/675879): Clean up after the Blink rename.
   bool use_chromium_style_naming = false;
+
   std::set<std::string> ignored_classes;
   std::set<std::string> checked_namespaces;
   std::vector<std::string> ignored_directories;
diff --git a/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp b/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
index a43cfdb0d..95d5595 100644
--- a/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
+++ b/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
@@ -150,6 +150,10 @@
 const char kIteratorToGCManagedCollectionNote[] =
     "[blink-gc] Iterator field %0 to a GC managed collection declared here:";
 
+const char kTraceMethodOfStackAllocatedParentNote[] =
+    "[blink-gc] The stack allocated class %0 provides an unnecessary "
+    "trace method:";
+
 } // namespace
 
 DiagnosticBuilder DiagnosticsReporter::ReportDiagnostic(
@@ -212,6 +216,8 @@
       getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
   diag_iterator_to_gc_managed_collection_note_ = diagnostic_.getCustomDiagID(
       getErrorLevel(), kIteratorToGCManagedCollectionNote);
+  diag_trace_method_of_stack_allocated_parent_ = diagnostic_.getCustomDiagID(
+      getErrorLevel(), kTraceMethodOfStackAllocatedParentNote);
 
   // Register note messages.
   diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
@@ -499,6 +505,14 @@
       << base << derived->record();
 }
 
+void DiagnosticsReporter::TraceMethodForStackAllocatedClass(
+    RecordInfo* info,
+    CXXMethodDecl* trace) {
+  ReportDiagnostic(trace->getLocStart(),
+                   diag_trace_method_of_stack_allocated_parent_)
+      << info->record();
+}
+
 void DiagnosticsReporter::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
   ReportDiagnostic(dispatch->getLocStart(),
                    diag_manual_dispatch_method_note_)
diff --git a/tools/clang/blink_gc_plugin/DiagnosticsReporter.h b/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
index ddcfbfd7..6a32f70 100644
--- a/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
+++ b/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
@@ -62,6 +62,8 @@
                                      clang::CXXRecordDecl* base);
   void BaseClassMustDeclareVirtualTrace(RecordInfo* derived,
                                               clang::CXXRecordDecl* base);
+  void TraceMethodForStackAllocatedClass(RecordInfo* parent,
+                                         clang::CXXMethodDecl* trace);
 
   void NoteManualDispatchMethod(clang::CXXMethodDecl* dispatch);
   void NoteBaseRequiresTracing(BasePoint* base);
@@ -136,6 +138,7 @@
   unsigned diag_overridden_non_virtual_trace_note_;
   unsigned diag_manual_dispatch_method_note_;
   unsigned diag_iterator_to_gc_managed_collection_note_;
+  unsigned diag_trace_method_of_stack_allocated_parent_;
 };
 
 #endif // TOOLS_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_
diff --git a/tools/clang/blink_gc_plugin/tests/.gitignore b/tools/clang/blink_gc_plugin/tests/.gitignore
index cc5bb740..8564477b 100644
--- a/tools/clang/blink_gc_plugin/tests/.gitignore
+++ b/tools/clang/blink_gc_plugin/tests/.gitignore
@@ -1 +1,2 @@
 /*.o
+/*.txt.actual
diff --git a/tools/clang/blink_gc_plugin/tests/legacy_naming/.gitignore b/tools/clang/blink_gc_plugin/tests/legacy_naming/.gitignore
index cc5bb740..8564477b 100644
--- a/tools/clang/blink_gc_plugin/tests/legacy_naming/.gitignore
+++ b/tools/clang/blink_gc_plugin/tests/legacy_naming/.gitignore
@@ -1 +1,2 @@
 /*.o
+/*.txt.actual
diff --git a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.flags b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.flags
new file mode 100644
index 0000000..7ec7af4
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-blink-gc-plugin -Xclang warn-stack-allocated-trace-method
\ No newline at end of file
diff --git a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.h b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.h
index 10d8f41..22100ec 100644
--- a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.h
+++ b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.h
@@ -19,6 +19,10 @@
 
 class StackObject {
     STACK_ALLOCATED();
+
+    // Redundant trace() method, warning/error expected.
+    void trace(Visitor* visitor) { visitor->trace(m_obj); }
+
 private:
     Member<HeapObject> m_obj; // Does not need tracing.
 };
diff --git a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.txt b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.txt
index 80980c3..5eb6220 100644
--- a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.txt
+++ b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated.txt
@@ -5,19 +5,22 @@
 ./stack_allocated.h:17:5: note: [blink-gc] Untraced field 'm_obj' declared here:
     Member<HeapObject> m_obj; // Needs tracing.
     ^
-./stack_allocated.h:26:1: warning: [blink-gc] Class 'HeapObject' contains invalid fields.
+./stack_allocated.h:24:5: warning: [blink-gc] The stack allocated class 'StackObject' provides an unnecessary trace method:
+    void trace(Visitor* visitor) { visitor->trace(m_obj); }
+    ^
+./stack_allocated.h:30:1: warning: [blink-gc] Class 'HeapObject' contains invalid fields.
 class HeapObject : public GarbageCollected<HeapObject> {
 ^
-./stack_allocated.h:30:5: note: [blink-gc] Stack-allocated field 'm_part' declared here:
+./stack_allocated.h:34:5: note: [blink-gc] Stack-allocated field 'm_part' declared here:
     StackObject m_part; // Cannot embed a stack allocated object.
     ^
-./stack_allocated.h:34:27: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject' derives class 'HeapObject' which is garbage collected.
+./stack_allocated.h:38:27: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject' derives class 'HeapObject' which is garbage collected.
 class DerivedHeapObject : public HeapObject, public StackObject {
                           ^
-./stack_allocated.h:38:28: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject2' derives class 'HeapObject' which is garbage collected.
+./stack_allocated.h:42:28: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject2' derives class 'HeapObject' which is garbage collected.
 class DerivedHeapObject2 : public HeapObject {
                            ^
-./stack_allocated.h:39:3: warning: [blink-gc] Garbage collected class 'DerivedHeapObject2' is not permitted to override its new operator.
+./stack_allocated.h:43:3: warning: [blink-gc] Garbage collected class 'DerivedHeapObject2' is not permitted to override its new operator.
   STACK_ALLOCATED();
   ^
 ./heap/stubs.h:178:5: note: expanded from macro 'STACK_ALLOCATED'
@@ -29,4 +32,4 @@
 stack_allocated.cpp:14:5: note: [blink-gc] Raw pointer field 'm_obj' to a GC managed class declared here:
     HeapObject* m_obj;
     ^
-6 warnings generated.
+7 warnings generated.
diff --git a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.cpp b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.cpp
new file mode 100644
index 0000000..d12af98
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.cpp
@@ -0,0 +1,5 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "stack_allocated_no_warning.h"
diff --git a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.h b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.h
new file mode 100644
index 0000000..3891d2a
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.h
@@ -0,0 +1,26 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef STACK_ALLOCATED_H_
+#define STACK_ALLOCATED_H_
+
+#include "heap/stubs.h"
+
+namespace blink {
+
+class HeapObject;
+
+class StackObject {
+    STACK_ALLOCATED();
+
+    // Redundant trace() method, but warning/error disabled.
+    void trace(Visitor* visitor) { visitor->trace(m_obj); }
+
+private:
+    Member<HeapObject> m_obj; // Does not need tracing.
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.txt b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/legacy_naming/stack_allocated_no_warning.txt
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated.flags b/tools/clang/blink_gc_plugin/tests/stack_allocated.flags
new file mode 100644
index 0000000..7ec7af4
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-blink-gc-plugin -Xclang warn-stack-allocated-trace-method
\ No newline at end of file
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated.h b/tools/clang/blink_gc_plugin/tests/stack_allocated.h
index 574219c..50a4632a 100644
--- a/tools/clang/blink_gc_plugin/tests/stack_allocated.h
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated.h
@@ -19,6 +19,10 @@
 
 class StackObject {
     STACK_ALLOCATED();
+
+    // Redundant trace() method, warning/error expected.
+    void Trace(Visitor* visitor) { visitor->Trace(m_obj); }
+
 private:
     Member<HeapObject> m_obj; // Does not need tracing.
 };
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated.txt b/tools/clang/blink_gc_plugin/tests/stack_allocated.txt
index 80980c3..f9c7a15 100644
--- a/tools/clang/blink_gc_plugin/tests/stack_allocated.txt
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated.txt
@@ -5,19 +5,22 @@
 ./stack_allocated.h:17:5: note: [blink-gc] Untraced field 'm_obj' declared here:
     Member<HeapObject> m_obj; // Needs tracing.
     ^
-./stack_allocated.h:26:1: warning: [blink-gc] Class 'HeapObject' contains invalid fields.
+./stack_allocated.h:24:5: warning: [blink-gc] The stack allocated class 'StackObject' provides an unnecessary trace method:
+    void Trace(Visitor* visitor) { visitor->Trace(m_obj); }
+    ^
+./stack_allocated.h:30:1: warning: [blink-gc] Class 'HeapObject' contains invalid fields.
 class HeapObject : public GarbageCollected<HeapObject> {
 ^
-./stack_allocated.h:30:5: note: [blink-gc] Stack-allocated field 'm_part' declared here:
+./stack_allocated.h:34:5: note: [blink-gc] Stack-allocated field 'm_part' declared here:
     StackObject m_part; // Cannot embed a stack allocated object.
     ^
-./stack_allocated.h:34:27: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject' derives class 'HeapObject' which is garbage collected.
+./stack_allocated.h:38:27: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject' derives class 'HeapObject' which is garbage collected.
 class DerivedHeapObject : public HeapObject, public StackObject {
                           ^
-./stack_allocated.h:38:28: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject2' derives class 'HeapObject' which is garbage collected.
+./stack_allocated.h:42:28: warning: [blink-gc] Stack-allocated class 'DerivedHeapObject2' derives class 'HeapObject' which is garbage collected.
 class DerivedHeapObject2 : public HeapObject {
                            ^
-./stack_allocated.h:39:3: warning: [blink-gc] Garbage collected class 'DerivedHeapObject2' is not permitted to override its new operator.
+./stack_allocated.h:43:3: warning: [blink-gc] Garbage collected class 'DerivedHeapObject2' is not permitted to override its new operator.
   STACK_ALLOCATED();
   ^
 ./heap/stubs.h:178:5: note: expanded from macro 'STACK_ALLOCATED'
@@ -29,4 +32,4 @@
 stack_allocated.cpp:14:5: note: [blink-gc] Raw pointer field 'm_obj' to a GC managed class declared here:
     HeapObject* m_obj;
     ^
-6 warnings generated.
+7 warnings generated.
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.cpp b/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.cpp
new file mode 100644
index 0000000..d12af98
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.cpp
@@ -0,0 +1,5 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "stack_allocated_no_warning.h"
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.h b/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.h
new file mode 100644
index 0000000..fe2c95a
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.h
@@ -0,0 +1,26 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef STACK_ALLOCATED_H_
+#define STACK_ALLOCATED_H_
+
+#include "heap/stubs.h"
+
+namespace blink {
+
+class HeapObject;
+
+class StackObject {
+    STACK_ALLOCATED();
+
+    // Redundant trace() method, but warning/error disabled.
+    void Trace(Visitor* visitor) { visitor->Trace(m_obj); }
+
+private:
+    Member<HeapObject> m_obj; // Does not need tracing.
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.txt b/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated_no_warning.txt
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
index 8fa8ec2..9f94e9b 100644
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -51,6 +51,8 @@
 const char kBlinkFieldPrefix[] = "m_";
 const char kBlinkStaticMemberPrefix[] = "s_";
 const char kGeneratedFileRegex[] = "^gen/|/gen/";
+const char kGeneratedFileExclusionRegex[] =
+    "(^gen/|/gen/).*/ComputedStyleBase\\.h$";
 const char kGMockMethodNamePrefix[] = "gmock_";
 const char kMethodBlocklistParamName[] = "method-blocklist";
 
@@ -508,6 +510,41 @@
   return Node.getDeclName().isIdentifier() && IsKnownTraitName(Node.getName());
 }
 
+AST_MATCHER(clang::Decl, isDeclInGeneratedFile) {
+  // This matcher mimics the built-in isExpansionInFileMatching matcher from
+  // llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h, except:
+  // - It special cases some files (e.g. doesn't skip renaming of identifiers
+  //   from gen/blink/core/ComputedStyleBase.h)
+
+  const clang::SourceManager& source_manager =
+      Node.getASTContext().getSourceManager();
+
+  // TODO(lukasza): Consider using getSpellingLoc below.
+  // The built-in isExpansionInFileMatching matcher uses getExpansionLoc below.
+  // We could consider using getSpellingLoc (which properly handles things like
+  // SETTINGS_GETTERS_AND_SETTERS macro which is defined in generated code
+  // (gen/blink/core/SettingsMacros.h), but expanded in non-generated code
+  // (third_party/WebKit/Source/core/frame/Settings.h).
+  clang::SourceLocation loc =
+      source_manager.getExpansionLoc(Node.getLocStart());
+
+  // TODO(lukasza): jump out of scratch space if token concatenation was used.
+  if (loc.isInvalid())
+    return false;
+
+  const clang::FileEntry* file_entry =
+      source_manager.getFileEntryForID(source_manager.getFileID(loc));
+  if (!file_entry)
+    return false;
+
+  static llvm::Regex exclusion_regex(kGeneratedFileExclusionRegex);
+  if (exclusion_regex.match(file_entry->getName()))
+    return false;
+
+  static llvm::Regex generated_file_regex(kGeneratedFileRegex);
+  return generated_file_regex.match(file_entry->getName());
+}
+
 // Helper to convert from a camelCaseName to camel_case_name. It uses some
 // heuristics to try to handle acronyms in camel case names correctly.
 std::string CamelCaseToUnderscoreCase(StringRef input) {
@@ -1516,7 +1553,7 @@
   auto in_blink_namespace = decl(
       anyOf(decl_under_blink_namespace, decl_has_qualifier_to_blink_namespace,
             hasAncestor(decl_has_qualifier_to_blink_namespace)),
-      unless(hasCanonicalDecl(isExpansionInFileMatching(kGeneratedFileRegex))));
+      unless(hasCanonicalDecl(isDeclInGeneratedFile())));
 
   // Field, variable, and enum declarations ========
   // Given
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 166559b6..0886fdfd 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -4356,11 +4356,13 @@
   <description>
     Count of Flash plugin instances that use JavaScript.
   </description>
+  <obsolete>Deprecated 02/2017.</obsolete>
 </action>
 
 <action name="Flash.PluginInstanceCreated" not_user_triggered="true">
   <owner>thestig@chromium.org</owner>
   <description>Count of Flash plugin instances.</description>
+  <obsolete>Deprecated 02/2017.</obsolete>
 </action>
 
 <action name="FocusAppMenu">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index adde8ff..0191421 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -24876,6 +24876,9 @@
 </histogram>
 
 <histogram name="Media.AudioRendererIpcStreams">
+  <obsolete>
+    Deprecated 02/2017. No longer needed.
+  </obsolete>
   <owner>grunell@chromium.org</owner>
   <summary>
     The maximum number of simultaneous audio render streams over IPC created in
@@ -24884,6 +24887,9 @@
 </histogram>
 
 <histogram name="Media.AudioRendererIpcStreamsTotal">
+  <obsolete>
+    Deprecated 02/2017. No longer needed.
+  </obsolete>
   <owner>grunell@chromium.org</owner>
   <summary>
     The maximum number of simultaneous audio render streams over IPC created in
@@ -52577,6 +52583,16 @@
   </summary>
 </histogram>
 
+<histogram name="PurgeAndSuspend.Experimental.TimeToFirstActivePaint"
+    units="ms">
+  <owner>tasak@google.com</owner>
+  <summary>
+    Time elapsed from when the backgrounded and purged renderer is foregrounded
+    until the renderer is painted. This is recorded every time the backgrounded
+    and purged renderer is foregrounded.
+  </summary>
+</histogram>
+
 <histogram name="PurgeAndSuspend.Memory.BlinkGCKB" units="KB">
   <owner>tasak@google.com</owner>
   <summary>
@@ -90931,6 +90947,8 @@
   <int value="1804" label="FullscreenRequestWithPendingElement"/>
   <int value="1805"
       label="HTMLIFrameElementAllowfullscreenAttributeSetAfterContentLoad"/>
+  <int value="1806" label="PointerEventSetCaptureOutsideDispatch"/>
+  <int value="1807" label="NotificationPermissionRequestedInsecureOrigin"/>
 </enum>
 
 <enum name="FetchRequestMode" type="int">
@@ -96862,6 +96880,7 @@
   <int value="201343576" label="enable-password-change-support:enabled"/>
   <int value="203776499" label="enable-virtual-keyboard-overscroll"/>
   <int value="223662457" label="BackgroundLoadingForDownloads:enabled"/>
+  <int value="243557364" label="ash-force-enable-palette"/>
   <int value="244697230" label="enable-theme-color-in-tabbed-mode"/>
   <int value="262382944" label="GuestViewCrossProcessFrames:disabled"/>
   <int value="266702296" label="disable-plugin-power-saver"/>
diff --git a/ui/accessibility/platform/ax_platform_node.h b/ui/accessibility/platform/ax_platform_node.h
index c9df259..ec52635 100644
--- a/ui/accessibility/platform/ax_platform_node.h
+++ b/ui/accessibility/platform/ax_platform_node.h
@@ -11,7 +11,7 @@
 #include "ui/gfx/native_widget_types.h"
 
 // Set PLATFORM_HAS_AX_PLATFORM_NODE_IMPL if this platform has a specific
-// implementation of AxPlatfromNode::Create().
+// implementation of AXPlatformNode::Create().
 #undef PLATFORM_HAS_AX_PLATFORM_NODE_IMPL
 
 #if defined(OS_WIN)
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
index bc1fd094..b72f5e8 100644
--- a/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -5,6 +5,7 @@
 #include "ui/accessibility/platform/ax_platform_node_base.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -204,4 +205,14 @@
       AXPlatformNode::FromNativeViewAccessible(accessible));
 }
 
+bool AXPlatformNodeBase::SetTextSelection(int start_offset, int end_offset) {
+  ui::AXActionData action_data;
+  action_data.action = ui::AX_ACTION_SET_SELECTION;
+  action_data.anchor_node_id = action_data.focus_node_id = GetData().id;
+  action_data.anchor_offset = start_offset;
+  action_data.focus_offset = end_offset;
+  DCHECK(delegate_);
+  return delegate_->AccessibilityPerformAction(action_data);
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h
index 45e316c..78ea0fc 100644
--- a/ui/accessibility/platform/ax_platform_node_base.h
+++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -75,6 +75,9 @@
 
   virtual void Dispose();
 
+  // Sets the text selection in this object if possible.
+  bool SetTextSelection(int start_offset, int end_offset);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeBase);
 };
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 5028f2da..428222e 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -854,6 +854,48 @@
   return S_OK;
 }
 
+STDMETHODIMP AXPlatformNodeWin::addSelection(LONG start_offset,
+                                             LONG end_offset) {
+  // We only support one selection.
+  return setSelection(0, start_offset, end_offset);
+}
+
+STDMETHODIMP AXPlatformNodeWin::removeSelection(LONG selection_index) {
+  if (selection_index != 0)
+    return E_INVALIDARG;
+  // Simply collapse the selection to the position of the caret if a caret is
+  // visible, otherwise set the selection to 0.
+  return setCaretOffset(GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END));
+}
+
+STDMETHODIMP AXPlatformNodeWin::setCaretOffset(LONG offset) {
+  return setSelection(0, offset, offset);
+}
+
+STDMETHODIMP AXPlatformNodeWin::setSelection(LONG selection_index,
+                                             LONG start_offset,
+                                             LONG end_offset) {
+  if (selection_index != 0)
+    return E_INVALIDARG;
+
+  HandleSpecialTextOffset(&start_offset);
+  HandleSpecialTextOffset(&end_offset);
+  if (start_offset < 0 ||
+      start_offset > static_cast<LONG>(TextForIAccessibleText().length())) {
+    return E_INVALIDARG;
+  }
+  if (end_offset < 0 ||
+      end_offset > static_cast<LONG>(TextForIAccessibleText().length())) {
+    return E_INVALIDARG;
+  }
+
+  if (SetTextSelection(static_cast<int>(start_offset),
+                       static_cast<int>(end_offset))) {
+    return S_OK;
+  }
+  return E_FAIL;
+}
+
 //
 // IAccessibleText methods not implemented.
 //
@@ -864,16 +906,6 @@
 STDMETHODIMP AXPlatformNodeWin::get_oldText(IA2TextSegment* old_text) {
   return E_NOTIMPL;
 }
-STDMETHODIMP AXPlatformNodeWin::addSelection(LONG start_offset,
-                                             LONG end_offset) {
-  return E_NOTIMPL;
-}
-STDMETHODIMP AXPlatformNodeWin::get_attributes(LONG offset,
-                                               LONG* start_offset,
-                                               LONG* end_offset,
-                                               BSTR* text_attributes) {
-  return E_NOTIMPL;
-}
 STDMETHODIMP AXPlatformNodeWin::get_characterExtents(
     LONG offset,
     enum IA2CoordinateType coord_type,
@@ -883,17 +915,6 @@
     LONG* height) {
   return E_NOTIMPL;
 }
-STDMETHODIMP AXPlatformNodeWin::removeSelection(LONG selection_index) {
-  return E_NOTIMPL;
-}
-STDMETHODIMP AXPlatformNodeWin::setCaretOffset(LONG offset) {
-  return E_NOTIMPL;
-}
-STDMETHODIMP AXPlatformNodeWin::setSelection(LONG selection_index,
-                                             LONG start_offset,
-                                             LONG end_offset) {
-  return E_NOTIMPL;
-}
 STDMETHODIMP AXPlatformNodeWin::scrollSubstringTo(
     LONG start_index,
     LONG end_index,
@@ -908,6 +929,12 @@
     LONG y) {
   return E_NOTIMPL;
 }
+STDMETHODIMP AXPlatformNodeWin::get_attributes(LONG offset,
+                                               LONG* start_offset,
+                                               LONG* end_offset,
+                                               BSTR* text_attributes) {
+  return E_NOTIMPL;
+}
 
 //
 // IServiceProvider implementation.
@@ -1131,14 +1158,12 @@
 base::string16 AXPlatformNodeWin::TextForIAccessibleText() {
   if (GetData().role == ui::AX_ROLE_TEXT_FIELD)
     return GetString16Attribute(ui::AX_ATTR_VALUE);
-  else
-    return GetString16Attribute(ui::AX_ATTR_NAME);
+  return GetString16Attribute(ui::AX_ATTR_NAME);
 }
 
-void AXPlatformNodeWin::HandleSpecialTextOffset(
-    const base::string16& text, LONG* offset) {
+void AXPlatformNodeWin::HandleSpecialTextOffset(LONG* offset) {
   if (*offset == IA2_TEXT_OFFSET_LENGTH) {
-    *offset = static_cast<LONG>(text.size());
+    *offset = static_cast<LONG>(TextForIAccessibleText().length());
   } else if (*offset == IA2_TEXT_OFFSET_CARET) {
     get_caretOffset(offset);
   }
@@ -1164,7 +1189,7 @@
     IA2TextBoundaryType ia2_boundary,
     LONG start_offset,
     ui::TextBoundaryDirection direction) {
-  HandleSpecialTextOffset(text, &start_offset);
+  HandleSpecialTextOffset(&start_offset);
   ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
   std::vector<int32_t> line_breaks;
   return static_cast<LONG>(ui::FindAccessibleTextBoundary(
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index 4d84e8d..c676983 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -288,7 +288,7 @@
 
   // If offset is a member of IA2TextSpecialOffsets this function updates the
   // value of offset and returns, otherwise offset remains unchanged.
-  void HandleSpecialTextOffset(const base::string16& text, LONG* offset);
+  void HandleSpecialTextOffset(LONG* offset);
 
   // Convert from a IA2TextBoundaryType to a ui::TextBoundaryType.
   ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type);
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index e8207d1..85f9940 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -95,6 +95,7 @@
 
   ScopedComPtr<IAccessible2> ToIAccessible2(
       ScopedComPtr<IAccessible> accessible) {
+    CHECK(accessible.get());
     ScopedComPtr<IServiceProvider> service_provider;
     service_provider.QueryFrom(accessible.get());
     ScopedComPtr<IAccessible2> result;
@@ -114,12 +115,12 @@
 
   ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
   ScopedBstr name;
-  ASSERT_EQ(S_OK, root_obj->get_accName(SELF, name.Receive()));
-  EXPECT_EQ(L"Name", base::string16(name));
+  EXPECT_EQ(S_OK, root_obj->get_accName(SELF, name.Receive()));
+  EXPECT_STREQ(L"Name", name);
 
   tree_.reset(new AXTree());
   ScopedBstr name2;
-  ASSERT_EQ(E_FAIL, root_obj->get_accName(SELF, name2.Receive()));
+  EXPECT_EQ(E_FAIL, root_obj->get_accName(SELF, name2.Receive()));
 }
 
 TEST_F(AXPlatformNodeWinTest, TestIAccessibleName) {
@@ -130,13 +131,13 @@
 
   ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
   ScopedBstr name;
-  ASSERT_EQ(S_OK, root_obj->get_accName(SELF, name.Receive()));
-  EXPECT_EQ(L"Name", base::string16(name));
+  EXPECT_EQ(S_OK, root_obj->get_accName(SELF, name.Receive()));
+  EXPECT_STREQ(L"Name", name);
 
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accName(SELF, nullptr));
+  EXPECT_EQ(E_INVALIDARG, root_obj->get_accName(SELF, nullptr));
   ScopedVariant bad_id(999);
   ScopedBstr name2;
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accName(bad_id, name2.Receive()));
+  EXPECT_EQ(E_INVALIDARG, root_obj->get_accName(bad_id, name2.Receive()));
 }
 
 TEST_F(AXPlatformNodeWinTest, TestIAccessibleDescription) {
@@ -147,13 +148,13 @@
 
   ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
   ScopedBstr description;
-  ASSERT_EQ(S_OK, root_obj->get_accDescription(SELF, description.Receive()));
-  EXPECT_EQ(L"Description", base::string16(description));
+  EXPECT_EQ(S_OK, root_obj->get_accDescription(SELF, description.Receive()));
+  EXPECT_STREQ(L"Description", description);
 
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accDescription(SELF, nullptr));
+  EXPECT_EQ(E_INVALIDARG, root_obj->get_accDescription(SELF, nullptr));
   ScopedVariant bad_id(999);
   ScopedBstr d2;
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accDescription(bad_id, d2.Receive()));
+  EXPECT_EQ(E_INVALIDARG, root_obj->get_accDescription(bad_id, d2.Receive()));
 }
 
 TEST_F(AXPlatformNodeWinTest, TestIAccessibleValue) {
@@ -164,13 +165,13 @@
 
   ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
   ScopedBstr value;
-  ASSERT_EQ(S_OK, root_obj->get_accValue(SELF, value.Receive()));
-  EXPECT_EQ(L"Value", base::string16(value));
+  EXPECT_EQ(S_OK, root_obj->get_accValue(SELF, value.Receive()));
+  EXPECT_STREQ(L"Value", value);
 
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accValue(SELF, nullptr));
+  EXPECT_EQ(E_INVALIDARG, root_obj->get_accValue(SELF, nullptr));
   ScopedVariant bad_id(999);
   ScopedBstr v2;
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accValue(bad_id, v2.Receive()));
+  EXPECT_EQ(E_INVALIDARG, root_obj->get_accValue(bad_id, v2.Receive()));
 }
 
 TEST_F(AXPlatformNodeWinTest, TestIAccessibleShortcut) {
@@ -181,15 +182,14 @@
 
   ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
   ScopedBstr shortcut;
-  ASSERT_EQ(S_OK, root_obj->get_accKeyboardShortcut(
-      SELF, shortcut.Receive()));
-  EXPECT_EQ(L"Shortcut", base::string16(shortcut));
+  EXPECT_EQ(S_OK, root_obj->get_accKeyboardShortcut(SELF, shortcut.Receive()));
+  EXPECT_STREQ(L"Shortcut", shortcut);
 
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accKeyboardShortcut(SELF, nullptr));
+  EXPECT_EQ(E_INVALIDARG, root_obj->get_accKeyboardShortcut(SELF, nullptr));
   ScopedVariant bad_id(999);
   ScopedBstr k2;
-  ASSERT_EQ(E_INVALIDARG, root_obj->get_accKeyboardShortcut(
-      bad_id, k2.Receive()));
+  EXPECT_EQ(E_INVALIDARG,
+            root_obj->get_accKeyboardShortcut(bad_id, k2.Receive()));
 }
 
 TEST_F(AXPlatformNodeWinTest, TestIAccessibleRole) {
@@ -209,23 +209,23 @@
 
   child.role = AX_ROLE_ALERT;
   child_node->SetData(child);
-  ASSERT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
+  EXPECT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
   EXPECT_EQ(ROLE_SYSTEM_ALERT, V_I4(role.ptr()));
 
   child.role = AX_ROLE_BUTTON;
   child_node->SetData(child);
-  ASSERT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
+  EXPECT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
   EXPECT_EQ(ROLE_SYSTEM_PUSHBUTTON, V_I4(role.ptr()));
 
   child.role = AX_ROLE_POP_UP_BUTTON;
   child_node->SetData(child);
-  ASSERT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
+  EXPECT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
   EXPECT_EQ(ROLE_SYSTEM_BUTTONMENU, V_I4(role.ptr()));
 
-  ASSERT_EQ(E_INVALIDARG, child_iaccessible->get_accRole(SELF, nullptr));
+  EXPECT_EQ(E_INVALIDARG, child_iaccessible->get_accRole(SELF, nullptr));
   ScopedVariant bad_id(999);
-  ASSERT_EQ(E_INVALIDARG, child_iaccessible->get_accRole(
-      bad_id, role.Receive()));
+  EXPECT_EQ(E_INVALIDARG,
+            child_iaccessible->get_accRole(bad_id, role.Receive()));
 }
 
 TEST_F(AXPlatformNodeWinTest, TestIAccessibleLocation) {
@@ -237,24 +237,24 @@
   TestAXNodeWrapper::SetGlobalCoordinateOffset(gfx::Vector2d(100, 200));
 
   LONG x_left, y_top, width, height;
-  ASSERT_EQ(S_OK, GetRootIAccessible()->accLocation(
-      &x_left, &y_top, &width, &height, SELF));
+  EXPECT_EQ(S_OK, GetRootIAccessible()->accLocation(&x_left, &y_top, &width,
+                                                    &height, SELF));
   EXPECT_EQ(110, x_left);
   EXPECT_EQ(240, y_top);
   EXPECT_EQ(800, width);
   EXPECT_EQ(600, height);
 
-  ASSERT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
-      nullptr, &y_top, &width, &height, SELF));
-  ASSERT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
-      &x_left, nullptr, &width, &height, SELF));
-  ASSERT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
-      &x_left, &y_top, nullptr, &height, SELF));
-  ASSERT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
-      &x_left, &y_top, &width, nullptr, SELF));
+  EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
+                              nullptr, &y_top, &width, &height, SELF));
+  EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
+                              &x_left, nullptr, &width, &height, SELF));
+  EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
+                              &x_left, &y_top, nullptr, &height, SELF));
+  EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
+                              &x_left, &y_top, &width, nullptr, SELF));
   ScopedVariant bad_id(999);
-  ASSERT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
-      &x_left, &y_top, &width, &height, bad_id));
+  EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
+                              &x_left, &y_top, &width, &height, bad_id));
 }
 
 TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
@@ -281,38 +281,38 @@
       IAccessibleFromNode(checkbox_node));
 
   LONG child_count;
-  ASSERT_EQ(S_OK, root_iaccessible->get_accChildCount(&child_count));
-  ASSERT_EQ(2L, child_count);
-  ASSERT_EQ(S_OK, button_iaccessible->get_accChildCount(&child_count));
-  ASSERT_EQ(0L, child_count);
-  ASSERT_EQ(S_OK, checkbox_iaccessible->get_accChildCount(&child_count));
-  ASSERT_EQ(0L, child_count);
+  EXPECT_EQ(S_OK, root_iaccessible->get_accChildCount(&child_count));
+  EXPECT_EQ(2L, child_count);
+  EXPECT_EQ(S_OK, button_iaccessible->get_accChildCount(&child_count));
+  EXPECT_EQ(0L, child_count);
+  EXPECT_EQ(S_OK, checkbox_iaccessible->get_accChildCount(&child_count));
+  EXPECT_EQ(0L, child_count);
 
   {
     ScopedComPtr<IDispatch> result;
-    ASSERT_EQ(S_OK, root_iaccessible->get_accChild(SELF, result.Receive()));
-    ASSERT_EQ(result.get(), root_iaccessible);
+    EXPECT_EQ(S_OK, root_iaccessible->get_accChild(SELF, result.Receive()));
+    EXPECT_EQ(result.get(), root_iaccessible);
   }
 
   {
     ScopedComPtr<IDispatch> result;
     ScopedVariant child1(1);
-    ASSERT_EQ(S_OK, root_iaccessible->get_accChild(child1, result.Receive()));
-    ASSERT_EQ(result.get(), button_iaccessible);
+    EXPECT_EQ(S_OK, root_iaccessible->get_accChild(child1, result.Receive()));
+    EXPECT_EQ(result.get(), button_iaccessible);
   }
 
   {
     ScopedComPtr<IDispatch> result;
     ScopedVariant child2(2);
-    ASSERT_EQ(S_OK, root_iaccessible->get_accChild(child2, result.Receive()));
-    ASSERT_EQ(result.get(), checkbox_iaccessible);
+    EXPECT_EQ(S_OK, root_iaccessible->get_accChild(child2, result.Receive()));
+    EXPECT_EQ(result.get(), checkbox_iaccessible);
   }
 
   {
     // Asking for child id 3 should fail.
     ScopedComPtr<IDispatch> result;
     ScopedVariant child3(3);
-    ASSERT_EQ(E_INVALIDARG,
+    EXPECT_EQ(E_INVALIDARG,
               root_iaccessible->get_accChild(child3, result.Receive()));
   }
 
@@ -325,9 +325,9 @@
   {
     ScopedComPtr<IDispatch> result;
     ScopedVariant button_id_variant(button_unique_id);
-    ASSERT_EQ(S_OK, root_iaccessible->get_accChild(button_id_variant,
+    EXPECT_EQ(S_OK, root_iaccessible->get_accChild(button_id_variant,
                                                    result.Receive()));
-    ASSERT_EQ(result.get(), button_iaccessible);
+    EXPECT_EQ(result.get(), button_iaccessible);
   }
 
   // We shouldn't be able to ask for the root node by its unique ID
@@ -340,26 +340,26 @@
   {
     ScopedComPtr<IDispatch> result;
     ScopedVariant root_id_variant(root_unique_id);
-    ASSERT_EQ(E_INVALIDARG, button_iaccessible->get_accChild(root_id_variant,
+    EXPECT_EQ(E_INVALIDARG, button_iaccessible->get_accChild(root_id_variant,
                                                              result.Receive()));
   }
 
   // Now check parents.
   {
     ScopedComPtr<IDispatch> result;
-    ASSERT_EQ(S_OK, button_iaccessible->get_accParent(result.Receive()));
-    ASSERT_EQ(result.get(), root_iaccessible);
+    EXPECT_EQ(S_OK, button_iaccessible->get_accParent(result.Receive()));
+    EXPECT_EQ(result.get(), root_iaccessible);
   }
 
   {
     ScopedComPtr<IDispatch> result;
-    ASSERT_EQ(S_OK, checkbox_iaccessible->get_accParent(result.Receive()));
-    ASSERT_EQ(result.get(), root_iaccessible);
+    EXPECT_EQ(S_OK, checkbox_iaccessible->get_accParent(result.Receive()));
+    EXPECT_EQ(result.get(), root_iaccessible);
   }
 
   {
     ScopedComPtr<IDispatch> result;
-    ASSERT_EQ(S_FALSE, root_iaccessible->get_accParent(result.Receive()));
+    EXPECT_EQ(S_FALSE, root_iaccessible->get_accParent(result.Receive()));
   }
 }
 
@@ -389,13 +389,37 @@
       ToIAccessible2(right_iaccessible);
 
   LONG index;
-  ASSERT_EQ(E_FAIL, root_iaccessible2->get_indexInParent(&index));
+  EXPECT_EQ(E_FAIL, root_iaccessible2->get_indexInParent(&index));
 
-  ASSERT_EQ(S_OK, left_iaccessible2->get_indexInParent(&index));
+  EXPECT_EQ(S_OK, left_iaccessible2->get_indexInParent(&index));
   EXPECT_EQ(0, index);
 
-  ASSERT_EQ(S_OK, right_iaccessible2->get_indexInParent(&index));
+  EXPECT_EQ(S_OK, right_iaccessible2->get_indexInParent(&index));
   EXPECT_EQ(1, index);
 }
 
+TEST_F(AXPlatformNodeWinTest, TestIAccessible2SetSelection) {
+  AXNodeData text_field_node;
+  text_field_node.id = 1;
+  text_field_node.role = ui::AX_ROLE_TEXT_FIELD;
+  text_field_node.state = 1 << ui::AX_STATE_EDITABLE;
+  text_field_node.SetValue("Hi");
+
+  Init(text_field_node);
+  ScopedComPtr<IAccessible2> ia2_text_field =
+      ToIAccessible2(GetRootIAccessible());
+  ScopedComPtr<IAccessibleText> text_field;
+  text_field.QueryFrom(ia2_text_field.get());
+  ASSERT_NE(nullptr, text_field);
+
+  EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 0, 1));
+  EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 1, 0));
+  EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 2, 2));
+  EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, IA2_TEXT_OFFSET_CARET,
+                                                    IA2_TEXT_OFFSET_LENGTH));
+
+  EXPECT_HRESULT_FAILED(text_field->setSelection(1, 0, 0));
+  EXPECT_HRESULT_FAILED(text_field->setSelection(0, 0, 5));
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc
index 2910684..2e9566f 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -119,7 +119,7 @@
 
 bool TestAXNodeWrapper::AccessibilityPerformAction(
     const ui::AXActionData& data) {
-  return false;
+  return true;
 }
 
 void TestAXNodeWrapper::DoDefaultAction() {}
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index bc9223a5..6e5631b 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -65,6 +65,7 @@
     "//ui/display",
     "//ui/gfx",
     "//ui/gfx/geometry",
+    "//url",
   ]
 }
 
diff --git a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java
index 9a9d89b..97c1e48 100644
--- a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java
+++ b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java
@@ -5,6 +5,7 @@
 package org.chromium.ui.base;
 
 import android.content.ClipData;
+import android.content.Intent;
 import android.graphics.Bitmap;
 import android.os.Build;
 import android.view.View;
@@ -13,18 +14,27 @@
 import android.widget.ImageView;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 
+import java.net.URISyntaxException;
+
 /**
  * Class to acquire, position, and remove anchor views from the implementing View.
  */
 @JNINamespace("ui")
 public abstract class ViewAndroidDelegate {
 
+    private static final String TAG = "ViewAndroidDelegate";
+
     // TODO(hush): use View#DRAG_FLAG_GLOBAL when Chromium starts to build with API 24.
     private static final int DRAG_FLAG_GLOBAL = 1 << 8;
 
+    private static final String GEO_SCHEME = "geo";
+    private static final String TEL_SCHEME = "tel";
+    private static final String MAILTO_SCHEME = "mailto";
+
     /**
      * @return An anchor view that can be used to anchor decoration views like Autofill popup.
      */
@@ -105,6 +115,57 @@
     }
 
     /**
+     * Called whenever the background color of the page changes as notified by Blink.
+     * @param color The new ARGB color of the page background.
+     */
+    @CalledByNative
+    public void onBackgroundColorChanged(int color) {}
+
+    /**
+     * Notify the client of the position of the top controls.
+     * @param topControlsOffsetY The Y offset of the top controls in physical pixels.
+     * @param topContentOffsetY The Y offset of the content in physical pixels.
+     */
+    @CalledByNative
+    public void onTopControlsChanged(float topControlsOffsetY, float topContentOffsetY) {}
+
+    /**
+     * Notify the client of the position of the bottom controls.
+     * @param bottomControlsOffsetY The Y offset of the bottom controls in physical pixels.
+     * @param bottomContentOffsetY The Y offset of the content in physical pixels.
+     */
+    @CalledByNative
+    public void onBottomControlsChanged(float bottomControlsOffsetY, float bottomContentOffsetY) {}
+
+    /**
+     * Called when a new content intent is requested to be started.
+     * Invokes {@link #startContentIntent(Intent, String, boolean)} only if the parsed
+     * intent is valid and the scheme is acceptable.
+     */
+    @CalledByNative
+    private void onStartContentIntent(String intentUrl, boolean isMainFrame) {
+        Intent intent;
+        try {
+            intent = Intent.parseUri(intentUrl, Intent.URI_INTENT_SCHEME);
+        } catch (URISyntaxException e) {
+            Log.d(TAG, "Bad URI %s", intentUrl, e);
+            return;
+        }
+        String scheme = intent.getScheme();
+        if (!(GEO_SCHEME.equals(scheme) || TEL_SCHEME.equals(scheme)
+                || MAILTO_SCHEME.equals(scheme))) {
+            Log.d(TAG, "Invalid scheme for URI %s", intentUrl);
+            return;
+        }
+        startContentIntent(intent, intentUrl, isMainFrame);
+    }
+
+    /**
+     * Start a new content intent.
+     */
+    public void startContentIntent(Intent intent, String intentUrl, boolean isMainFrame) {}
+
+    /**
      * @return container view that the anchor views are added to. May be null.
      */
     @CalledByNative
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc
index 43f084f..e1716c14 100644
--- a/ui/android/view_android.cc
+++ b/ui/android/view_android.cc
@@ -7,14 +7,17 @@
 #include <algorithm>
 
 #include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
 #include "cc/layers/layer.h"
 #include "jni/ViewAndroidDelegate_jni.h"
 #include "ui/android/window_android.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "url/gurl.h"
 
 namespace ui {
 
+using base::android::ConvertUTF8ToJavaString;
 using base::android::JavaRef;
 using base::android::ScopedJavaLocalRef;
 
@@ -215,7 +218,9 @@
   if (delegate.is_null())
     return false;
   JNIEnv* env = base::android::AttachCurrentThread();
-  return Java_ViewAndroidDelegate_startDragAndDrop(env, delegate, jtext,
+  return Java_ViewAndroidDelegate_startDragAndDrop(env,
+                                                   delegate,
+                                                   jtext,
                                                    jimage);
 }
 
@@ -241,4 +246,52 @@
   return false;
 }
 
+void ViewAndroid::OnBackgroundColorChanged(unsigned int color) {
+  ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
+  if (delegate.is_null())
+    return;
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_ViewAndroidDelegate_onBackgroundColorChanged(env,
+                                                    delegate,
+                                                    color);
+}
+
+void ViewAndroid::OnTopControlsChanged(float top_controls_offset,
+                                       float top_content_offset) {
+  ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
+  if (delegate.is_null())
+    return;
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_ViewAndroidDelegate_onTopControlsChanged(env,
+                                                delegate,
+                                                top_controls_offset,
+                                                top_content_offset);
+}
+
+void ViewAndroid::OnBottomControlsChanged(float bottom_controls_offset,
+                                          float bottom_content_offset) {
+  ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
+  if (delegate.is_null())
+    return;
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_ViewAndroidDelegate_onBottomControlsChanged(env,
+                                                   delegate,
+                                                   bottom_controls_offset,
+                                                   bottom_content_offset);
+}
+
+void ViewAndroid::StartContentIntent(const GURL& content_url,
+                                       bool is_main_frame) {
+  ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
+  if (delegate.is_null())
+    return;
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> jcontent_url =
+      ConvertUTF8ToJavaString(env, content_url.spec());
+  Java_ViewAndroidDelegate_onStartContentIntent(env,
+                                                delegate,
+                                                jcontent_url,
+                                                is_main_frame);
+
+}
 }  // namespace ui
diff --git a/ui/android/view_android.h b/ui/android/view_android.h
index e446048..22780e6b 100644
--- a/ui/android/view_android.h
+++ b/ui/android/view_android.h
@@ -13,6 +13,8 @@
 #include "ui/android/view_client.h"
 #include "ui/gfx/geometry/rect_f.h"
 
+class GURL;
+
 namespace cc {
 class Layer;
 }
@@ -102,6 +104,14 @@
   bool StartDragAndDrop(const base::android::JavaRef<jstring>& jtext,
                         const base::android::JavaRef<jobject>& jimage);
 
+  void OnBackgroundColorChanged(unsigned int color);
+  void OnTopControlsChanged(float top_controls_offset,
+                            float top_content_offset);
+  void OnBottomControlsChanged(float bottom_controls_offset,
+                               float bottom_content_offset);
+  void StartContentIntent(const GURL& content_url,
+                          bool is_main_frame);
+
   ScopedAnchorView AcquireAnchorView();
   void SetAnchorRect(const base::android::JavaRef<jobject>& anchor,
                      const gfx::RectF& bounds);
diff --git a/ui/app_list/PRESUBMIT.py b/ui/app_list/PRESUBMIT.py
index e788678..eda670bc 100644
--- a/ui/app_list/PRESUBMIT.py
+++ b/ui/app_list/PRESUBMIT.py
@@ -23,5 +23,4 @@
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results += CheckChangeLintsClean(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
diff --git a/ui/base/cocoa/nsgraphics_context_additions.mm b/ui/base/cocoa/nsgraphics_context_additions.mm
index 9e85fad2..c29a762 100644
--- a/ui/base/cocoa/nsgraphics_context_additions.mm
+++ b/ui/base/cocoa/nsgraphics_context_additions.mm
@@ -4,10 +4,27 @@
 
 #import "ui/base/cocoa/nsgraphics_context_additions.h"
 
+#include "base/logging.h"
+
 @implementation NSGraphicsContext (CrAdditions)
 
 - (void)cr_setPatternPhase:(NSPoint)phase
                    forView:(NSView*)view {
+  // TODO(sdy): Remove once we no longer add the tab background view to
+  // [[window contentView] superview] *or* no longer make the content view
+  // smaller than the window while exiting fullscreen. These two things
+  // together can result in the tab background view being drawn while it's
+  // outside of contentView, with a pattern phase that assumes it's inside.
+  NSView* contentView = [[view window] contentView];
+  if (![view isDescendantOf:contentView]) {
+    NSView* frameView = [contentView superview];
+    DCHECK([view isDescendantOf:frameView]);
+    // Convert phase into an offset from the top left corner of contentView so
+    // that it will be aligned correctly at the end of the transition.
+    phase.x += NSMinX([frameView frame]) - NSMinX([contentView frame]);
+    phase.y += NSMaxY([frameView frame]) - NSMaxY([contentView frame]);
+  }
+
   NSView* ancestorWithLayer = view;
   while (ancestorWithLayer && ![ancestorWithLayer layer])
     ancestorWithLayer = [ancestorWithLayer superview];
diff --git a/ui/chromeos/PRESUBMIT.py b/ui/chromeos/PRESUBMIT.py
deleted file mode 100644
index 64582bf0..0000000
--- a/ui/chromeos/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 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.
-
-"""Presubmit script for chromeos.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 378a09e..9170fa2d 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -820,8 +820,9 @@
     delegate_->OnDelegatedFrameDamage(damage_rect_in_dip);
 }
 
-void Layer::SetScrollable(Layer* parent_clip_layer,
-                          const base::Closure& on_scroll) {
+void Layer::SetScrollable(
+    Layer* parent_clip_layer,
+    const base::Callback<void(const gfx::ScrollOffset&)>& on_scroll) {
   cc_layer_->SetScrollClipLayerId(parent_clip_layer->cc_layer_->id());
   cc_layer_->set_did_scroll_callback(on_scroll);
   cc_layer_->SetUserScrollable(true, true);
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index e1525b5..76451c0a 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -349,7 +349,9 @@
 
   // Makes this Layer scrollable, clipping to |parent_clip_layer|. |on_scroll|
   // is invoked when scrolling performed by the cc::InputHandler is committed.
-  void SetScrollable(Layer* parent_clip_layer, const base::Closure& on_scroll);
+  void SetScrollable(
+      Layer* parent_clip_layer,
+      const base::Callback<void(const gfx::ScrollOffset&)>& on_scroll);
 
   // Gets and sets the current scroll offset of the layer.
   gfx::ScrollOffset CurrentScrollOffset() const;
diff --git a/ui/file_manager/image_loader/piex_loader.js b/ui/file_manager/image_loader/piex_loader.js
index e506e3a4..d4bb42e 100644
--- a/ui/file_manager/image_loader/piex_loader.js
+++ b/ui/file_manager/image_loader/piex_loader.js
@@ -65,14 +65,14 @@
   this.naclModule_ = document.createElement('embed');
 
   /**
-   * @private {!Promise}
+   * @private {!Promise<boolean>}
    * @const
    */
   this.naclPromise_ = new Promise(function(fulfill) {
     chrome.fileManagerPrivate.isPiexLoaderEnabled(fulfill);
   }).then(function(enabled) {
     if (!enabled)
-      return Promise.reject('PiexLoader is not enabled for chromium build.');
+      return false;
     return new Promise(function(fulfill, reject) {
       var embed = this.naclModule_;
       embed.setAttribute('type', 'application/x-pnacl');
@@ -88,7 +88,8 @@
       // 'load' event fires.
       var listenerContainer = document.createElement('div');
       listenerContainer.appendChild(embed);
-      listenerContainer.addEventListener('load', fulfill, true);
+      listenerContainer.addEventListener(
+          'load', fulfill.bind(null, true), true);
       listenerContainer.addEventListener(
           'message', this.onMessage_.bind(this), true);
       listenerContainer.addEventListener('error', function() {
@@ -100,7 +101,10 @@
       listenerContainer.style.height = '0px';
       document.body.appendChild(listenerContainer);
     }.bind(this));
-  }.bind(this));
+  }.bind(this)).catch(function (error) {
+    console.error(error);
+    return false;
+  });
 
   /**
    * @private {!Object<number, PiexRequestCallbacks>}
@@ -135,7 +139,9 @@
  * @return {!Promise<!PiexLoaderResponse>}
  */
 PiexLoader.prototype.load = function(url) {
-  return this.naclPromise_.then(function() {
+  return this.naclPromise_.then(function(loaded) {
+    if (!loaded)
+      return Promise.reject('Piex is not loaded');
     var message = {
       id: this.requestIdCount_++,
       name: 'loadThumbnail',
@@ -144,6 +150,9 @@
     this.naclModule_.postMessage(message);
     return new Promise(function(fulfill, reject) {
       this.requests_[message.id] = {fulfill: fulfill, reject: reject};
-    }.bind(this));
+    }.bind(this)).catch(function(error) {
+      console.error('PiexLoaderError: ', error);
+      return Promise.reject(error);
+    });
   }.bind(this));
 };
diff --git a/ui/file_manager/image_loader/request.js b/ui/file_manager/image_loader/request.js
index 0f55e1a..af197cb 100644
--- a/ui/file_manager/image_loader/request.js
+++ b/ui/file_manager/image_loader/request.js
@@ -261,8 +261,8 @@
       this.image_.src = url;
       this.request_.orientation = data.orientation;
       this.request_.colorSpace = data.colorSpace;
-    }.bind(this), function(error) {
-      console.error('PiexLoaderError: ', error);
+    }.bind(this), function() {
+      // The error has already been logged in PiexLoader.
       onFailure();
     });
     return;
diff --git a/ui/ozone/PRESUBMIT.py b/ui/ozone/PRESUBMIT.py
deleted file mode 100644
index 6b822c9..0000000
--- a/ui/ozone/PRESUBMIT.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2014 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.
-
-"""Presubmit script for ozone.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details about the presubmit API built into depot_tools.
-"""
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
index 8d80aa9..528569f 100644
--- a/ui/ozone/platform/wayland/BUILD.gn
+++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -50,6 +50,7 @@
     "//ui/base:ui_features",
     "//ui/display",
     "//ui/events",
+    "//ui/events:dom_keycode_converter",
     "//ui/events/ozone:events_ozone_layout",
     "//ui/events/platform",
     "//ui/gfx",
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index 6db5b67..09bb43d 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -104,6 +104,12 @@
     surface_factory_ozone_.reset(new X11SurfaceFactory());
   }
 
+  base::MessageLoop::Type GetMessageLoopTypeForGpu() override {
+    // When Ozone X11 backend is running use an UI loop to grab Expose events.
+    // See GLSurfaceGLX and https://crbug.com/326995.
+    return base::MessageLoop::TYPE_UI;
+  }
+
  private:
   // Objects in the browser process.
   std::unique_ptr<X11WindowManagerOzone> window_manager_;
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc
index 6f25a1b1..b723460a 100644
--- a/ui/ozone/public/ozone_platform.cc
+++ b/ui/ozone/public/ozone_platform.cc
@@ -40,7 +40,7 @@
 
 // static
 void OzonePlatform::InitializeForUI(const InitParams& args) {
-  CreateInstance();
+  EnsureInstance();
   if (g_platform_initialized_ui)
     return;
   g_platform_initialized_ui = true;
@@ -58,7 +58,7 @@
 
 // static
 void OzonePlatform::InitializeForGPU(const InitParams& args) {
-  CreateInstance();
+  EnsureInstance();
   if (g_platform_initialized_gpu)
     return;
   g_platform_initialized_gpu = true;
@@ -72,7 +72,7 @@
 }
 
 // static
-void OzonePlatform::CreateInstance() {
+OzonePlatform* OzonePlatform::EnsureInstance() {
   if (!instance_) {
     TRACE_EVENT1("ozone",
                  "OzonePlatform::Initialize",
@@ -85,6 +85,7 @@
     OzonePlatform* pl = platform.release();
     DCHECK_EQ(instance_, pl);
   }
+  return instance_;
 }
 
 // static
@@ -94,6 +95,7 @@
 void OzonePlatform::InitializeUI(const InitParams& args) {
   InitializeUI();
 }
+
 void OzonePlatform::InitializeGPU(const InitParams& args) {
   InitializeGPU();
 }
@@ -101,6 +103,11 @@
 IPC::MessageFilter* OzonePlatform::GetGpuMessageFilter() {
   return nullptr;
 }
+
+base::MessageLoop::Type OzonePlatform::GetMessageLoopTypeForGpu() {
+  return base::MessageLoop::TYPE_DEFAULT;
+}
+
 void OzonePlatform::AddInterfaces(
     service_manager::InterfaceRegistry* registry) {}
 
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index 236924f..f1995c1 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "ui/ozone/ozone_export.h"
 
 namespace display {
@@ -71,6 +72,12 @@
     bool single_process = false;
   };
 
+  // Ensures the OzonePlatform instance without doing any initialization.
+  // No-op in case the instance is already created.
+  // This is useful in order call virtual methods that depend on the ozone
+  // platform selected at runtime, e.g. ::GetMessageLoopTypeForGpu.
+  static OzonePlatform* EnsureInstance();
+
   // Initializes the subsystems/resources necessary for the UI process (e.g.
   // events, etc.)
   // TODO(rjkroege): Remove deprecated entry point (http://crbug.com/620934)
@@ -108,6 +115,10 @@
   virtual std::unique_ptr<display::NativeDisplayDelegate>
   CreateNativeDisplayDelegate() = 0;
 
+  // Returns the message loop type required for OzonePlatform instance that
+  // will be initialized for the GPU process.
+  virtual base::MessageLoop::Type GetMessageLoopTypeForGpu();
+
   // Ozone platform implementations may also choose to expose mojo interfaces to
   // internal functionality. Embedders wishing to take advantage of ozone mojo
   // implementations must invoke AddInterfaces with a valid
@@ -124,8 +135,6 @@
   virtual void InitializeUI(const InitParams& args);
   virtual void InitializeGPU(const InitParams& args);
 
-  static void CreateInstance();
-
   static OzonePlatform* instance_;
 
   DISALLOW_COPY_AND_ASSIGN(OzonePlatform);
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 4183b1a0..37db59d 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -433,12 +433,6 @@
   } else {
     showing_ = true;
 
-    // TODO(jonross): remove after tracking down the cause of
-    // (crbug.com/683087).
-    // If we are not showing we should be shutting down, this could lead to
-    // incorrect delegate states.
-    CHECK(!running_);
-
     if (owner_)
       owner_->RemoveObserver(this);
     owner_ = parent;
@@ -476,10 +470,6 @@
   if (ViewsDelegate::GetInstance())
     ViewsDelegate::GetInstance()->AddRef();
 
-  // TODO(jonross): remove after tracking down the cause of (crbug.com/683087).
-  // About to either exit and run async, or nest message loop.
-  running_ = true;
-
   if (async_run_)
     return nullptr;
 
@@ -529,11 +519,6 @@
   SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
 
   if (!blocking_run_) {
-    // TODO(jonross): remove after tracking down the cause of
-    // (crbug.com/683087).
-    bool nested = delegate_stack_.size() > 1;
-    CHECK(!nested);
-    base::WeakPtr<MenuController> this_ref = AsWeakPtr();
     // If we didn't block the caller we need to notify the menu, which
     // triggers deleting us.
     DCHECK(selected);
@@ -541,7 +526,6 @@
     delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
                             selected->GetRootMenuItem(), accept_event_flags_);
     // WARNING: the call to MenuClosed deletes us.
-    CHECK(!this_ref);
     return;
   }
 
@@ -564,12 +548,6 @@
 
 void MenuController::AddNestedDelegate(
     internal::MenuControllerDelegate* delegate) {
-  // TODO(jonross): remove after tracking down the cause of (crbug.com/683087).
-  for (auto delegates : delegate_stack_) {
-    // Having the same delegate in the stack could cause deletion order issues.
-    CHECK_NE(delegates.first, delegate);
-  }
-
   delegate_stack_.push_back(std::make_pair(delegate, async_run_));
   delegate_ = delegate;
 }
@@ -1005,13 +983,9 @@
     drop_target = drop_target->GetParentMenuItem();
 
   if (!IsBlockingRun()) {
-    // TODO(jonross): remove after tracking down the cause of
-    // (crbug.com/683087).
-    base::WeakPtr<MenuController> this_ref = AsWeakPtr();
     delegate_->OnMenuClosed(
         internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE,
         item->GetRootMenuItem(), accept_event_flags_);
-    CHECK(!this_ref);
   }
 
   // WARNING: the call to MenuClosed deletes us.
@@ -1410,7 +1384,6 @@
                                internal::MenuControllerDelegate* delegate)
     : blocking_run_(blocking),
       showing_(false),
-      running_(false),
       exit_type_(EXIT_NONE),
       did_capture_(false),
       result_(NULL),
@@ -2689,9 +2662,6 @@
 
     showing_ = false;
     did_capture_ = false;
-    // TODO(jonross): remove after tracking down the cause of
-    // (crbug.com/683087).
-    running_ = false;
   }
 
   MenuItemView* result = result_;
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h
index d3a4177..697e9a5 100644
--- a/ui/views/controls/menu/menu_controller.h
+++ b/ui/views/controls/menu/menu_controller.h
@@ -574,11 +574,6 @@
   // If true, we're showing.
   bool showing_;
 
-  // TODO(jonross): remove after tracking down the cause of (crbug.com/683087).
-  // If true running has began and there are still delegates which have not been
-  // closed. We may not be showing.
-  bool running_;
-
   // Indicates what to exit.
   ExitType exit_type_;
 
diff --git a/ui/views/controls/menu/menu_runner_impl.cc b/ui/views/controls/menu/menu_runner_impl.cc
index 0bb9486..a247d512 100644
--- a/ui/views/controls/menu/menu_runner_impl.cc
+++ b/ui/views/controls/menu/menu_runner_impl.cc
@@ -69,15 +69,9 @@
       controller_->Cancel(MenuController::EXIT_DESTROYED);
       return;
     }
-
-    // TODO(jonross): remove after tracking down the cause of
-    // (crbug.com/683087).
-    // Update for the ASAN stack trace to determine if we are in the running
-    // state during the incorrect destruction order.
-    delete this;
-  } else {
-    delete this;
   }
+
+  delete this;
 }
 
 MenuRunner::RunResult MenuRunnerImpl::RunMenuAt(Widget* parent,
@@ -92,12 +86,6 @@
     return MenuRunner::NORMAL_EXIT;
   }
 
-  // TODO(jonross): remove after tracking down the cause of (crbug.com/683087).
-  // Verify that this was not a delegate previously used for a run, which was
-  // shutdown, but not deleted. Nesting the same delegate multiple times is
-  // dangerous.
-  CHECK(!controller_);
-
   MenuController* controller = MenuController::GetActiveInstance();
   if (controller) {
     if ((run_types & MenuRunner::IS_NESTED) != 0) {
@@ -133,8 +121,6 @@
   if (!controller) {
     // No menus are showing, show one.
     controller = new MenuController(!for_drop_, this);
-    // TODO(jonross): remove after tracking down the cause of
-    // (crbug.com/683087).
     owns_controller_ = true;
   }
   controller->SetAsyncRun(async_);
@@ -204,9 +190,8 @@
     // We created the controller and need to delete it.
     delete controller_.get();
     owns_controller_ = false;
-    controller_ = nullptr;
   }
-
+  controller_ = nullptr;
   // Make sure all the windows we created to show the menus have been
   // destroyed.
   menu_->DestroyAllMenuHosts();
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc
index 9440e34..f457cb7c 100644
--- a/ui/views/controls/scroll_view.cc
+++ b/ui/views/controls/scroll_view.cc
@@ -699,7 +699,7 @@
     // but will only be invoked (asynchronously) when a Compositor is present
     // and commits a frame, which isn't true in some tests.
     // See http://crbug.com/637521.
-    OnLayerScrolled();
+    OnLayerScrolled(offset);
   } else {
     contents_->SetPosition(gfx::Point(-offset.x(), -offset.y()));
     ScrollHeader();
@@ -720,7 +720,7 @@
   contents_viewport_->layer()->SetMasksToBounds(true);
 }
 
-void ScrollView::OnLayerScrolled() {
+void ScrollView::OnLayerScrolled(const gfx::ScrollOffset&) {
   UpdateScrollBarPositions();
   ScrollHeader();
 }
diff --git a/ui/views/controls/scroll_view.h b/ui/views/controls/scroll_view.h
index 6dc4393..db38b2c8 100644
--- a/ui/views/controls/scroll_view.h
+++ b/ui/views/controls/scroll_view.h
@@ -149,7 +149,7 @@
   bool ScrollsWithLayers() const;
 
   // Callback entrypoint when hosted Layers are scrolled by the Compositor.
-  void OnLayerScrolled();
+  void OnLayerScrolled(const gfx::ScrollOffset& offset);
 
   // Horizontally scrolls the header (if any) to match the contents.
   void ScrollHeader();
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 529da58..15df149 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -902,6 +902,15 @@
 }
 
 bool Textfield::HandleAccessibleAction(const ui::AXActionData& action_data) {
+  if (action_data.action == ui::AX_ACTION_SET_SELECTION) {
+    if (action_data.anchor_node_id != action_data.focus_node_id)
+      return false;
+    // TODO(nektar): Check that the focus_node_id matches the ID of this node.
+    const gfx::Range range(action_data.anchor_offset, action_data.focus_offset);
+    return SetSelectionRange(range);
+  }
+
+  // Remaining actions cannot be performed on readonly fields.
   if (read_only())
     return View::HandleAccessibleAction(action_data);
 
@@ -1909,11 +1918,7 @@
       StartBlinkingCursor();
     else
       StopBlinkingCursor();
-    if (!text_changed) {
-      // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire
-      // this if only the selection changed.
-      NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true);
-    }
+    NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true);
   }
   if (text_changed || cursor_changed) {
     OnCaretBoundsChanged();
diff --git a/ui/webui/resources/PRESUBMIT.py b/ui/webui/resources/PRESUBMIT.py
index 7a7e28b..b05b5b55 100644
--- a/ui/webui/resources/PRESUBMIT.py
+++ b/ui/webui/resources/PRESUBMIT.py
@@ -75,6 +75,4 @@
 def _CommonChecks(input_api, output_api):
   results = []
   results += _CheckForTranslations(input_api, output_api)
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
-                                                         check_js=True)
   return results
diff --git a/url/gurl.cc b/url/gurl.cc
index 041001a..f521692f9 100644
--- a/url/gurl.cc
+++ b/url/gurl.cc
@@ -468,6 +468,14 @@
   return url::DomainIs(host_piece(), lower_ascii_domain);
 }
 
+bool GURL::EqualsIgnoringRef(const GURL& other) const {
+  int ref_position = parsed_.CountCharactersBefore(url::Parsed::REF, true);
+  int ref_position_other =
+      other.parsed_.CountCharactersBefore(url::Parsed::REF, true);
+  return base::StringPiece(spec_).substr(0, ref_position) ==
+         base::StringPiece(other.spec_).substr(0, ref_position_other);
+}
+
 void GURL::Swap(GURL* other) {
   spec_.swap(other->spec_);
   std::swap(is_valid_, other->is_valid_);
diff --git a/url/gurl.h b/url/gurl.h
index 175cb60..d7d575b 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -385,6 +385,10 @@
   // object constructions are done.
   bool DomainIs(base::StringPiece lower_ascii_domain) const;
 
+  // Checks whether or not two URLs are differing only in the ref (the part
+  // after the # character).
+  bool EqualsIgnoringRef(const GURL& other) const;
+
   // Swaps the contents of this GURL object with |other|, without doing
   // any memory allocations.
   void Swap(GURL* other);
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc
index a3b61fff..e51b0241 100644
--- a/url/url_util_unittest.cc
+++ b/url/url_util_unittest.cc
@@ -433,4 +433,62 @@
     EXPECT_FALSE(IsAboutBlank(GURL(url)));
 }
 
+TEST(URLUtilTest, EqualsIgnoringRef) {
+  const struct {
+    const char* url_a;
+    const char* url_b;
+    bool are_equals;
+  } kTestCases[] = {
+      // No ref.
+      {"http://a.com", "http://a.com", true},
+      {"http://a.com", "http://b.com", false},
+
+      // Same Ref.
+      {"http://a.com#foo", "http://a.com#foo", true},
+      {"http://a.com#foo", "http://b.com#foo", false},
+
+      // Different Refs.
+      {"http://a.com#foo", "http://a.com#bar", true},
+      {"http://a.com#foo", "http://b.com#bar", false},
+
+      // One has a ref, the other doesn't.
+      {"http://a.com#foo", "http://a.com", true},
+      {"http://a.com#foo", "http://b.com", false},
+
+      // Empty refs.
+      {"http://a.com#", "http://a.com#", true},
+      {"http://a.com#", "http://a.com", true},
+
+      // URLs that differ only by their last character.
+      {"http://aaa", "http://aab", false},
+      {"http://aaa#foo", "http://aab#foo", false},
+
+      // Different size of the part before the ref.
+      {"http://123#a", "http://123456#a", false},
+
+      // Blob URLs
+      {"blob:http://a.com#foo", "blob:http://a.com#foo", true},
+      {"blob:http://a.com#foo", "blob:http://a.com#bar", true},
+      {"blob:http://a.com#foo", "blob:http://b.com#bar", false},
+
+      // Filesystem URLs
+      {"filesystem:http://a.com#foo", "filesystem:http://a.com#foo", true},
+      {"filesystem:http://a.com#foo", "filesystem:http://a.com#bar", true},
+      {"filesystem:http://a.com#foo", "filesystem:http://b.com#bar", false},
+  };
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(testing::Message()
+                 << std::endl
+                 << "url_a = " << test_case.url_a << std::endl
+                 << "url_b = " << test_case.url_b << std::endl);
+    // A versus B.
+    EXPECT_EQ(test_case.are_equals,
+              GURL(test_case.url_a).EqualsIgnoringRef(GURL(test_case.url_b)));
+    // B versus A.
+    EXPECT_EQ(test_case.are_equals,
+              GURL(test_case.url_b).EqualsIgnoringRef(GURL(test_case.url_a)));
+  }
+}
+
 }  // namespace url